From 569672027cee12a8eb9221861b6aa073dbfca3f7 Mon Sep 17 00:00:00 2001 From: Alex Donesky Date: Wed, 27 Jan 2021 10:43:28 -0600 Subject: [PATCH 01/48] Allow editing transaction amount after clicking max (#10278) --- test/e2e/metamask-ui.spec.js | 2 -- .../currency-input.component.js | 4 +--- .../currency-input.container.js | 8 +------ .../tests/currency-input.container.test.js | 16 ------------- .../ui/unit-input/unit-input.component.js | 23 ++++--------------- 5 files changed, 6 insertions(+), 47 deletions(-) diff --git a/test/e2e/metamask-ui.spec.js b/test/e2e/metamask-ui.spec.js index f7a558ba9..561ad737a 100644 --- a/test/e2e/metamask-ui.spec.js +++ b/test/e2e/metamask-ui.spec.js @@ -308,8 +308,6 @@ describe('MetaMask', function () { ) await amountMax.click() - assert.equal(await inputAmount.isEnabled(), false) - let inputValue = await inputAmount.getAttribute('value') assert(Number(inputValue) > 99) diff --git a/ui/app/components/ui/currency-input/currency-input.component.js b/ui/app/components/ui/currency-input/currency-input.component.js index 5fc3b991d..0186051de 100644 --- a/ui/app/components/ui/currency-input/currency-input.component.js +++ b/ui/app/components/ui/currency-input/currency-input.component.js @@ -21,7 +21,6 @@ export default class CurrencyInput extends PureComponent { static propTypes = { conversionRate: PropTypes.number, currentCurrency: PropTypes.string, - maxModeOn: PropTypes.bool, nativeCurrency: PropTypes.string, onChange: PropTypes.func, useFiat: PropTypes.bool, @@ -153,7 +152,7 @@ export default class CurrencyInput extends PureComponent { } render() { - const { fiatSuffix, nativeSuffix, maxModeOn, ...restProps } = this.props + const { fiatSuffix, nativeSuffix, ...restProps } = this.props const { decimalValue } = this.state return ( @@ -162,7 +161,6 @@ export default class CurrencyInput extends PureComponent { suffix={this.shouldUseFiat() ? fiatSuffix : nativeSuffix} onChange={this.handleChange} value={decimalValue} - maxModeOn={maxModeOn} actionComponent={
} diff --git a/ui/app/components/ui/currency-input/currency-input.container.js b/ui/app/components/ui/currency-input/currency-input.container.js index 3a5719929..e402a3def 100644 --- a/ui/app/components/ui/currency-input/currency-input.container.js +++ b/ui/app/components/ui/currency-input/currency-input.container.js @@ -1,10 +1,6 @@ import { connect } from 'react-redux' import { ETH } from '../../../helpers/constants/common' -import { - getSendMaxModeState, - getIsMainnet, - getPreferences, -} from '../../../selectors' +import { getIsMainnet, getPreferences } from '../../../selectors' import CurrencyInput from './currency-input.component' const mapStateToProps = (state) => { @@ -13,14 +9,12 @@ const mapStateToProps = (state) => { } = state const { showFiatInTestnets } = getPreferences(state) const isMainnet = getIsMainnet(state) - const maxModeOn = getSendMaxModeState(state) return { nativeCurrency, currentCurrency, conversionRate, hideFiat: !isMainnet && !showFiatInTestnets, - maxModeOn, } } diff --git a/ui/app/components/ui/currency-input/tests/currency-input.container.test.js b/ui/app/components/ui/currency-input/tests/currency-input.container.test.js index 1ce9eb559..630e4cdc6 100644 --- a/ui/app/components/ui/currency-input/tests/currency-input.container.test.js +++ b/ui/app/components/ui/currency-input/tests/currency-input.container.test.js @@ -30,9 +30,6 @@ describe('CurrencyInput container', function () { provider: { type: 'mainnet', }, - send: { - maxModeOn: false, - }, }, }, expected: { @@ -40,7 +37,6 @@ describe('CurrencyInput container', function () { currentCurrency: 'usd', nativeCurrency: 'ETH', hideFiat: false, - maxModeOn: false, }, }, // Test # 2 @@ -58,9 +54,6 @@ describe('CurrencyInput container', function () { provider: { type: 'rinkeby', }, - send: { - maxModeOn: false, - }, }, }, expected: { @@ -68,7 +61,6 @@ describe('CurrencyInput container', function () { currentCurrency: 'usd', nativeCurrency: 'ETH', hideFiat: true, - maxModeOn: false, }, }, // Test # 3 @@ -86,9 +78,6 @@ describe('CurrencyInput container', function () { provider: { type: 'rinkeby', }, - send: { - maxModeOn: false, - }, }, }, expected: { @@ -96,7 +85,6 @@ describe('CurrencyInput container', function () { currentCurrency: 'usd', nativeCurrency: 'ETH', hideFiat: false, - maxModeOn: false, }, }, // Test # 4 @@ -114,9 +102,6 @@ describe('CurrencyInput container', function () { provider: { type: 'mainnet', }, - send: { - maxModeOn: false, - }, }, }, expected: { @@ -124,7 +109,6 @@ describe('CurrencyInput container', function () { currentCurrency: 'usd', nativeCurrency: 'ETH', hideFiat: false, - maxModeOn: false, }, }, ] diff --git a/ui/app/components/ui/unit-input/unit-input.component.js b/ui/app/components/ui/unit-input/unit-input.component.js index 7e084a3bb..8155e242b 100644 --- a/ui/app/components/ui/unit-input/unit-input.component.js +++ b/ui/app/components/ui/unit-input/unit-input.component.js @@ -13,7 +13,6 @@ export default class UnitInput extends PureComponent { children: PropTypes.node, actionComponent: PropTypes.node, error: PropTypes.bool, - maxModeOn: PropTypes.bool, onChange: PropTypes.func, placeholder: PropTypes.string, suffix: PropTypes.string, @@ -63,33 +62,20 @@ export default class UnitInput extends PureComponent { } render() { - const { - error, - placeholder, - suffix, - actionComponent, - children, - maxModeOn, - } = this.props + const { error, placeholder, suffix, actionComponent, children } = this.props const { value } = this.state return (
{ this.unitInput = ref }} - disabled={maxModeOn} /> {suffix &&
{suffix}
}
From 3806e0a2a665522bf08bd09010add8a8fcce6ff4 Mon Sep 17 00:00:00 2001 From: Brad Decker Date: Wed, 27 Jan 2021 10:51:59 -0600 Subject: [PATCH 02/48] Refactor NetworkDisplay, ConnectedStatusIndicator, etc to use ColorIndicator (#10214) --- test/e2e/ethereum-on.spec.js | 2 +- test/e2e/from-import-ui.spec.js | 2 +- test/e2e/metamask-responsive-ui.spec.js | 6 +- test/e2e/metamask-ui.spec.js | 8 +- .../app/app-header/app-header.component.js | 19 +- ui/app/components/app/app-header/index.scss | 13 +- .../app/app-header/tests/app-header.test.js | 5 +- .../confirm-page-container-header/index.scss | 5 + .../connected-status-indicator.component.js | 71 ------- .../connected-status-indicator.container.js | 39 ---- .../connected-status-indicator.js | 66 ++++++ .../app/connected-status-indicator/index.js | 2 +- .../app/dropdowns/components/dropdown.js | 7 + .../components/network-dropdown-icon.js | 48 ----- .../app/dropdowns/network-dropdown.js | 194 ++++++------------ .../tests/network-dropdown-icon.test.js | 22 -- .../dropdowns/tests/network-dropdown.test.js | 57 +++-- .../components/app/network-display/index.js | 4 +- .../components/app/network-display/index.scss | 104 +++++----- .../network-display.component.js | 71 ------- .../network-display.container.js | 15 -- .../app/network-display/network-display.js | 78 +++++++ ui/app/components/app/network.js | 192 ----------------- .../app/permission-page-container/index.js | 1 - .../permission-page-container-header/index.js | 1 - ...mission-page-container-header.component.js | 12 -- .../app/signature-request/index.scss | 10 +- ui/app/components/ui/chip/chip.js | 7 + .../components/ui/loading-indicator/index.js | 1 + .../ui/loading-indicator/loading-indicator.js | 29 +++ .../loading-indicator/loading-indicator.scss | 17 ++ ui/app/components/ui/ui-components.scss | 1 + ui/app/css/itcss/components/network.scss | 40 +--- ui/app/pages/settings/networks-tab/index.scss | 3 +- .../networks-tab/networks-tab.component.js | 20 +- 35 files changed, 396 insertions(+), 776 deletions(-) delete mode 100644 ui/app/components/app/connected-status-indicator/connected-status-indicator.component.js delete mode 100644 ui/app/components/app/connected-status-indicator/connected-status-indicator.container.js create mode 100644 ui/app/components/app/connected-status-indicator/connected-status-indicator.js delete mode 100644 ui/app/components/app/dropdowns/components/network-dropdown-icon.js delete mode 100644 ui/app/components/app/dropdowns/tests/network-dropdown-icon.test.js delete mode 100644 ui/app/components/app/network-display/network-display.component.js delete mode 100644 ui/app/components/app/network-display/network-display.container.js create mode 100644 ui/app/components/app/network-display/network-display.js delete mode 100644 ui/app/components/app/network.js delete mode 100644 ui/app/components/app/permission-page-container/permission-page-container-header/index.js delete mode 100644 ui/app/components/app/permission-page-container/permission-page-container-header/permission-page-container-header.component.js create mode 100644 ui/app/components/ui/loading-indicator/index.js create mode 100644 ui/app/components/ui/loading-indicator/loading-indicator.js create mode 100644 ui/app/components/ui/loading-indicator/loading-indicator.scss diff --git a/test/e2e/ethereum-on.spec.js b/test/e2e/ethereum-on.spec.js index 81f178c9d..52485d76a 100644 --- a/test/e2e/ethereum-on.spec.js +++ b/test/e2e/ethereum-on.spec.js @@ -171,7 +171,7 @@ describe('MetaMask', function () { it('changes the network', async function () { await driver.switchToWindow(extension) - await driver.clickElement(By.css('.network-name')) + await driver.clickElement(By.css('.network-display')) await driver.delay(regularDelayMs) await driver.clickElement(By.xpath(`//span[contains(text(), 'Ropsten')]`)) diff --git a/test/e2e/from-import-ui.spec.js b/test/e2e/from-import-ui.spec.js index dc5457f7d..8dbabbcac 100644 --- a/test/e2e/from-import-ui.spec.js +++ b/test/e2e/from-import-ui.spec.js @@ -177,7 +177,7 @@ describe('Using MetaMask with an existing account', function () { describe('Add an account', function () { it('switches to localhost', async function () { - await driver.clickElement(By.css('.network-name')) + await driver.clickElement(By.css('.network-display')) await driver.delay(regularDelayMs) await driver.clickElement( diff --git a/test/e2e/metamask-responsive-ui.spec.js b/test/e2e/metamask-responsive-ui.spec.js index 1474960ef..60fe1c901 100644 --- a/test/e2e/metamask-responsive-ui.spec.js +++ b/test/e2e/metamask-responsive-ui.spec.js @@ -205,11 +205,13 @@ describe('MetaMask', function () { }) it('switches to localhost', async function () { - await driver.clickElement(By.css('.network-name')) + await driver.clickElement(By.css('.network-display')) await driver.delay(regularDelayMs) await driver.clickElement( - By.xpath(`//span[contains(text(), 'Localhost')]`), + By.xpath( + `//span[contains(@class, 'network-name-item') and contains(text(), 'Localhost 8545')]`, + ), ) await driver.delay(largeDelayMs * 2) }) diff --git a/test/e2e/metamask-ui.spec.js b/test/e2e/metamask-ui.spec.js index 561ad737a..52819a7ac 100644 --- a/test/e2e/metamask-ui.spec.js +++ b/test/e2e/metamask-ui.spec.js @@ -1723,7 +1723,7 @@ describe('MetaMask', function () { const rpcUrl = 'http://127.0.0.1:8545/1' const chainId = '0x539' // Ganache default, decimal 1337 - await driver.clickElement(By.css('.network-name')) + await driver.clickElement(By.css('.network-display')) await driver.delay(regularDelayMs) await driver.clickElement( @@ -1753,7 +1753,7 @@ describe('MetaMask', function () { const rpcUrl = 'http://127.0.0.1:8545/2' const chainId = '0x539' // Ganache default, decimal 1337 - await driver.clickElement(By.css('.network-name')) + await driver.clickElement(By.css('.network-display')) await driver.delay(regularDelayMs) await driver.clickElement( @@ -1780,7 +1780,7 @@ describe('MetaMask', function () { }) it('selects another provider', async function () { - await driver.clickElement(By.css('.network-name')) + await driver.clickElement(By.css('.network-display')) await driver.delay(regularDelayMs) await driver.clickElement( @@ -1790,7 +1790,7 @@ describe('MetaMask', function () { }) it('finds all recent RPCs in history', async function () { - await driver.clickElement(By.css('.network-name')) + await driver.clickElement(By.css('.network-display')) await driver.delay(regularDelayMs) // only recent 3 are found and in correct order (most recent at the top) diff --git a/ui/app/components/app/app-header/app-header.component.js b/ui/app/components/app/app-header/app-header.component.js index 7ad30d3d3..c8e388880 100644 --- a/ui/app/components/app/app-header/app-header.component.js +++ b/ui/app/components/app/app-header/app-header.component.js @@ -4,13 +4,11 @@ import classnames from 'classnames' import Identicon from '../../ui/identicon' import MetaFoxLogo from '../../ui/metafox-logo' import { DEFAULT_ROUTE } from '../../../helpers/constants/routes' -import NetworkIndicator from '../network' +import NetworkDisplay from '../network-display' export default class AppHeader extends PureComponent { static propTypes = { history: PropTypes.object, - network: PropTypes.string, - provider: PropTypes.object, networkDropdownOpen: PropTypes.bool, showNetworkDropdown: PropTypes.func, hideNetworkDropdown: PropTypes.func, @@ -37,8 +35,14 @@ export default class AppHeader extends PureComponent { networkDropdownOpen, showNetworkDropdown, hideNetworkDropdown, + disabled, + disableNetworkIndicator, } = this.props + if (disabled || disableNetworkIndicator) { + return + } + if (networkDropdownOpen === false) { this.context.metricsEvent({ eventOpts: { @@ -91,8 +95,6 @@ export default class AppHeader extends PureComponent { render() { const { history, - network, - provider, isUnlocked, hideNetworkIndicator, disableNetworkIndicator, @@ -119,9 +121,10 @@ export default class AppHeader extends PureComponent {
{!hideNetworkIndicator && (
- this.handleNetworkIndicatorClick(event)} disabled={disabled || disableNetworkIndicator} /> diff --git a/ui/app/components/app/app-header/index.scss b/ui/app/components/app/app-header/index.scss index aacbbf9be..0a3b09635 100644 --- a/ui/app/components/app/app-header/index.scss +++ b/ui/app/components/app/app-header/index.scss @@ -95,13 +95,12 @@ flex: 1 0 auto; width: 0; justify-content: flex-end; + } - .network-component.pointer { - max-width: 200px; - } - - .network-indicator { - width: 100%; - } + &__network-down-arrow { + background-image: url(/images/icons/caret-down.svg); + background-repeat: no-repeat; + background-size: contain; + background-position: center; } } diff --git a/ui/app/components/app/app-header/tests/app-header.test.js b/ui/app/components/app/app-header/tests/app-header.test.js index 7a1b43ee7..c736d6549 100644 --- a/ui/app/components/app/app-header/tests/app-header.test.js +++ b/ui/app/components/app/app-header/tests/app-header.test.js @@ -4,6 +4,7 @@ import sinon from 'sinon' import { shallow } from 'enzyme' import MetaFoxLogo from '../../../ui/metafox-logo' import AppHeader from '..' +import NetworkDisplay from '../../network-display' describe('App Header', function () { let wrapper @@ -49,7 +50,7 @@ describe('App Header', function () { describe('Network', function () { it('shows network dropdown when networkDropdownOpen is false', function () { - const network = wrapper.find({ network: 'test' }) + const network = wrapper.find(NetworkDisplay) network.simulate('click', { preventDefault: () => undefined, @@ -61,7 +62,7 @@ describe('App Header', function () { it('hides network dropdown when networkDropdownOpen is true', function () { wrapper.setProps({ networkDropdownOpen: true }) - const network = wrapper.find({ network: 'test' }) + const network = wrapper.find(NetworkDisplay) network.simulate('click', { preventDefault: () => undefined, diff --git a/ui/app/components/app/confirm-page-container/confirm-page-container-header/index.scss b/ui/app/components/app/confirm-page-container/confirm-page-container-header/index.scss index 79d79e55b..9268e12a0 100644 --- a/ui/app/components/app/confirm-page-container/confirm-page-container-header/index.scss +++ b/ui/app/components/app/confirm-page-container/confirm-page-container-header/index.scss @@ -10,6 +10,11 @@ padding: 4px 13px 4px 13px; flex: 0 0 auto; align-items: center; + + & .network-display { + margin-right: 0; + height: 25px; + } } &__back-button-container { diff --git a/ui/app/components/app/connected-status-indicator/connected-status-indicator.component.js b/ui/app/components/app/connected-status-indicator/connected-status-indicator.component.js deleted file mode 100644 index 7734dc9cc..000000000 --- a/ui/app/components/app/connected-status-indicator/connected-status-indicator.component.js +++ /dev/null @@ -1,71 +0,0 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import classnames from 'classnames' -import { - STATUS_CONNECTED, - STATUS_CONNECTED_TO_ANOTHER_ACCOUNT, - STATUS_NOT_CONNECTED, -} from '../../../helpers/constants/connected-sites' - -export default class ConnectedStatusIndicator extends Component { - static contextTypes = { - t: PropTypes.func, - } - - static propTypes = { - status: PropTypes.oneOf([ - STATUS_CONNECTED, - STATUS_CONNECTED_TO_ANOTHER_ACCOUNT, - STATUS_NOT_CONNECTED, - ]), - onClick: PropTypes.func, - } - - static defaultProps = { - status: STATUS_NOT_CONNECTED, - onClick: undefined, - } - - renderStatusCircle = () => { - const { status } = this.props - - return ( -
- -
- ) - } - - renderStatusText = () => { - const { t } = this.context - const { status } = this.props - - const text = - status === STATUS_CONNECTED - ? t('statusConnected') - : t('statusNotConnected') - - return
{text}
- } - - render() { - return ( - - ) - } -} diff --git a/ui/app/components/app/connected-status-indicator/connected-status-indicator.container.js b/ui/app/components/app/connected-status-indicator/connected-status-indicator.container.js deleted file mode 100644 index 253027959..000000000 --- a/ui/app/components/app/connected-status-indicator/connected-status-indicator.container.js +++ /dev/null @@ -1,39 +0,0 @@ -import { findKey } from 'lodash' -import { connect } from 'react-redux' -import { - STATUS_CONNECTED, - STATUS_CONNECTED_TO_ANOTHER_ACCOUNT, - STATUS_NOT_CONNECTED, -} from '../../../helpers/constants/connected-sites' -import { - getAddressConnectedDomainMap, - getOriginOfCurrentTab, - getSelectedAddress, -} from '../../../selectors' -import ConnectedStatusIndicator from './connected-status-indicator.component' - -const mapStateToProps = (state) => { - const selectedAddress = getSelectedAddress(state) - const addressConnectedDomainMap = getAddressConnectedDomainMap(state) - const originOfCurrentTab = getOriginOfCurrentTab(state) - - const selectedAddressDomainMap = addressConnectedDomainMap[selectedAddress] - const currentTabIsConnectedToSelectedAddress = Boolean( - selectedAddressDomainMap && selectedAddressDomainMap[originOfCurrentTab], - ) - - let status - if (currentTabIsConnectedToSelectedAddress) { - status = STATUS_CONNECTED - } else if (findKey(addressConnectedDomainMap, originOfCurrentTab)) { - status = STATUS_CONNECTED_TO_ANOTHER_ACCOUNT - } else { - status = STATUS_NOT_CONNECTED - } - - return { - status, - } -} - -export default connect(mapStateToProps)(ConnectedStatusIndicator) diff --git a/ui/app/components/app/connected-status-indicator/connected-status-indicator.js b/ui/app/components/app/connected-status-indicator/connected-status-indicator.js new file mode 100644 index 000000000..31cb2b137 --- /dev/null +++ b/ui/app/components/app/connected-status-indicator/connected-status-indicator.js @@ -0,0 +1,66 @@ +import React from 'react' +import PropTypes from 'prop-types' +import { useSelector } from 'react-redux' +import { findKey } from 'lodash' +import { + STATUS_CONNECTED, + STATUS_CONNECTED_TO_ANOTHER_ACCOUNT, + STATUS_NOT_CONNECTED, +} from '../../../helpers/constants/connected-sites' +import ColorIndicator from '../../ui/color-indicator' +import { COLORS } from '../../../helpers/constants/design-system' +import { useI18nContext } from '../../../hooks/useI18nContext' +import { + getAddressConnectedDomainMap, + getOriginOfCurrentTab, + getSelectedAddress, +} from '../../../selectors' + +export default function ConnectedStatusIndicator({ onClick }) { + const t = useI18nContext() + + const selectedAddress = useSelector(getSelectedAddress) + const addressConnectedDomainMap = useSelector(getAddressConnectedDomainMap) + const originOfCurrentTab = useSelector(getOriginOfCurrentTab) + + const selectedAddressDomainMap = addressConnectedDomainMap[selectedAddress] + const currentTabIsConnectedToSelectedAddress = Boolean( + selectedAddressDomainMap && selectedAddressDomainMap[originOfCurrentTab], + ) + let status + if (currentTabIsConnectedToSelectedAddress) { + status = STATUS_CONNECTED + } else if (findKey(addressConnectedDomainMap, originOfCurrentTab)) { + status = STATUS_CONNECTED_TO_ANOTHER_ACCOUNT + } else { + status = STATUS_NOT_CONNECTED + } + + let indicatorType = ColorIndicator.TYPES.OUTLINE + let indicatorColor = COLORS.UI4 + + if (status === STATUS_CONNECTED) { + indicatorColor = COLORS.SUCCESS1 + indicatorType = ColorIndicator.TYPES.PARTIAL + } else if (status === STATUS_CONNECTED_TO_ANOTHER_ACCOUNT) { + indicatorColor = COLORS.ALERT1 + } + + const text = + status === STATUS_CONNECTED ? t('statusConnected') : t('statusNotConnected') + + return ( + + ) +} + +ConnectedStatusIndicator.defaultProps = { + onClick: undefined, +} + +ConnectedStatusIndicator.propTypes = { + onClick: PropTypes.func, +} diff --git a/ui/app/components/app/connected-status-indicator/index.js b/ui/app/components/app/connected-status-indicator/index.js index 37679809b..4f654fae4 100644 --- a/ui/app/components/app/connected-status-indicator/index.js +++ b/ui/app/components/app/connected-status-indicator/index.js @@ -1 +1 @@ -export { default } from './connected-status-indicator.container' +export { default } from './connected-status-indicator' diff --git a/ui/app/components/app/dropdowns/components/dropdown.js b/ui/app/components/app/dropdowns/components/dropdown.js index 52a4af4ef..da67c700f 100644 --- a/ui/app/components/app/dropdowns/components/dropdown.js +++ b/ui/app/components/app/dropdowns/components/dropdown.js @@ -73,6 +73,12 @@ export class DropdownMenuItem extends Component { onClick() closeMenu() }} + onKeyPress={(event) => { + if (event.key === 'Enter') { + onClick() + closeMenu() + } + }} style={{ listStyle: 'none', padding: '8px 0px', @@ -85,6 +91,7 @@ export class DropdownMenuItem extends Component { color: 'white', ...style, }} + tabIndex="0" > {children} diff --git a/ui/app/components/app/dropdowns/components/network-dropdown-icon.js b/ui/app/components/app/dropdowns/components/network-dropdown-icon.js deleted file mode 100644 index 2201651b8..000000000 --- a/ui/app/components/app/dropdowns/components/network-dropdown-icon.js +++ /dev/null @@ -1,48 +0,0 @@ -import PropTypes from 'prop-types' -import React from 'react' - -function NetworkDropdownIcon(props) { - const { backgroundColor, isSelected, innerBorder, diameter, loading } = props - - return loading ? ( - - - - ) : ( -
-
-
- ) -} - -NetworkDropdownIcon.defaultProps = { - backgroundColor: undefined, - loading: false, - innerBorder: 'none', - diameter: '12', - isSelected: false, -} - -NetworkDropdownIcon.propTypes = { - backgroundColor: PropTypes.string, - loading: PropTypes.bool, - innerBorder: PropTypes.string, - diameter: PropTypes.string, - isSelected: PropTypes.bool, -} - -export default NetworkDropdownIcon diff --git a/ui/app/components/app/dropdowns/network-dropdown.js b/ui/app/components/app/dropdowns/network-dropdown.js index c9e9464dc..613de6b28 100644 --- a/ui/app/components/app/dropdowns/network-dropdown.js +++ b/ui/app/components/app/dropdowns/network-dropdown.js @@ -14,8 +14,9 @@ import { NETWORK_TYPE_RPC } from '../../../../../shared/constants/network' import { isPrefixedFormattedHexString } from '../../../../../shared/modules/utils' import { getEnvironmentType } from '../../../../../app/scripts/lib/util' +import ColorIndicator from '../../ui/color-indicator' +import { COLORS } from '../../../helpers/constants/design-system' import { Dropdown, DropdownMenuItem } from './components/dropdown' -import NetworkDropdownIcon from './components/network-dropdown-icon' // classes from nodes of the toggle element. const notToggleElementClassnames = [ @@ -26,6 +27,12 @@ const notToggleElementClassnames = [ 'network-component', ] +const DROP_DOWN_MENU_ITEM_STYLE = { + fontSize: '16px', + lineHeight: '20px', + padding: '12px 0', +} + function mapStateToProps(state) { return { provider: state.metamask.provider, @@ -140,9 +147,11 @@ class NetworkDropdown extends Component { ) : (
)} - this.handleClick(network)} + style={DROP_DOWN_MENU_ITEM_STYLE} + > + {providerType === network ? ( + + ) : ( +
+ )} + + + {this.context.t(network)} + + + ) + } + render() { const { - provider: { type: providerType, rpcUrl: activeNetwork }, + provider: { rpcUrl: activeNetwork }, setNetworksTabAddMode, setSelectedSettingsRpcUrl, } = this.props const rpcListDetail = this.props.frequentRpcListDetail const isOpen = this.props.networkDropdownOpen - const dropdownMenuItemStyle = { - fontSize: '16px', - lineHeight: '20px', - padding: '12px 0', - } return (
- this.props.hideNetworkDropdown()} - onClick={() => this.handleClick('mainnet')} - style={{ ...dropdownMenuItemStyle, borderColor: '#038789' }} - > - {providerType === 'mainnet' ? ( - - ) : ( -
- )} - - - {this.context.t('mainnet')} - -
- this.props.hideNetworkDropdown()} - onClick={() => this.handleClick('ropsten')} - style={dropdownMenuItemStyle} - > - {providerType === 'ropsten' ? ( - - ) : ( -
- )} - - - {this.context.t('ropsten')} - -
- this.props.hideNetworkDropdown()} - onClick={() => this.handleClick('kovan')} - style={dropdownMenuItemStyle} - > - {providerType === 'kovan' ? ( - - ) : ( -
- )} - - - {this.context.t('kovan')} - -
- this.props.hideNetworkDropdown()} - onClick={() => this.handleClick('rinkeby')} - style={dropdownMenuItemStyle} - > - {providerType === 'rinkeby' ? ( - - ) : ( -
- )} - - - {this.context.t('rinkeby')} - -
- this.props.hideNetworkDropdown()} - onClick={() => this.handleClick('goerli')} - style={dropdownMenuItemStyle} - > - {providerType === 'goerli' ? ( - - ) : ( -
- )} - - - {this.context.t('goerli')} - -
+ {this.renderNetworkEntry('mainnet')} + {this.renderNetworkEntry('ropsten')} + {this.renderNetworkEntry('kovan')} + {this.renderNetworkEntry('rinkeby')} + {this.renderNetworkEntry('goerli')} + {this.renderCustomRpcList(rpcListDetail, this.props.provider)} this.props.hideNetworkDropdown()} @@ -373,16 +297,18 @@ class NetworkDropdown extends Component { setSelectedSettingsRpcUrl('') setNetworksTabAddMode(true) }} - style={dropdownMenuItemStyle} + style={DROP_DOWN_MENU_ITEM_STYLE} > {activeNetwork === 'custom' ? ( ) : (
)} - , - ) - const styleProp = wrapper.find('.menu-icon-circle').children().prop('style') - assert.strictEqual(styleProp.background, 'red') - assert.strictEqual(styleProp.border, 'none') - assert.strictEqual(styleProp.height, '12px') - assert.strictEqual(styleProp.width, '12px') - }) -}) diff --git a/ui/app/components/app/dropdowns/tests/network-dropdown.test.js b/ui/app/components/app/dropdowns/tests/network-dropdown.test.js index 2df87f956..50e607ac9 100644 --- a/ui/app/components/app/dropdowns/tests/network-dropdown.test.js +++ b/ui/app/components/app/dropdowns/tests/network-dropdown.test.js @@ -5,7 +5,7 @@ import thunk from 'redux-thunk' import { mountWithRouter } from '../../../../../../test/lib/render-helpers' import NetworkDropdown from '../network-dropdown' import { DropdownMenuItem } from '../components/dropdown' -import NetworkDropdownIcon from '../components/network-dropdown-icon' +import ColorIndicator from '../../../ui/color-indicator' describe('Network Dropdown', function () { let wrapper @@ -65,46 +65,41 @@ describe('Network Dropdown', function () { assert.strictEqual(wrapper.find(DropdownMenuItem).length, 8) }) - it('checks background color for first NetworkDropdownIcon', function () { - assert.strictEqual( - wrapper.find(NetworkDropdownIcon).at(0).prop('backgroundColor'), - '#29B6AF', - ) // Ethereum Mainnet Teal + it('checks background color for first ColorIndicator', function () { + const colorIndicator = wrapper.find(ColorIndicator).at(0) + assert.strictEqual(colorIndicator.prop('color'), 'mainnet') + assert.strictEqual(colorIndicator.prop('borderColor'), 'mainnet') }) - it('checks background color for second NetworkDropdownIcon', function () { - assert.strictEqual( - wrapper.find(NetworkDropdownIcon).at(1).prop('backgroundColor'), - '#ff4a8d', - ) // Ropsten Red + it('checks background color for second ColorIndicator', function () { + const colorIndicator = wrapper.find(ColorIndicator).at(1) + assert.strictEqual(colorIndicator.prop('color'), 'ropsten') + assert.strictEqual(colorIndicator.prop('borderColor'), 'ropsten') }) - it('checks background color for third NetworkDropdownIcon', function () { - assert.strictEqual( - wrapper.find(NetworkDropdownIcon).at(2).prop('backgroundColor'), - '#7057ff', - ) // Kovan Purple + it('checks background color for third ColorIndicator', function () { + const colorIndicator = wrapper.find(ColorIndicator).at(2) + assert.strictEqual(colorIndicator.prop('color'), 'kovan') + assert.strictEqual(colorIndicator.prop('borderColor'), 'kovan') }) - it('checks background color for fourth NetworkDropdownIcon', function () { - assert.strictEqual( - wrapper.find(NetworkDropdownIcon).at(3).prop('backgroundColor'), - '#f6c343', - ) // Rinkeby Yellow + it('checks background color for fourth ColorIndicator', function () { + const colorIndicator = wrapper.find(ColorIndicator).at(3) + assert.strictEqual(colorIndicator.prop('color'), 'rinkeby') + assert.strictEqual(colorIndicator.prop('borderColor'), 'rinkeby') }) - it('checks background color for fifth NetworkDropdownIcon', function () { - assert.strictEqual( - wrapper.find(NetworkDropdownIcon).at(4).prop('backgroundColor'), - '#3099f2', - ) // Goerli Blue + it('checks background color for fifth ColorIndicator', function () { + const colorIndicator = wrapper.find(ColorIndicator).at(4) + assert.strictEqual(colorIndicator.prop('color'), 'goerli') + assert.strictEqual(colorIndicator.prop('borderColor'), 'goerli') }) - it('checks background color for sixth NetworkDropdownIcon', function () { - assert.strictEqual( - wrapper.find(NetworkDropdownIcon).at(5).prop('backgroundColor'), - '#d6d9dc', - ) // "Custom network grey" + it('checks background color for sixth ColorIndicator', function () { + const colorIndicator = wrapper.find(ColorIndicator).at(5) + const customNetworkGray = 'ui-2' + assert.strictEqual(colorIndicator.prop('color'), customNetworkGray) + assert.strictEqual(colorIndicator.prop('borderColor'), customNetworkGray) }) it('checks dropdown for frequestRPCList from state', function () { diff --git a/ui/app/components/app/network-display/index.js b/ui/app/components/app/network-display/index.js index 9fbb16700..6e361e905 100644 --- a/ui/app/components/app/network-display/index.js +++ b/ui/app/components/app/network-display/index.js @@ -1,3 +1 @@ -import NetworkDisplay from './network-display.container' - -export default NetworkDisplay +export { default } from './network-display' diff --git a/ui/app/components/app/network-display/index.scss b/ui/app/components/app/network-display/index.scss index 4ded13d54..c07126b6f 100644 --- a/ui/app/components/app/network-display/index.scss +++ b/ui/app/components/app/network-display/index.scss @@ -1,66 +1,58 @@ .network-display { - &__container { - display: flex; - align-items: center; - justify-content: flex-start; - padding: 0 10px; - border-radius: 4px; - height: 25px; + display: flex; + align-items: center; + justify-content: flex-start; + padding: 0 10px; + border-radius: 4px; + min-height: 25px; + cursor: pointer; - &--colored { - background-color: lighten(rgb(125, 128, 130), 45%); - } - - &--mainnet { - background-color: lighten($blue-lagoon, 68%); - } - - &--ropsten { - background-color: lighten($crimson, 45%); - } - - &--kovan { - background-color: lighten($purple, 65%); - } - - &--rinkeby { - background-color: lighten($tulip-tree, 35%); - } - - &--goerli { - background-color: lighten($dodger-blue, 35%); - } + &--disabled { + cursor: not-allowed; } - &__name { - @include H7; + &--colored { + background-color: lighten(rgb(125, 128, 130), 45%); + } - padding-left: 5px; + &--mainnet { + background-color: lighten($blue-lagoon, 68%); + } + + &--ropsten { + background-color: lighten($crimson, 45%); + } + + &--kovan { + background-color: lighten($purple, 65%); + } + + &--rinkeby { + background-color: lighten($tulip-tree, 35%); + } + + &--goerli { + background-color: lighten($dodger-blue, 35%); + } + + + & .chip__label { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + + & .chip__left-icon { + margin-left: 4px; + } + + & .chip__right-icon { + margin-right: 4px; } &__icon { - height: 10px; - width: 10px; - border-radius: 10px; - - &--mainnet { - background-color: $blue-lagoon; - } - - &--ropsten { - background-color: $crimson; - } - - &--kovan { - background-color: $purple; - } - - &--rinkeby { - background-color: $tulip-tree; - } - - &--goerli { - background-color: $dodger-blue; - } + height: 8px; + width: 12px; + display: block; } } diff --git a/ui/app/components/app/network-display/network-display.component.js b/ui/app/components/app/network-display/network-display.component.js deleted file mode 100644 index c045c1527..000000000 --- a/ui/app/components/app/network-display/network-display.component.js +++ /dev/null @@ -1,71 +0,0 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import classnames from 'classnames' -import { NETWORK_TYPE_RPC } from '../../../../../shared/constants/network' - -export default class NetworkDisplay extends Component { - static defaultProps = { - colored: true, - } - - static propTypes = { - networkNickname: PropTypes.string.isRequired, - networkType: PropTypes.string.isRequired, - colored: PropTypes.bool, - } - - static contextTypes = { - t: PropTypes.func, - } - - renderNetworkIcon() { - const { networkType } = this.props - - return networkType ? ( -
- ) : ( -
- ) - } - - render() { - const { colored, networkNickname, networkType } = this.props - - return ( -
- {networkType ? ( -
- ) : ( -
- )} -
- {networkType === NETWORK_TYPE_RPC && networkNickname - ? networkNickname - : this.context.t(networkType)} -
-
- ) - } -} diff --git a/ui/app/components/app/network-display/network-display.container.js b/ui/app/components/app/network-display/network-display.container.js deleted file mode 100644 index 136336448..000000000 --- a/ui/app/components/app/network-display/network-display.container.js +++ /dev/null @@ -1,15 +0,0 @@ -import { connect } from 'react-redux' -import NetworkDisplay from './network-display.component' - -const mapStateToProps = ({ - metamask: { - provider: { nickname, type }, - }, -}) => { - return { - networkNickname: nickname, - networkType: type, - } -} - -export default connect(mapStateToProps)(NetworkDisplay) diff --git a/ui/app/components/app/network-display/network-display.js b/ui/app/components/app/network-display/network-display.js new file mode 100644 index 000000000..59e898c88 --- /dev/null +++ b/ui/app/components/app/network-display/network-display.js @@ -0,0 +1,78 @@ +import React from 'react' +import PropTypes from 'prop-types' +import classnames from 'classnames' +import { useSelector } from 'react-redux' +import { NETWORK_TYPE_RPC } from '../../../../../shared/constants/network' + +import LoadingIndicator from '../../ui/loading-indicator' +import ColorIndicator from '../../ui/color-indicator' +import { COLORS, TYPOGRAPHY } from '../../../helpers/constants/design-system' +import Chip from '../../ui/chip/chip' +import { useI18nContext } from '../../../hooks/useI18nContext' + +export default function NetworkDisplay({ + colored, + outline, + iconClassName, + disabled, + onClick, +}) { + const { network, networkNickname, networkType } = useSelector((state) => ({ + network: state.metamask.network, + networkNickname: state.metamask.provider.nickname, + networkType: state.metamask.provider.type, + })) + const t = useI18nContext() + + return ( + + + + } + rightIcon={ + iconClassName && ( + + ) + } + label={ + networkType === NETWORK_TYPE_RPC + ? networkNickname ?? t('privateNetwork') + : t(networkType) + } + className={classnames('network-display', { + 'network-display--colored': colored, + 'network-display--disabled': disabled, + [`network-display--${networkType}`]: colored && networkType, + })} + labelProps={{ + variant: TYPOGRAPHY.H7, + }} + /> + ) +} +NetworkDisplay.propTypes = { + colored: PropTypes.bool, + outline: PropTypes.bool, + disabled: PropTypes.bool, + iconClassName: PropTypes.string, + onClick: PropTypes.func, +} + +NetworkDisplay.defaultProps = { + colored: true, +} diff --git a/ui/app/components/app/network.js b/ui/app/components/app/network.js deleted file mode 100644 index 194e65c65..000000000 --- a/ui/app/components/app/network.js +++ /dev/null @@ -1,192 +0,0 @@ -import PropTypes from 'prop-types' -import React, { Component } from 'react' -import classnames from 'classnames' -import NetworkDropdownIcon from './dropdowns/components/network-dropdown-icon' - -function NetworkIndicator({ - disabled, - children, - hoverText, - onClick, - providerName, -}) { - return ( -
{ - if (!disabled) { - onClick(event) - } - }} - > -
- {children} -
-
-
- ) -} - -NetworkIndicator.propTypes = { - children: PropTypes.node.isRequired, - disabled: PropTypes.bool, - hoverText: PropTypes.string, - onClick: PropTypes.func, - providerName: PropTypes.string, -} - -export default class Network extends Component { - static contextTypes = { - t: PropTypes.func, - } - - static propTypes = { - network: PropTypes.string.isRequired, - provider: PropTypes.shape({ - type: PropTypes.string, - nickname: PropTypes.string, - rpcUrl: PropTypes.string, - }).isRequired, - disabled: PropTypes.bool, - onClick: PropTypes.func.isRequired, - } - - render() { - const { t } = this.context - - const { disabled, network: networkNumber, onClick, provider } = this.props - - let providerName, providerNick, providerUrl - if (provider) { - providerName = provider.type - providerNick = provider.nickname || '' - providerUrl = provider.rpcUrl - } - - switch (providerName) { - case 'mainnet': - return ( - - -
{t('mainnet')}
-
- ) - - case 'ropsten': - return ( - - -
{t('ropsten')}
-
- ) - - case 'kovan': - return ( - - -
{t('kovan')}
-
- ) - - case 'rinkeby': - return ( - - -
{t('rinkeby')}
-
- ) - - case 'goerli': - return ( - - -
{t('goerli')}
-
- ) - - default: - return ( - - {networkNumber === 'loading' ? ( - onClick(event)} - > - {t('attemptingConnect')} - - ) : ( - - )} -
- {providerNick || t('privateNetwork')} -
-
- ) - } - } -} diff --git a/ui/app/components/app/permission-page-container/index.js b/ui/app/components/app/permission-page-container/index.js index 63e8265c2..8fe6b44b9 100644 --- a/ui/app/components/app/permission-page-container/index.js +++ b/ui/app/components/app/permission-page-container/index.js @@ -1,3 +1,2 @@ export { default } from './permission-page-container.container' export { default as PermissionPageContainerContent } from './permission-page-container-content' -export { default as PermissionPageContainerHeader } from './permission-page-container-header' diff --git a/ui/app/components/app/permission-page-container/permission-page-container-header/index.js b/ui/app/components/app/permission-page-container/permission-page-container-header/index.js deleted file mode 100644 index d57a5370b..000000000 --- a/ui/app/components/app/permission-page-container/permission-page-container-header/index.js +++ /dev/null @@ -1 +0,0 @@ -export { default } from './permission-page-container-header.component' diff --git a/ui/app/components/app/permission-page-container/permission-page-container-header/permission-page-container-header.component.js b/ui/app/components/app/permission-page-container/permission-page-container-header/permission-page-container-header.component.js deleted file mode 100644 index 72bd17f82..000000000 --- a/ui/app/components/app/permission-page-container/permission-page-container-header/permission-page-container-header.component.js +++ /dev/null @@ -1,12 +0,0 @@ -import React from 'react' -import NetworkDisplay from '../../network-display' - -const ProviderPageContainerHeader = () => { - return ( -
- -
- ) -} - -export default ProviderPageContainerHeader diff --git a/ui/app/components/app/signature-request/index.scss b/ui/app/components/app/signature-request/index.scss index 16008cbc2..f4df222a1 100644 --- a/ui/app/components/app/signature-request/index.scss +++ b/ui/app/components/app/signature-request/index.scss @@ -16,16 +16,10 @@ .signature-request-header { flex: 1; - .network-display__container { + .network-display { padding: 0; justify-content: flex-end; - } - - .network-display__name { - @include H7; - - white-space: nowrap; - font-weight: 500; + margin-left: auto; } } diff --git a/ui/app/components/ui/chip/chip.js b/ui/app/components/ui/chip/chip.js index c2281f7d4..78dc8173d 100644 --- a/ui/app/components/ui/chip/chip.js +++ b/ui/app/components/ui/chip/chip.js @@ -15,9 +15,16 @@ export default function Chip({ rightIcon, onClick, }) { + const onKeyPress = (event) => { + if (event.key === 'Enter' && onClick) { + onClick(event) + } + } + return (
+ {alt} + + ) : ( + children + ) +} + +LoadingIndicator.propTypes = { + isLoading: PropTypes.bool.isRequired, + alt: PropTypes.string.isRequired, + title: PropTypes.string.isRequired, + children: PropTypes.node, +} diff --git a/ui/app/components/ui/loading-indicator/loading-indicator.scss b/ui/app/components/ui/loading-indicator/loading-indicator.scss new file mode 100644 index 000000000..1942b8389 --- /dev/null +++ b/ui/app/components/ui/loading-indicator/loading-indicator.scss @@ -0,0 +1,17 @@ +.loading-indicator { + display: flex; + flex-flow: row nowrap; + align-items: center; + position: relative; + height: 16px; + width: 16px; + margin-left: 5px; + + &__spinner { + width: 27px; + height: 26px; + position: absolute; + top: -5px; + left: -6px; + } +} diff --git a/ui/app/components/ui/ui-components.scss b/ui/app/components/ui/ui-components.scss index 2317072e1..2b76068d2 100644 --- a/ui/app/components/ui/ui-components.scss +++ b/ui/app/components/ui/ui-components.scss @@ -26,6 +26,7 @@ @import 'identicon/index'; @import 'info-tooltip/index'; @import 'list-item/index'; +@import 'loading-indicator/loading-indicator'; @import 'loading-screen/index'; @import 'menu/menu'; @import 'page-container/index'; diff --git a/ui/app/css/itcss/components/network.scss b/ui/app/css/itcss/components/network.scss index 34f905587..043626ff8 100644 --- a/ui/app/css/itcss/components/network.scss +++ b/ui/app/css/itcss/components/network.scss @@ -41,42 +41,6 @@ } } -.network-indicator { - @include H8; - - display: flex; - align-items: center; - - &__down-arrow { - height: 8px; - width: 12px; - display: block; - background-image: url(/images/icons/caret-down.svg); - background-repeat: no-repeat; - background-size: contain; - background-position: center; - margin: 0 8px; - } - - .fa-question-circle { - font-size: $font-size-paragraph; - margin: 0 4px 0 6px; - flex: 0 0 auto; - } -} - -.network-name { - @include H7; - - padding: 0 4px; - flex: 1 1 auto; - color: $tundora; - font-weight: 500; - white-space: nowrap; - text-overflow: ellipsis; - overflow: hidden; -} - .dropdown-menu-item .fa.delete { margin-right: 10px; display: none; @@ -89,6 +53,10 @@ .network-droppo { right: 2px; + .color-indicator { + margin: 0 14px; + } + @media screen and (min-width: 576px) { right: calc(((100% - 85vw) / 2) + 2px); } diff --git a/ui/app/pages/settings/networks-tab/index.scss b/ui/app/pages/settings/networks-tab/index.scss index 3b82a69fd..113657e83 100644 --- a/ui/app/pages/settings/networks-tab/index.scss +++ b/ui/app/pages/settings/networks-tab/index.scss @@ -142,8 +142,9 @@ display: flex; padding: 13px 0 13px 17px; position: relative; + align-items: center; - .menu-icon-circle { + .color-indicator { &:hover { cursor: pointer; } diff --git a/ui/app/pages/settings/networks-tab/networks-tab.component.js b/ui/app/pages/settings/networks-tab/networks-tab.component.js index 00e66cca8..02d987efb 100644 --- a/ui/app/pages/settings/networks-tab/networks-tab.component.js +++ b/ui/app/pages/settings/networks-tab/networks-tab.component.js @@ -8,7 +8,8 @@ import { NETWORKS_ROUTE, NETWORKS_FORM_ROUTE, } from '../../../helpers/constants/routes' -import NetworkDropdownIcon from '../../../components/app/dropdowns/components/network-dropdown-icon' +import ColorIndicator from '../../../components/ui/color-indicator' +import { COLORS } from '../../../helpers/constants/design-system' import NetworkForm from './network-form' export default class NetworksTab extends PureComponent { @@ -80,8 +81,6 @@ export default class NetworksTab extends PureComponent { isFullScreen, } = this.props const { - border, - iconColor, label, labelKey, rpcUrl, @@ -111,9 +110,10 @@ export default class NetworksTab extends PureComponent { } }} > -
-
{this.context.t('newNetwork')} From 293b8a0f530380407a840c029ee6a3b906cfef1e Mon Sep 17 00:00:00 2001 From: Brad Decker Date: Wed, 27 Jan 2021 11:54:25 -0600 Subject: [PATCH 03/48] Add box component (#10289) --- ui/app/components/ui/box/box.js | 149 ++++++++++++++++++ ui/app/components/ui/box/box.scss | 134 ++++++++++++++++ ui/app/components/ui/box/box.stories.js | 79 ++++++++++ ui/app/components/ui/box/index.js | 1 + ui/app/components/ui/chip/chip.js | 10 +- ui/app/components/ui/typography/typography.js | 29 +++- .../components/ui/typography/typography.scss | 18 ++- .../ui/typography/typography.stories.js | 30 ++-- ui/app/components/ui/ui-components.scss | 1 + ui/app/css/design-system/attributes.scss | 72 +++++++++ ui/app/css/design-system/index.scss | 1 + ui/app/css/design-system/typography.scss | 5 - ui/app/css/utilities/_spacing.scss | 7 + ui/app/css/utilities/index.scss | 1 + ui/app/helpers/constants/design-system.js | 114 ++++++++++++++ 15 files changed, 611 insertions(+), 40 deletions(-) create mode 100644 ui/app/components/ui/box/box.js create mode 100644 ui/app/components/ui/box/box.scss create mode 100644 ui/app/components/ui/box/box.stories.js create mode 100644 ui/app/components/ui/box/index.js create mode 100644 ui/app/css/design-system/attributes.scss create mode 100644 ui/app/css/utilities/_spacing.scss diff --git a/ui/app/components/ui/box/box.js b/ui/app/components/ui/box/box.js new file mode 100644 index 000000000..d8a630bad --- /dev/null +++ b/ui/app/components/ui/box/box.js @@ -0,0 +1,149 @@ +import React from 'react' +import PropTypes from 'prop-types' +import classnames from 'classnames' +import { + ALIGN_ITEMS, + BLOCK_SIZES, + BORDER_STYLE, + COLORS, + DISPLAY, + JUSTIFY_CONTENT, + SIZES, +} from '../../../helpers/constants/design-system' + +const ValidSize = PropTypes.oneOf([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]) +const ArrayOfValidSizes = PropTypes.arrayOf(ValidSize) +const MultipleSizes = PropTypes.oneOf([ValidSize, ArrayOfValidSizes]) + +function generateSizeClasses(baseClass, type, main, top, right, bottom, left) { + const arr = Array.isArray(main) ? main : [] + const singleDigit = Array.isArray(main) ? undefined : main + if (Array.isArray(main) && ![2, 3, 4].includes(main.length)) { + throw new Error( + `Expected prop ${type} to have length between 2 and 4, received ${main.length}`, + ) + } + + const isHorizontalAndVertical = arr.length === 2 + const isTopHorizontalAndBottom = arr.length === 3 + const isAllFour = arr.length === 4 + const hasAtLeastTwo = arr.length >= 2 + const hasAtLeastThree = arr.length >= 3 + return { + [`${baseClass}--${type}-${singleDigit}`]: singleDigit !== undefined, + [`${baseClass}--${type}-top-${top}`]: typeof top === 'number', + [`${baseClass}--${type}-right-${right}`]: typeof right === 'number', + [`${baseClass}--${type}-bottom-${bottom}`]: typeof bottom === 'number', + [`${baseClass}--${type}-left-${left}`]: typeof left === 'number', + // As long as an array of length >= 2 has been provided, the first number + // will always be for the top value. + [`${baseClass}--${type}-top-${arr?.[0]}`]: hasAtLeastTwo, + // As long as an array of length >= 2 has been provided, the second number + // will always be for the right value. + [`${baseClass}--${type}-right-${arr?.[1]}`]: hasAtLeastTwo, + // If an array has 2 values, the first number is the bottom value. If + // instead if has 3 or more values, the third number will be the bottom. + [`${baseClass}--${type}-bottom-${arr?.[2]}`]: hasAtLeastThree, + [`${baseClass}--${type}-bottom-${arr?.[0]}`]: isHorizontalAndVertical, + // If an array has 2 or 3 values, the second number will be the left value + [`${baseClass}--${type}-left-${arr?.[1]}`]: + isHorizontalAndVertical || isTopHorizontalAndBottom, + // If an array has 4 values, the fourth number is the left value + [`${baseClass}--${type}-left-${arr?.[3]}`]: isAllFour, + } +} + +export default function Box({ + padding, + paddingTop, + paddingRight, + paddingBottom, + paddingLeft, + margin, + marginTop, + marginRight, + marginBottom, + marginLeft, + borderColor, + borderWidth, + borderRadius, + borderStyle, + alignItems, + justifyContent, + display, + width, + height, + children, +}) { + const boxClassName = classnames('box', { + // ---Borders--- + // if borderWidth or borderColor is supplied w/o style, default to solid + 'box--border-style-solid': + !borderStyle && (Boolean(borderWidth) || Boolean(borderColor)), + // if borderColor supplied w/o width, default to 1 + 'box--border-size-1': !borderWidth && Boolean(borderColor), + [`box--border-color-${borderColor}`]: Boolean(borderColor), + [`box--rounded-${borderRadius}`]: Boolean(borderRadius), + [`box--border-style-${borderStyle}`]: Boolean(borderStyle), + [`box--border-size-${borderWidth}`]: Boolean(borderWidth), + // Margin + ...generateSizeClasses( + 'box', + 'margin', + margin, + marginTop, + marginRight, + marginBottom, + marginLeft, + ), + // Padding + ...generateSizeClasses( + 'box', + 'padding', + padding, + paddingTop, + paddingRight, + paddingBottom, + paddingLeft, + ), + // ---Flex/Grid alignment--- + // if justifyContent or alignItems supplied w/o display, default to flex + 'box--display-flex': + !display && (Boolean(justifyContent) || Boolean(alignItems)), + [`box--justify-content-${justifyContent}`]: Boolean(justifyContent), + [`box--align-items-${alignItems}`]: Boolean(alignItems), + // display + [`box--display-${display}`]: Boolean(display), + // width & height + [`box--width-${width}`]: Boolean(width), + [`box--height-${height}`]: Boolean(height), + }) + // Apply Box styles to any other component using function pattern + if (typeof children === 'function') { + return children(boxClassName) + } + return
{children}
+} + +Box.propTypes = { + children: PropTypes.oneOfType([PropTypes.node, PropTypes.func]), + margin: MultipleSizes, + marginTop: ValidSize, + marginBottom: ValidSize, + marginRight: ValidSize, + marginLeft: ValidSize, + padding: MultipleSizes, + paddingTop: ValidSize, + paddingBottom: ValidSize, + paddingRight: ValidSize, + paddingLeft: ValidSize, + borderColor: PropTypes.oneOf(Object.values(COLORS)), + borderWidth: PropTypes.number, + borderRadius: PropTypes.oneOf(Object.values(SIZES)), + borderStyle: PropTypes.oneOf(Object.values(BORDER_STYLE)), + alignItems: PropTypes.oneOf(Object.values(ALIGN_ITEMS)), + justifyContent: PropTypes.oneOf(Object.values(JUSTIFY_CONTENT)), + display: PropTypes.oneOf(Object.values(DISPLAY)), + width: PropTypes.oneOf(Object.values(BLOCK_SIZES)), + height: PropTypes.oneOf(Object.values(BLOCK_SIZES)), +} diff --git a/ui/app/components/ui/box/box.scss b/ui/app/components/ui/box/box.scss new file mode 100644 index 000000000..6ef762766 --- /dev/null +++ b/ui/app/components/ui/box/box.scss @@ -0,0 +1,134 @@ +@use "sass:map"; +@use "design-system"; +@use "utilities"; + +$attributes: padding, margin; + +.box { + // Padding and Margin + @each $attribute in $attributes { + @each $size in design-system.$sizes-numeric { + &--#{$attribute}-#{$size} { + #{$attribute}: utilities.get-spacing($size); + } + } + + @each $size in design-system.$sizes-numeric { + @each $direction in design-system.$directions { + &--#{$attribute}-#{$direction}-#{$size} { + #{$attribute}-#{$direction}: utilities.get-spacing($size); + } + } + } + } + + // Borders + @each $size in design-system.$sizes-numeric { + &--border-size-#{$size} { + border-width: #{$size}px; + } + } + + @each $variant, $color in design-system.$color-map { + &--border-color-#{$variant} { + border-color: $color; + } + } + + @each $border-style in design-system.$border-style { + &--border-style-#{$border-style} { + border-style: $border-style; + } + } + + &--rounded-none { + border-radius: 0; + } + + &--rounded-xs { + border-radius: 0.125rem; + } + + &--rounded-sm { + border-radius: 0.25rem; + } + + &--rounded-md { + border-radius: 0.375rem; + } + + &--rounded-lg { + border-radius: 0.5rem; + } + + &--rounded-xl { + border-radius: 0.75rem; + } + + // Display and Flex/Grid alignment + @each $display in design-system.$display { + &--display-#{$display} { + display: $display; + } + } + + @each $alignment in design-system.$align-items { + &--align-items-#{$alignment} { + align-items: $alignment; + } + } + + @each $justification in design-system.$justify-content { + &--justify-content-#{$justification} { + justify-content: $justification; + } + } + + // Width and Height + &--width-full { + width: 100%; + } + + &--height-full { + height: 100%; + } + + @each $fraction, $value in design-system.$fractions { + &--width-#{$fraction} { + width: $value; + } + + &--height-#{$fraction} { + height: $value; + } + } + + &--height-screen { + height: 100vh; + } + + &--width-screen { + width: 100vw; + } + + &--height-max { + height: max-content; + } + + &--width-max { + width: max-content; + } + + &--height-min { + height: min-content; + } + + &--width-min { + width: min-content; + } + + // text + @each $alignment in design-system.$text-align { + text-align: $alignment; + } +} diff --git a/ui/app/components/ui/box/box.stories.js b/ui/app/components/ui/box/box.stories.js new file mode 100644 index 000000000..324e642b2 --- /dev/null +++ b/ui/app/components/ui/box/box.stories.js @@ -0,0 +1,79 @@ +import { number, select } from '@storybook/addon-knobs' +import React from 'react' +import { + ALIGN_ITEMS, + BLOCK_SIZES, + BORDER_STYLE, + COLORS, + DISPLAY, + JUSTIFY_CONTENT, +} from '../../../helpers/constants/design-system' +import Box from './box' + +export default { + title: 'Box', +} + +const sizeKnobOptions = [undefined, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] + +export const box = () => { + const items = [] + const size = number( + 'size', + 100, + { range: true, min: 50, max: 500, step: 10 }, + 'children', + ) + for (let $i = 0; $i < number('items', 1, {}, 'children'); $i++) { + items.push() + } + return ( + + {items} + + ) +} diff --git a/ui/app/components/ui/box/index.js b/ui/app/components/ui/box/index.js new file mode 100644 index 000000000..e5b58f373 --- /dev/null +++ b/ui/app/components/ui/box/index.js @@ -0,0 +1 @@ +export { default } from './box' diff --git a/ui/app/components/ui/chip/chip.js b/ui/app/components/ui/chip/chip.js index 78dc8173d..1fa3faf3d 100644 --- a/ui/app/components/ui/chip/chip.js +++ b/ui/app/components/ui/chip/chip.js @@ -3,7 +3,7 @@ import PropTypes from 'prop-types' import classnames from 'classnames' import { omit } from 'lodash' import Typography from '../typography' -import { COLORS } from '../../../helpers/constants/design-system' +import { COLORS, TYPOGRAPHY } from '../../../helpers/constants/design-system' export default function Chip({ className, @@ -37,9 +37,9 @@ export default function Chip({ {children ?? ( {label} @@ -54,7 +54,9 @@ Chip.propTypes = { borderColor: PropTypes.oneOf(Object.values(COLORS)), label: PropTypes.string, children: PropTypes.node, - labelProps: PropTypes.shape(omit(Typography.propTypes, ['className'])), + labelProps: PropTypes.shape({ + ...omit(Typography.propTypes, ['className']), + }), leftIcon: PropTypes.node, rightIcon: PropTypes.node, className: PropTypes.string, diff --git a/ui/app/components/ui/typography/typography.js b/ui/app/components/ui/typography/typography.js index 93990b00b..f3ea8fac7 100644 --- a/ui/app/components/ui/typography/typography.js +++ b/ui/app/components/ui/typography/typography.js @@ -1,7 +1,13 @@ import React from 'react' import classnames from 'classnames' import PropTypes from 'prop-types' -import { COLORS, TYPOGRAPHY } from '../../../helpers/constants/design-system' +import { + COLORS, + FONT_WEIGHT, + TEXT_ALIGN, + TYPOGRAPHY, +} from '../../../helpers/constants/design-system' +import Box from '../box' const { H6, H7, H8, H9 } = TYPOGRAPHY @@ -11,16 +17,15 @@ export default function Typography({ color = COLORS.BLACK, tag, children, - spacing = 1, fontWeight = 'normal', align, + boxProps = {}, }) { const computedClassName = classnames( 'typography', className, `typography--${variant}`, `typography--align-${align}`, - `typography--spacing-${spacing}`, `typography--color-${color}`, `typography--weight-${fontWeight}`, ) @@ -33,7 +38,15 @@ export default function Typography({ Tag = H6 } - return {children} + return ( + + {(boxClassName) => ( + + {children} + + )} + + ) } Typography.propTypes = { @@ -41,9 +54,11 @@ Typography.propTypes = { children: PropTypes.node.isRequired, color: PropTypes.oneOf(Object.values(COLORS)), className: PropTypes.string, - align: PropTypes.oneOf(['center', 'right']), - spacing: PropTypes.oneOf([1, 2, 3, 4, 5, 6, 7, 8]), - fontWeight: PropTypes.oneOf(['bold', 'normal']), + align: PropTypes.oneOf(Object.values(TEXT_ALIGN)), + boxProps: PropTypes.shape({ + ...Box.propTypes, + }), + fontWeight: PropTypes.oneOf(Object.values(FONT_WEIGHT)), tag: PropTypes.oneOf([ 'p', 'h1', diff --git a/ui/app/components/ui/typography/typography.scss b/ui/app/components/ui/typography/typography.scss index e377f31d2..50a2ec622 100644 --- a/ui/app/components/ui/typography/typography.scss +++ b/ui/app/components/ui/typography/typography.scss @@ -4,6 +4,10 @@ .typography { @include design-system.Paragraph; + & b { + font-weight: 700; + } + @each $variant in map.keys(design-system.$typography-variants) { &--#{$variant} { @include design-system.typography($variant); @@ -16,18 +20,16 @@ } } - @each $variant, $weight in design-system.$typography-font-weights { - &--weight-#{$variant} { + @each $weight in design-system.$font-weight { + &--weight-#{$weight} { font-weight: $weight; } } - &--align-center { - text-align: center; - } - - &--align-right { - text-align: right; + @each $alignment in design-system.$text-align { + &--align-#{$alignment} { + text-align: $alignment; + } } @for $i from 1 through 8 { diff --git a/ui/app/components/ui/typography/typography.stories.js b/ui/app/components/ui/typography/typography.stories.js index 68d567e35..0d0d486b8 100644 --- a/ui/app/components/ui/typography/typography.stories.js +++ b/ui/app/components/ui/typography/typography.stories.js @@ -1,23 +1,17 @@ import React from 'react' import { number, select, text } from '@storybook/addon-knobs' -import { COLORS, TYPOGRAPHY } from '../../../helpers/constants/design-system' +import { + COLORS, + FONT_WEIGHT, + TEXT_ALIGN, + TYPOGRAPHY, +} from '../../../helpers/constants/design-system' import Typography from '.' export default { title: 'Typography', } -const fontWeightOptions = { - bold: 'bold', - normal: 'normal', -} - -const alignOptions = { - left: undefined, - center: 'center', - right: 'right', -} - export const list = () => (
{Object.values(TYPOGRAPHY).map((variant) => ( @@ -26,8 +20,12 @@ export const list = () => ( variant={variant} color={select('color', COLORS, COLORS.BLACK)} spacing={number('spacing', 1, { range: true, min: 1, max: 8 })} - align={select('align', alignOptions, undefined)} - fontWeight={select('font weight', fontWeightOptions, 'normal')} + align={select('align', TEXT_ALIGN, undefined)} + fontWeight={select( + 'font weight', + Object.values(FONT_WEIGHT), + FONT_WEIGHT.NORMAL, + )} > {variant} @@ -43,8 +41,8 @@ export const TheQuickOrangeFox = () => ( color={select('color', COLORS, COLORS.BLACK)} variant={select('variant', TYPOGRAPHY, TYPOGRAPHY.Paragraph)} spacing={number('spacing', 1, { range: true, min: 1, max: 8 })} - align={select('align', alignOptions, undefined)} - fontWeight={select('font weight', fontWeightOptions, 'normal')} + align={select('align', TEXT_ALIGN, undefined)} + fontWeight={select('font weight', FONT_WEIGHT, FONT_WEIGHT.NORMAL)} > {text('content', 'The quick orange fox jumped over the lazy dog.')} diff --git a/ui/app/components/ui/ui-components.scss b/ui/app/components/ui/ui-components.scss index 2b76068d2..09382d2a3 100644 --- a/ui/app/components/ui/ui-components.scss +++ b/ui/app/components/ui/ui-components.scss @@ -2,6 +2,7 @@ @import 'account-mismatch-warning/index'; @import 'alert-circle-icon/index'; @import 'alert/index'; +@import 'box/box'; @import 'breadcrumbs/index'; @import 'button-group/index'; @import 'button/buttons'; diff --git a/ui/app/css/design-system/attributes.scss b/ui/app/css/design-system/attributes.scss new file mode 100644 index 000000000..2176cddb9 --- /dev/null +++ b/ui/app/css/design-system/attributes.scss @@ -0,0 +1,72 @@ +$align-items: + baseline, + center, + flex-end, + flex-start, + stretch; + +$justify-content: + center, + flex-end, + flex-start, + space-around, + space-between, + space-evenly; + +$fractions: ( + 1\/2: 50%, + 1\/3: 33.333333%, + 2\/3: 66.666667%, + 1\/4: 25%, + 2\/4: 50%, + 3\/4: 75%, + 1\/5: 20%, + 2\/5: 40%, + 3\/5: 60%, + 4\/5: 80%, + 1\/6: 16.666667%, + 2\/6: 33.333333%, + 3\/6: 50%, + 4\/6: 66.666667%, + 5\/6: 83.333333%, + 1\/12: 8.333333%, + 2\/12: 16.666667%, + 3\/12: 25%, + 4\/12: 33.333333%, + 5\/12: 41.666667%, + 6\/12: 50%, + 7\/12: 58.333333%, + 8\/12: 66.666667%, + 9\/12: 75%, + 10\/12: 83.333333%, + 11\/12: 91.666667%, +); + +$sizes-numeric: + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12; + +$sizes-strings: + xs, + sm, + md, + lg, + xl, + none; + +$border-style: solid, double, none, dashed, dotted; +$directions: top, right, bottom, left; +$display: block, grid, flex, inline-block, inline-grid, inline-flex, list-item; +$text-align: left, right, center, justify; +$font-weight: bold, normal, 100, 200, 300, 400, 500, 600, 700, 800, 900; diff --git a/ui/app/css/design-system/index.scss b/ui/app/css/design-system/index.scss index d4f8980b9..3d5e5e410 100644 --- a/ui/app/css/design-system/index.scss +++ b/ui/app/css/design-system/index.scss @@ -1,3 +1,4 @@ +@forward 'attributes'; @forward 'breakpoints'; @forward 'colors'; @forward 'deprecated-colors'; diff --git a/ui/app/css/design-system/typography.scss b/ui/app/css/design-system/typography.scss index 73ccab414..707170c24 100644 --- a/ui/app/css/design-system/typography.scss +++ b/ui/app/css/design-system/typography.scss @@ -82,11 +82,6 @@ $typography-variants: ( 'h9': 0.5rem, ); -$typography-font-weights: ( - 'bold': 700, - 'normal': 400, -); - $font-size-h1: map-get($typography-variants, 'h1'); $font-size-h2: map-get($typography-variants, 'h2'); $font-size-h3: map-get($typography-variants, 'h3'); diff --git a/ui/app/css/utilities/_spacing.scss b/ui/app/css/utilities/_spacing.scss new file mode 100644 index 000000000..ab87c3380 --- /dev/null +++ b/ui/app/css/utilities/_spacing.scss @@ -0,0 +1,7 @@ +$theme-spacing-value: 4px; + +@function get-spacing($spacing) { + $spacingInPx: $spacing * 4px; + + @return $spacingInPx; +} diff --git a/ui/app/css/utilities/index.scss b/ui/app/css/utilities/index.scss index 701193836..abbfed74a 100644 --- a/ui/app/css/utilities/index.scss +++ b/ui/app/css/utilities/index.scss @@ -1 +1,2 @@ @forward 'colors'; +@forward 'spacing'; diff --git a/ui/app/helpers/constants/design-system.js b/ui/app/helpers/constants/design-system.js index 288a1f0be..3663cd879 100644 --- a/ui/app/helpers/constants/design-system.js +++ b/ui/app/helpers/constants/design-system.js @@ -1,3 +1,9 @@ +/** + * A note about the existence of both singular and plural variable names here: + * When dealing with a literal property name, e.g. ALIGN_ITEMS, the constant + * should match the property. When detailing a collection of things, it should + * match the plural form of the thing. e.g. COLORS, TYPOGRAPHY + */ export const COLORS = { UI1: 'ui-1', UI2: 'ui-2', @@ -40,3 +46,111 @@ export const TYPOGRAPHY = { H9: 'h9', Paragraph: 'paragraph', } + +const NONE = 'none' + +export const SIZES = { + XS: 'xs', + SM: 'sm', + MD: 'md', + LG: 'lg', + XL: 'xl', + NONE, +} + +export const BORDER_STYLE = { + DASHED: 'dashed', + SOLID: 'solid', + DOTTED: 'dotted', + DOUBLE: 'double', + NONE, +} + +const FLEX_END = 'flex-end' +const FLEX_START = 'flex-start' +const CENTER = 'center' + +export const ALIGN_ITEMS = { + FLEX_START, + FLEX_END, + CENTER, + BASELINE: 'baseline', + STRETCH: 'stretch', +} + +export const JUSTIFY_CONTENT = { + FLEX_START, + FLEX_END, + CENTER, + SPACE_AROUND: 'space-around', + SPACE_BETWEEN: 'space-between', + SPACE_EVENLY: 'space-evenly', +} + +export const DISPLAY = { + BLOCK: 'block', + FLEX: 'flex', + GRID: 'grid', + INLINE_BLOCK: 'inline-block', + INLINE_FLEX: 'inline-flex', + INLINE_GRID: 'inline-grid', + LIST_ITEM: 'list-item', +} + +const FRACTIONS = { + HALF: '1/2', + ONE_THIRD: '1/3', + TWO_THIRDS: '2/3', + ONE_FOURTH: '1/4', + TWO_FOURTHS: '2/4', + THREE_FOURTHS: '3/4', + ONE_FIFTH: '1/5', + TWO_FIFTHS: '2/5', + THREE_FIFTHS: '3/5', + FOUR_FIFTHS: '4/5', + ONE_SIXTH: '1/6', + TWO_SIXTHS: '2/6', + THREE_SIXTHS: '3/6', + FOUR_SIXTHS: '4/6', + FIVE_SIXTHS: '5/6', + ONE_TWELFTH: '1/12', + TWO_TWELFTHS: '2/12', + THREE_TWELFTHS: '3/12', + FOUR_TWELFTHS: '4/12', + FIVE_TWELFTHS: '5/12', + SIX_TWELFTHS: '6/12', + SEVEN_TWELFTHS: '7/12', + EIGHT_TWELFTHS: '8/12', + NINE_TWELFTHS: '9/12', + TEN_TWELFTHS: '10/12', + ELEVEN_TWELFTHS: '11/12', +} + +export const BLOCK_SIZES = { + ...FRACTIONS, + SCREEN: 'screen', + MAX: 'max', + MIN: 'min', + FULL: 'full', +} + +export const TEXT_ALIGN = { + LEFT: 'left', + CENTER: 'center', + RIGHT: 'right', + JUSTIFY: 'justify', +} + +export const FONT_WEIGHT = { + BOLD: 'bold', + NORMAL: 'normal', + 100: 100, + 200: 200, + 300: 300, + 400: 400, + 500: 500, + 600: 600, + 700: 700, + 800: 800, + 900: 900, +} From 425ec6228cc1848f170fbf2157b12c6857054be3 Mon Sep 17 00:00:00 2001 From: Thomas Huang Date: Wed, 27 Jan 2021 22:44:04 -0800 Subject: [PATCH 04/48] Use nativeCurrency in the confirm approve screen (#10298) Gets nativeCurrency from state and uses in place of the previously hardcoded ETH value in the confirm approve component. --- .../confirm-approve-content.component.js | 4 +++- ui/app/pages/confirm-approve/confirm-approve.js | 7 ++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/ui/app/pages/confirm-approve/confirm-approve-content/confirm-approve-content.component.js b/ui/app/pages/confirm-approve/confirm-approve-content/confirm-approve-content.component.js index 5486776b7..78fe41fe7 100644 --- a/ui/app/pages/confirm-approve/confirm-approve-content/confirm-approve-content.component.js +++ b/ui/app/pages/confirm-approve/confirm-approve-content/confirm-approve-content.component.js @@ -24,6 +24,7 @@ export default class ConfirmApproveContent extends Component { data: PropTypes.string, toAddress: PropTypes.string, currentCurrency: PropTypes.string, + nativeCurrency: PropTypes.string, fiatTransactionTotal: PropTypes.string, ethTransactionTotal: PropTypes.string, } @@ -75,6 +76,7 @@ export default class ConfirmApproveContent extends Component { const { t } = this.context const { currentCurrency, + nativeCurrency, ethTransactionTotal, fiatTransactionTotal, } = this.props @@ -88,7 +90,7 @@ export default class ConfirmApproveContent extends Component { {formatCurrency(fiatTransactionTotal, currentCurrency)}
- {`${ethTransactionTotal} ETH`} + {`${ethTransactionTotal} ${nativeCurrency}`}
diff --git a/ui/app/pages/confirm-approve/confirm-approve.js b/ui/app/pages/confirm-approve/confirm-approve.js index e1109c473..9b8d7abde 100644 --- a/ui/app/pages/confirm-approve/confirm-approve.js +++ b/ui/app/pages/confirm-approve/confirm-approve.js @@ -14,11 +14,10 @@ import { getTokens } from '../../ducks/metamask/metamask' import { transactionFeeSelector, txDataSelector, -} from '../../selectors/confirm-transaction' -import { getCurrentCurrency, getDomainMetadata, -} from '../../selectors/selectors' + getNativeCurrency, +} from '../../selectors' import { currentNetworkTxListSelector } from '../../selectors/transactions' import { getCustomTxParamsData } from './confirm-approve.util' import ConfirmApproveContent from './confirm-approve-content' @@ -32,6 +31,7 @@ export default function ConfirmApprove() { } = useSelector(txDataSelector) const currentCurrency = useSelector(getCurrentCurrency) + const nativeCurrency = useSelector(getNativeCurrency) const currentNetworkTxList = useSelector(currentNetworkTxListSelector) const domainMetadata = useSelector(getDomainMetadata) const tokens = useSelector(getTokens) @@ -133,6 +133,7 @@ export default function ConfirmApprove() { data={customData || data} toAddress={toAddress} currentCurrency={currentCurrency} + nativeCurrency={nativeCurrency} ethTransactionTotal={ethTransactionTotal} fiatTransactionTotal={fiatTransactionTotal} /> From 419897cba6f76bb63e5a140763efa59e7b418df1 Mon Sep 17 00:00:00 2001 From: Brad Decker Date: Thu, 28 Jan 2021 09:54:02 -0600 Subject: [PATCH 05/48] Add Definition List component (#10291) --- ui/app/components/ui/box/box.js | 2 +- .../ui/definition-list/definition-list.js | 83 +++++++++++++++++++ .../ui/definition-list/definition-list.scss | 19 +++++ .../definition-list.stories.js | 69 +++++++++++++++ ui/app/components/ui/definition-list/index.js | 1 + ui/app/components/ui/typography/typography.js | 2 + ui/app/components/ui/ui-components.scss | 1 + 7 files changed, 176 insertions(+), 1 deletion(-) create mode 100644 ui/app/components/ui/definition-list/definition-list.js create mode 100644 ui/app/components/ui/definition-list/definition-list.scss create mode 100644 ui/app/components/ui/definition-list/definition-list.stories.js create mode 100644 ui/app/components/ui/definition-list/index.js diff --git a/ui/app/components/ui/box/box.js b/ui/app/components/ui/box/box.js index d8a630bad..85567e6c6 100644 --- a/ui/app/components/ui/box/box.js +++ b/ui/app/components/ui/box/box.js @@ -13,7 +13,7 @@ import { const ValidSize = PropTypes.oneOf([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]) const ArrayOfValidSizes = PropTypes.arrayOf(ValidSize) -const MultipleSizes = PropTypes.oneOf([ValidSize, ArrayOfValidSizes]) +const MultipleSizes = PropTypes.oneOfType([ValidSize, ArrayOfValidSizes]) function generateSizeClasses(baseClass, type, main, top, right, bottom, left) { const arr = Array.isArray(main) ? main : [] diff --git a/ui/app/components/ui/definition-list/definition-list.js b/ui/app/components/ui/definition-list/definition-list.js new file mode 100644 index 000000000..4be40cb1b --- /dev/null +++ b/ui/app/components/ui/definition-list/definition-list.js @@ -0,0 +1,83 @@ +import React from 'react' +import PropTypes from 'prop-types' +import { omit } from 'lodash' +import Typography from '../typography' +import { + COLORS, + SIZES, + TYPOGRAPHY, + FONT_WEIGHT, +} from '../../../helpers/constants/design-system' +import Tooltip from '../tooltip' + +const MARGIN_MAP = { + [SIZES.XS]: 0, + [SIZES.SM]: 2, + [SIZES.MD]: 4, + [SIZES.LG]: 6, + [SIZES.XL]: 8, +} + +export default function DefinitionList({ + dictionary, + termTypography = {}, + definitionTypography = {}, + tooltips = {}, + gapSize = SIZES.SM, +}) { + return ( +
+ {Object.entries(dictionary).map(([term, definition]) => ( + + + {term} + {tooltips[term] && ( + + + + )} + + + {definition} + + + ))} +
+ ) +} + +DefinitionList.propTypes = { + gapSize: PropTypes.oneOf(Object.values(SIZES)), + dictionary: PropTypes.objectOf(PropTypes.string), + tooltips: PropTypes.objectOf(PropTypes.string), + termTypography: PropTypes.shape({ + ...omit(Typography.propTypes, ['tag', 'className', 'boxProps']), + }), + definitionTypography: PropTypes.shape({ + ...omit(Typography.propTypes, ['tag', 'className', 'boxProps']), + }), +} diff --git a/ui/app/components/ui/definition-list/definition-list.scss b/ui/app/components/ui/definition-list/definition-list.scss new file mode 100644 index 000000000..bf154d194 --- /dev/null +++ b/ui/app/components/ui/definition-list/definition-list.scss @@ -0,0 +1,19 @@ +.definition-list { + $self: &; + + &__term { + display: flex; + align-items: center; + + & i { + color: $ui-3; + margin-left: 6px; + font-size: $font-size-h8; + } + + & #{$self}__tooltip-wrapper { + display: flex !important; + align-items: center; + } + } +} diff --git a/ui/app/components/ui/definition-list/definition-list.stories.js b/ui/app/components/ui/definition-list/definition-list.stories.js new file mode 100644 index 000000000..b833e71d3 --- /dev/null +++ b/ui/app/components/ui/definition-list/definition-list.stories.js @@ -0,0 +1,69 @@ +import React from 'react' +import { object, select } from '@storybook/addon-knobs' +import { + COLORS, + SIZES, + TYPOGRAPHY, +} from '../../../helpers/constants/design-system' +import DefinitionList from './definition-list' + +export default { + title: 'Definition List', +} + +const basic = { + term: + 'a word or phrase used to describe a thing or to express a concept, especially in a particular kind of language or branch of study.', + definition: + 'a statement of the exact meaning of a word, especially in a dictionary.', + dl: 'HTML tag denoting a definition list', + dt: 'HTML tag denoting a definition list term', + dd: 'HTML tag denoting a definition list definition', +} + +const advanced = { + 'Network Name': 'Ethereum Mainnet', + 'Chain ID': '1', + Ticker: 'ETH', +} + +const tooltips = { + 'Network Name': 'The name that is associated with this network', + 'Chain ID': 'The numeric value representing the ID of this network', + Ticker: 'The currency symbol of the primary currency for this network', +} + +export const definitionList = () => ( + +) + +export const withTooltips = () => ( + +) + +export const withTypographyControl = () => ( + +) diff --git a/ui/app/components/ui/definition-list/index.js b/ui/app/components/ui/definition-list/index.js new file mode 100644 index 000000000..a321da7a8 --- /dev/null +++ b/ui/app/components/ui/definition-list/index.js @@ -0,0 +1 @@ +export { default } from './definition-list' diff --git a/ui/app/components/ui/typography/typography.js b/ui/app/components/ui/typography/typography.js index f3ea8fac7..c6ca4afe8 100644 --- a/ui/app/components/ui/typography/typography.js +++ b/ui/app/components/ui/typography/typography.js @@ -69,5 +69,7 @@ Typography.propTypes = { 'h6', 'span', 'div', + 'dt', + 'dd', ]), } diff --git a/ui/app/components/ui/ui-components.scss b/ui/app/components/ui/ui-components.scss index 09382d2a3..3f01126d2 100644 --- a/ui/app/components/ui/ui-components.scss +++ b/ui/app/components/ui/ui-components.scss @@ -13,6 +13,7 @@ @import 'color-indicator/color-indicator'; @import 'currency-display/index'; @import 'currency-input/index'; +@import 'definition-list/definition-list'; @import 'dialog/dialog'; @import 'dropdown/dropdown'; @import 'editable-label/index'; From ecff9dfcb01953fb70a7c12cea458a3a99bb97d9 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Thu, 28 Jan 2021 13:47:26 -0330 Subject: [PATCH 06/48] Remove unused transaction base props (#10295) These props were never given. They have been removed to simplify the component. --- ...onfirm-page-container-content.component.js | 35 +-- ...onfirm-page-container-summary.component.js | 4 +- .../confirm-page-container.component.js | 6 - .../confirm-transaction-base.component.js | 277 +++++++----------- 4 files changed, 124 insertions(+), 198 deletions(-) diff --git a/ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-content.component.js b/ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-content.component.js index 9a6c3f5c5..affda4c12 100644 --- a/ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-content.component.js +++ b/ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-content.component.js @@ -17,9 +17,7 @@ export default class ConfirmPageContainerContent extends Component { identiconAddress: PropTypes.string, nonce: PropTypes.string, assetImage: PropTypes.string, - subtitle: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), subtitleComponent: PropTypes.node, - summaryComponent: PropTypes.node, title: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), titleComponent: PropTypes.node, warning: PropTypes.string, @@ -65,13 +63,11 @@ export default class ConfirmPageContainerContent extends Component { errorMessage, title, titleComponent, - subtitle, subtitleComponent, hideSubtitle, identiconAddress, nonce, assetImage, - summaryComponent, detailsComponent, dataComponent, warning, @@ -88,23 +84,20 @@ export default class ConfirmPageContainerContent extends Component { return (
{warning && } - {summaryComponent || ( - - )} + {this.renderContent()} {(errorKey || errorMessage) && (
diff --git a/ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-summary/confirm-page-container-summary.component.js b/ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-summary/confirm-page-container-summary.component.js index dfa7b63fb..94c3e4279 100644 --- a/ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-summary/confirm-page-container-summary.component.js +++ b/ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-summary/confirm-page-container-summary.component.js @@ -8,7 +8,6 @@ const ConfirmPageContainerSummary = (props) => { action, title, titleComponent, - subtitle, subtitleComponent, hideSubtitle, className, @@ -42,7 +41,7 @@ const ConfirmPageContainerSummary = (props) => {
{hideSubtitle || (
- {subtitleComponent || subtitle} + {subtitleComponent}
)}
@@ -53,7 +52,6 @@ ConfirmPageContainerSummary.propTypes = { action: PropTypes.string, title: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), titleComponent: PropTypes.node, - subtitle: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), subtitleComponent: PropTypes.node, hideSubtitle: PropTypes.bool, className: PropTypes.string, diff --git a/ui/app/components/app/confirm-page-container/confirm-page-container.component.js b/ui/app/components/app/confirm-page-container/confirm-page-container.component.js index 45c32b3b6..69f8fdc33 100644 --- a/ui/app/components/app/confirm-page-container/confirm-page-container.component.js +++ b/ui/app/components/app/confirm-page-container/confirm-page-container.component.js @@ -19,7 +19,6 @@ export default class ConfirmPageContainer extends Component { hideSubtitle: PropTypes.bool, onEdit: PropTypes.func, showEdit: PropTypes.bool, - subtitle: PropTypes.string, subtitleComponent: PropTypes.node, title: PropTypes.string, titleComponent: PropTypes.node, @@ -41,7 +40,6 @@ export default class ConfirmPageContainer extends Component { identiconAddress: PropTypes.string, nonce: PropTypes.string, assetImage: PropTypes.string, - summaryComponent: PropTypes.node, warning: PropTypes.string, unapprovedTxCount: PropTypes.number, // Navigation @@ -79,10 +77,8 @@ export default class ConfirmPageContainer extends Component { action, title, titleComponent, - subtitle, subtitleComponent, hideSubtitle, - summaryComponent, detailsComponent, dataComponent, onCancelAll, @@ -146,10 +142,8 @@ export default class ConfirmPageContainer extends Component { action={action} title={title} titleComponent={titleComponent} - subtitle={subtitle} subtitleComponent={subtitleComponent} hideSubtitle={hideSubtitle} - summaryComponent={summaryComponent} detailsComponent={detailsComponent} dataComponent={dataComponent} errorMessage={errorMessage} diff --git a/ui/app/pages/confirm-transaction-base/confirm-transaction-base.component.js b/ui/app/pages/confirm-transaction-base/confirm-transaction-base.component.js index 0b7d82ae0..ec079c3da 100644 --- a/ui/app/pages/confirm-transaction-base/confirm-transaction-base.component.js +++ b/ui/app/pages/confirm-transaction-base/confirm-transaction-base.component.js @@ -70,31 +70,19 @@ export default class ConfirmTransactionBase extends Component { actionKey: PropTypes.string, contentComponent: PropTypes.node, dataComponent: PropTypes.node, - detailsComponent: PropTypes.node, - errorKey: PropTypes.string, - errorMessage: PropTypes.string, primaryTotalTextOverride: PropTypes.oneOfType([ PropTypes.string, PropTypes.node, ]), secondaryTotalTextOverride: PropTypes.string, hideData: PropTypes.bool, - hideDetails: PropTypes.bool, hideSubtitle: PropTypes.bool, identiconAddress: PropTypes.string, - onCancel: PropTypes.func, onEdit: PropTypes.func, - onEditGas: PropTypes.func, - onSubmit: PropTypes.func, setMetaMetricsSendCount: PropTypes.func, metaMetricsSendCount: PropTypes.number, - subtitle: PropTypes.string, subtitleComponent: PropTypes.node, - summaryComponent: PropTypes.node, title: PropTypes.string, - titleComponent: PropTypes.node, - valid: PropTypes.bool, - warning: PropTypes.string, advancedInlineGasShown: PropTypes.bool, insufficientBalance: PropTypes.bool, hideFiatConversion: PropTypes.bool, @@ -212,7 +200,6 @@ export default class ConfirmTransactionBase extends Component { handleEditGas() { const { - onEditGas, showCustomizeGasModal, actionKey, txData: { origin }, @@ -235,21 +222,15 @@ export default class ConfirmTransactionBase extends Component { }, }) - if (onEditGas) { - onEditGas() - } else { - showCustomizeGasModal() - } + showCustomizeGasModal() } renderDetails() { const { - detailsComponent, primaryTotalTextOverride, secondaryTotalTextOverride, hexTransactionFee, hexTransactionTotal, - hideDetails, useNonceField, customNonceValue, updateCustomNonce, @@ -263,100 +244,90 @@ export default class ConfirmTransactionBase extends Component { isMainnet, } = this.props - if (hideDetails) { - return null - } - const notMainnetOrTest = !(isMainnet || process.env.IN_TEST) return ( - detailsComponent || ( -
-
- this.handleEditGas() - } - secondaryText={ - hideFiatConversion - ? this.context.t('noConversionRateAvailable') - : '' - } - /> - {advancedInlineGasShown || notMainnetOrTest ? ( - - updateGasAndCalculate({ ...customGas, gasPrice: newGasPrice }) - } - updateCustomGasLimit={(newGasLimit) => - updateGasAndCalculate({ ...customGas, gasLimit: newGasLimit }) - } - customGasPrice={customGas.gasPrice} - customGasLimit={customGas.gasLimit} - insufficientBalance={insufficientBalance} - customPriceIsSafe - isSpeedUp={false} - /> - ) : null} -
-
+
+ - this.handleEditGas()} + secondaryText={ + hideFiatConversion + ? this.context.t('noConversionRateAvailable') + : '' + } + /> + {advancedInlineGasShown || notMainnetOrTest ? ( + + updateGasAndCalculate({ ...customGas, gasPrice: newGasPrice }) } - headerText="Amount + Gas Fee" - headerTextClassName="confirm-detail-row__header-text--total" - primaryValueTextColor="#2f9ae0" + updateCustomGasLimit={(newGasLimit) => + updateGasAndCalculate({ ...customGas, gasLimit: newGasLimit }) + } + customGasPrice={customGas.gasPrice} + customGasLimit={customGas.gasLimit} + insufficientBalance={insufficientBalance} + customPriceIsSafe + isSpeedUp={false} /> -
- {useNonceField ? ( -
-
-
- {this.context.t('nonceFieldHeading')} -
-
- { - if (!value.length || Number(value) < 0) { - updateCustomNonce('') - } else { - updateCustomNonce(String(Math.floor(value))) - } - getNextNonce() - }} - fullWidth - margin="dense" - value={customNonceValue || ''} - /> -
-
-
) : null}
- ) +
+ +
+ {useNonceField ? ( +
+
+
+ {this.context.t('nonceFieldHeading')} +
+
+ { + if (!value.length || Number(value) < 0) { + updateCustomNonce('') + } else { + updateCustomNonce(String(Math.floor(value))) + } + getNextNonce() + }} + fullWidth + margin="dense" + value={customNonceValue || ''} + /> +
+
+
+ ) : null} +
) } @@ -455,7 +426,6 @@ export default class ConfirmTransactionBase extends Component { handleCancel() { const { metricsEvent } = this.context const { - onCancel, txData, cancelTransaction, history, @@ -484,14 +454,10 @@ export default class ConfirmTransactionBase extends Component { }, }) updateCustomNonce('') - if (onCancel) { - onCancel(txData) - } else { - cancelTransaction(txData).then(() => { - clearConfirmTransaction() - history.push(mostRecentOverviewPage) - }) - } + cancelTransaction(txData).then(() => { + clearConfirmTransaction() + history.push(mostRecentOverviewPage) + }) } handleSubmit() { @@ -502,7 +468,6 @@ export default class ConfirmTransactionBase extends Component { clearConfirmTransaction, txData, history, - onSubmit, actionKey, mostRecentOverviewPage, metaMetricsSendCount = 0, @@ -540,42 +505,33 @@ export default class ConfirmTransactionBase extends Component { }) setMetaMetricsSendCount(metaMetricsSendCount + 1).then(() => { - if (onSubmit) { - Promise.resolve(onSubmit(txData)).then(() => { + sendTransaction(txData) + .then(() => { + clearConfirmTransaction() + this.setState( + { + submitting: false, + }, + () => { + history.push(mostRecentOverviewPage) + updateCustomNonce('') + }, + ) + }) + .catch((error) => { this.setState({ submitting: false, + submitError: error.message, }) updateCustomNonce('') }) - } else { - sendTransaction(txData) - .then(() => { - clearConfirmTransaction() - this.setState( - { - submitting: false, - }, - () => { - history.push(mostRecentOverviewPage) - updateCustomNonce('') - }, - ) - }) - .catch((error) => { - this.setState({ - submitting: false, - submitError: error.message, - }) - updateCustomNonce('') - }) - } }) }, ) } renderTitleComponent() { - const { title, titleComponent, hexTransactionAmount } = this.props + const { title, hexTransactionAmount } = this.props // Title string passed in by props takes priority if (title) { @@ -583,25 +539,18 @@ export default class ConfirmTransactionBase extends Component { } return ( - titleComponent || ( - - ) + ) } renderSubtitleComponent() { - const { subtitle, subtitleComponent, hexTransactionAmount } = this.props - - // Subtitle string passed in by props takes priority - if (subtitle) { - return null - } + const { subtitleComponent, hexTransactionAmount } = this.props return ( subtitleComponent || ( @@ -708,20 +657,14 @@ export default class ConfirmTransactionBase extends Component { toEns, toNickname, methodData, - valid: propsValid = true, - errorMessage, - errorKey: propsErrorKey, title, - subtitle, hideSubtitle, identiconAddress, - summaryComponent, contentComponent, onEdit, nonce, customNonceValue, assetImage, - warning, unapprovedTxCount, transactionCategory, hideSenderToRecipient, @@ -765,10 +708,8 @@ export default class ConfirmTransactionBase extends Component { action={functionType} title={title} titleComponent={this.renderTitleComponent()} - subtitle={subtitle} subtitleComponent={this.renderSubtitleComponent()} hideSubtitle={hideSubtitle} - summaryComponent={summaryComponent} detailsComponent={this.renderDetails()} dataComponent={this.renderData(functionType)} contentComponent={contentComponent} @@ -776,9 +717,9 @@ export default class ConfirmTransactionBase extends Component { unapprovedTxCount={unapprovedTxCount} assetImage={assetImage} identiconAddress={identiconAddress} - errorMessage={errorMessage || submitError} - errorKey={propsErrorKey || errorKey} - warning={warning || submitWarning} + errorMessage={submitError} + errorKey={errorKey} + warning={submitWarning} totalTx={totalTx} positionOfCurrentTx={positionOfCurrentTx} nextTxId={nextTxId} @@ -789,7 +730,7 @@ export default class ConfirmTransactionBase extends Component { lastTx={lastTx} ofText={ofText} requestsWaitingText={requestsWaitingText} - disabled={!propsValid || !valid || submitting} + disabled={!valid || submitting} onEdit={() => this.handleEdit()} onCancelAll={() => this.handleCancelAll()} onCancel={() => this.handleCancel()} From 471140fdea72dcf52c2fce4c9b30540cffc166f9 Mon Sep 17 00:00:00 2001 From: Brad Decker Date: Thu, 28 Jan 2021 11:22:37 -0600 Subject: [PATCH 07/48] Add Truncated Definition List (#10292) --- app/_locales/en/messages.json | 3 + .../ui/truncated-definition-list/index.js | 1 + .../truncated-definition-list.js | 78 +++++++++++++++++++ .../truncated-definition-list.scss | 9 +++ .../truncated-definition-list.stories.js | 47 +++++++++++ ui/app/components/ui/ui-components.scss | 1 + 6 files changed, 139 insertions(+) create mode 100644 ui/app/components/ui/truncated-definition-list/index.js create mode 100644 ui/app/components/ui/truncated-definition-list/truncated-definition-list.js create mode 100644 ui/app/components/ui/truncated-definition-list/truncated-definition-list.scss create mode 100644 ui/app/components/ui/truncated-definition-list/truncated-definition-list.stories.js diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index e6ff6ed73..9cd0c2161 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -2086,6 +2086,9 @@ "viewAccount": { "message": "View Account" }, + "viewAllDetails": { + "message": "View all details" + }, "viewContact": { "message": "View Contact" }, diff --git a/ui/app/components/ui/truncated-definition-list/index.js b/ui/app/components/ui/truncated-definition-list/index.js new file mode 100644 index 000000000..427109d63 --- /dev/null +++ b/ui/app/components/ui/truncated-definition-list/index.js @@ -0,0 +1 @@ +export { default } from './truncated-definition-list' diff --git a/ui/app/components/ui/truncated-definition-list/truncated-definition-list.js b/ui/app/components/ui/truncated-definition-list/truncated-definition-list.js new file mode 100644 index 000000000..356f1aed1 --- /dev/null +++ b/ui/app/components/ui/truncated-definition-list/truncated-definition-list.js @@ -0,0 +1,78 @@ +import { pick } from 'lodash' +import React, { useState } from 'react' +import PropTypes from 'prop-types' +import { COLORS, SIZES } from '../../../helpers/constants/design-system' +import Box from '../box' +import Button from '../button' +import DefinitionList from '../definition-list/definition-list' +import Popover from '../popover' +import { useI18nContext } from '../../../hooks/useI18nContext' + +export default function TruncatedDefinitionList({ + dictionary, + tooltips, + prefaceKeys, + title, +}) { + const [isPopoverOpen, setIsPopoverOpen] = useState(false) + const t = useI18nContext() + + return ( + <> + + + + + {isPopoverOpen && ( + setIsPopoverOpen(false)} + footer={ + <> +
+ + + } + > + + + + + )} + + ) +} + +TruncatedDefinitionList.propTypes = { + dictionary: DefinitionList.propTypes.dictionary, + tooltips: DefinitionList.propTypes.dictionary, + title: PropTypes.string, + prefaceKeys: PropTypes.arrayOf(PropTypes.string), +} diff --git a/ui/app/components/ui/truncated-definition-list/truncated-definition-list.scss b/ui/app/components/ui/truncated-definition-list/truncated-definition-list.scss new file mode 100644 index 000000000..599d91e23 --- /dev/null +++ b/ui/app/components/ui/truncated-definition-list/truncated-definition-list.scss @@ -0,0 +1,9 @@ +.truncated-definition-list { + &__view-more { + @include H6; + + display: inline-block; + padding: 0; + width: auto; + } +} diff --git a/ui/app/components/ui/truncated-definition-list/truncated-definition-list.stories.js b/ui/app/components/ui/truncated-definition-list/truncated-definition-list.stories.js new file mode 100644 index 000000000..68101ef0d --- /dev/null +++ b/ui/app/components/ui/truncated-definition-list/truncated-definition-list.stories.js @@ -0,0 +1,47 @@ +import React from 'react' +import { object, text } from '@storybook/addon-knobs' + +import TruncatedDefinitionList from './truncated-definition-list' + +export default { + title: 'Truncated Definition List', +} + +const basic = { + term: + 'a word or phrase used to describe a thing or to express a concept, especially in a particular kind of language or branch of study.', + definition: + 'a statement of the exact meaning of a word, especially in a dictionary.', + dl: 'HTML tag denoting a definition list', + dt: 'HTML tag denoting a definition list term', + dd: 'HTML tag denoting a definition list definition', +} + +const advanced = { + 'Network Name': 'Ethereum Mainnet', + 'Chain ID': '1', + Ticker: 'ETH', +} + +const tooltips = { + 'Network Name': 'The name that is associated with this network', + 'Chain ID': 'The numeric value representing the ID of this network', + Ticker: 'The currency symbol of the primary currency for this network', +} + +export const truncatedDefinitionList = () => ( + +) + +export const withTooltips = () => ( + +) diff --git a/ui/app/components/ui/ui-components.scss b/ui/app/components/ui/ui-components.scss index 3f01126d2..f2fd4c5b0 100644 --- a/ui/app/components/ui/ui-components.scss +++ b/ui/app/components/ui/ui-components.scss @@ -42,6 +42,7 @@ @import 'toggle-button/index'; @import 'token-balance/index'; @import 'tooltip/index'; +@import 'truncated-definition-list/truncated-definition-list'; @import 'typography/typography'; @import 'unit-input/index'; @import 'url-icon/index'; From d8993883b7f50d17450319498cc6227ddd569398 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Thu, 28 Jan 2021 14:29:25 -0330 Subject: [PATCH 08/48] Add origin to signature request confirmation page (#10300) Fixes #6071 The origin of the dapp that suggested signing has been added to the signature request confirmation page. This only applies to `eth_sign`, `personal_sign`, `eth_signTypedData`, and `eth_signTypedData_v1`. The confirmation page for `eth_signTypedData_v3` and `eth_signTypedData_v4` already featured the origin. --- app/_locales/am/messages.json | 3 -- app/_locales/ar/messages.json | 3 -- app/_locales/bg/messages.json | 3 -- app/_locales/bn/messages.json | 3 -- app/_locales/ca/messages.json | 3 -- app/_locales/cs/messages.json | 3 -- app/_locales/da/messages.json | 3 -- app/_locales/de/messages.json | 3 -- app/_locales/el/messages.json | 3 -- app/_locales/en/messages.json | 3 -- app/_locales/es/messages.json | 3 -- app/_locales/es_419/messages.json | 3 -- app/_locales/et/messages.json | 3 -- app/_locales/fa/messages.json | 3 -- app/_locales/fi/messages.json | 3 -- app/_locales/fil/messages.json | 3 -- app/_locales/fr/messages.json | 3 -- app/_locales/he/messages.json | 3 -- app/_locales/hi/messages.json | 3 -- app/_locales/hn/messages.json | 3 -- app/_locales/hr/messages.json | 3 -- app/_locales/ht/messages.json | 3 -- app/_locales/hu/messages.json | 3 -- app/_locales/id/messages.json | 3 -- app/_locales/it/messages.json | 3 -- app/_locales/ja/messages.json | 3 -- app/_locales/kn/messages.json | 3 -- app/_locales/ko/messages.json | 3 -- app/_locales/lt/messages.json | 3 -- app/_locales/lv/messages.json | 3 -- app/_locales/ms/messages.json | 3 -- app/_locales/nl/messages.json | 3 -- app/_locales/no/messages.json | 3 -- app/_locales/ph/messages.json | 3 -- app/_locales/pl/messages.json | 3 -- app/_locales/pt/messages.json | 3 -- app/_locales/pt_BR/messages.json | 3 -- app/_locales/ro/messages.json | 3 -- app/_locales/ru/messages.json | 3 -- app/_locales/sk/messages.json | 3 -- app/_locales/sl/messages.json | 3 -- app/_locales/sr/messages.json | 3 -- app/_locales/sv/messages.json | 3 -- app/_locales/sw/messages.json | 3 -- app/_locales/ta/messages.json | 3 -- app/_locales/th/messages.json | 3 -- app/_locales/tr/messages.json | 3 -- app/_locales/uk/messages.json | 3 -- app/_locales/vi/messages.json | 3 -- app/_locales/zh_CN/messages.json | 3 -- app/_locales/zh_TW/messages.json | 3 -- .../app/signature-request-original/index.scss | 21 ++++++++------ .../signature-request-original.component.js | 29 +++++++++++++++---- .../signature-request-original.container.js | 2 ++ 54 files changed, 38 insertions(+), 167 deletions(-) diff --git a/app/_locales/am/messages.json b/app/_locales/am/messages.json index 227bbcb84..af0f3c78c 100644 --- a/app/_locales/am/messages.json +++ b/app/_locales/am/messages.json @@ -1253,9 +1253,6 @@ "yourPrivateSeedPhrase": { "message": "የግል ዘር ሐረግዎ" }, - "yourSigRequested": { - "message": "ፊርማዎ እየተጠየቀ ነው" - }, "zeroGasPriceOnSpeedUpError": { "message": "በስፒድ አፕ ላይ ዜሮ የነዳጅ ዋጋ" } diff --git a/app/_locales/ar/messages.json b/app/_locales/ar/messages.json index 39a3df7c0..8edd9482f 100644 --- a/app/_locales/ar/messages.json +++ b/app/_locales/ar/messages.json @@ -1249,9 +1249,6 @@ "yourPrivateSeedPhrase": { "message": "عبارة الأمان الشخصية الخاصة بك" }, - "yourSigRequested": { - "message": "جاري طلب توقيعك" - }, "zeroGasPriceOnSpeedUpError": { "message": "سعر الغاز صفر عند التعجيل" } diff --git a/app/_locales/bg/messages.json b/app/_locales/bg/messages.json index ec998b1ce..f06f2e39e 100644 --- a/app/_locales/bg/messages.json +++ b/app/_locales/bg/messages.json @@ -1252,9 +1252,6 @@ "yourPrivateSeedPhrase": { "message": "Вашата лична фраза зародиш" }, - "yourSigRequested": { - "message": "Изисква се вашият подпис" - }, "zeroGasPriceOnSpeedUpError": { "message": "Нулева цена на газ при ускоряване" } diff --git a/app/_locales/bn/messages.json b/app/_locales/bn/messages.json index 2840c8470..fc2b72108 100644 --- a/app/_locales/bn/messages.json +++ b/app/_locales/bn/messages.json @@ -1256,9 +1256,6 @@ "yourPrivateSeedPhrase": { "message": "আপনার ব্যক্তিগত সীড ফ্রেজ" }, - "yourSigRequested": { - "message": "আপনার স্বাক্ষরের অনুরোধ জানানো হয়েছে" - }, "zeroGasPriceOnSpeedUpError": { "message": "স্পীড আপ এ শূণ্য গ্যাসের মূল্য" } diff --git a/app/_locales/ca/messages.json b/app/_locales/ca/messages.json index 571da2f5f..f8bd80055 100644 --- a/app/_locales/ca/messages.json +++ b/app/_locales/ca/messages.json @@ -1225,9 +1225,6 @@ "yourPrivateSeedPhrase": { "message": "La teva frase privada de seeds" }, - "yourSigRequested": { - "message": "Es necessita la teva firma" - }, "zeroGasPriceOnSpeedUpError": { "message": "Gas a cost zero accelerant-se" } diff --git a/app/_locales/cs/messages.json b/app/_locales/cs/messages.json index 4dc29f2a3..0fe5b7b48 100644 --- a/app/_locales/cs/messages.json +++ b/app/_locales/cs/messages.json @@ -464,8 +464,5 @@ }, "youSign": { "message": "Podepisujete" - }, - "yourSigRequested": { - "message": "Je vyžadován váš podpis" } } diff --git a/app/_locales/da/messages.json b/app/_locales/da/messages.json index f4765f987..99f0df45b 100644 --- a/app/_locales/da/messages.json +++ b/app/_locales/da/messages.json @@ -1225,9 +1225,6 @@ "yourPrivateSeedPhrase": { "message": "Din private seed-sætning" }, - "yourSigRequested": { - "message": "Din signatur er ønsket" - }, "zeroGasPriceOnSpeedUpError": { "message": "Nul brændstofpris på fremskynding" } diff --git a/app/_locales/de/messages.json b/app/_locales/de/messages.json index bfd714822..1bc83610d 100644 --- a/app/_locales/de/messages.json +++ b/app/_locales/de/messages.json @@ -1213,9 +1213,6 @@ "yourPrivateSeedPhrase": { "message": "Ihr privater Seed-Schlüssel" }, - "yourSigRequested": { - "message": "Deine Unterschrift wird angefordert" - }, "zeroGasPriceOnSpeedUpError": { "message": "Keine Gaskosten bei Beschleunigung" } diff --git a/app/_locales/el/messages.json b/app/_locales/el/messages.json index eab1d1077..5b7e9e6b4 100644 --- a/app/_locales/el/messages.json +++ b/app/_locales/el/messages.json @@ -1250,9 +1250,6 @@ "yourPrivateSeedPhrase": { "message": "Η προσωπική σας φράση φύτρου" }, - "yourSigRequested": { - "message": "Ζητείται η υπογραφή σας" - }, "zeroGasPriceOnSpeedUpError": { "message": "Μηδενική τιμή καυσίμου κατά την επιτάχυνση" } diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index 9cd0c2161..affb60904 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -2142,9 +2142,6 @@ "yourPrivateSeedPhrase": { "message": "Your private seed phrase" }, - "yourSigRequested": { - "message": "Your signature is being requested" - }, "zeroGasPriceOnSpeedUpError": { "message": "Zero gas price on speed up" } diff --git a/app/_locales/es/messages.json b/app/_locales/es/messages.json index 55f77bb00..20b7ef950 100644 --- a/app/_locales/es/messages.json +++ b/app/_locales/es/messages.json @@ -985,9 +985,6 @@ "yourPrivateSeedPhrase": { "message": "Tu frase semilla privada" }, - "yourSigRequested": { - "message": "Tu firma ya fue solicitada" - }, "zeroGasPriceOnSpeedUpError": { "message": "No hubo precio de gas al agilizar" } diff --git a/app/_locales/es_419/messages.json b/app/_locales/es_419/messages.json index 1073b7e31..1cf13ed44 100644 --- a/app/_locales/es_419/messages.json +++ b/app/_locales/es_419/messages.json @@ -1235,9 +1235,6 @@ "yourPrivateSeedPhrase": { "message": "Tu frase de inicialización privada" }, - "yourSigRequested": { - "message": "Su firma se está procesando" - }, "zeroGasPriceOnSpeedUpError": { "message": "El precio del gas es cero en aceleración" } diff --git a/app/_locales/et/messages.json b/app/_locales/et/messages.json index 681daaac3..1fc296d7c 100644 --- a/app/_locales/et/messages.json +++ b/app/_locales/et/messages.json @@ -1246,9 +1246,6 @@ "yourPrivateSeedPhrase": { "message": "Teie privaatne seemnefraas" }, - "yourSigRequested": { - "message": "Taotletakse teie allkirja" - }, "zeroGasPriceOnSpeedUpError": { "message": "Null gaasihind kiirendamisel" } diff --git a/app/_locales/fa/messages.json b/app/_locales/fa/messages.json index 15cb8b997..2a95dd796 100644 --- a/app/_locales/fa/messages.json +++ b/app/_locales/fa/messages.json @@ -1256,9 +1256,6 @@ "yourPrivateSeedPhrase": { "message": "عبارت بازیاب شخصی شما" }, - "yourSigRequested": { - "message": "امضاء شما درخواست میشود" - }, "zeroGasPriceOnSpeedUpError": { "message": "قیمت صفر گاز بسوی سرعت" } diff --git a/app/_locales/fi/messages.json b/app/_locales/fi/messages.json index 1aa3be909..5f96b1c77 100644 --- a/app/_locales/fi/messages.json +++ b/app/_locales/fi/messages.json @@ -1253,9 +1253,6 @@ "yourPrivateSeedPhrase": { "message": "Sinun yksityinen siemenlauseesi" }, - "yourSigRequested": { - "message": "Allekirjoitustasi pyydetään" - }, "zeroGasPriceOnSpeedUpError": { "message": "Polttoaine ei maksa kiihdytyksen yhteydessä" } diff --git a/app/_locales/fil/messages.json b/app/_locales/fil/messages.json index fa048b96d..0b4123370 100644 --- a/app/_locales/fil/messages.json +++ b/app/_locales/fil/messages.json @@ -1147,9 +1147,6 @@ "yourPrivateSeedPhrase": { "message": "Ang iyong pribadong seed phrase" }, - "yourSigRequested": { - "message": "Hinihiling ang iyong signature" - }, "zeroGasPriceOnSpeedUpError": { "message": "Zero ang presyo ng gas sa speed up" } diff --git a/app/_locales/fr/messages.json b/app/_locales/fr/messages.json index 0789b71d4..19c613762 100644 --- a/app/_locales/fr/messages.json +++ b/app/_locales/fr/messages.json @@ -1232,9 +1232,6 @@ "yourPrivateSeedPhrase": { "message": "Votre phrase Seed privée" }, - "yourSigRequested": { - "message": "Votre signature est demandée" - }, "zeroGasPriceOnSpeedUpError": { "message": "Prix de l'essence zéro sur l'accélération" } diff --git a/app/_locales/he/messages.json b/app/_locales/he/messages.json index 71900e7e7..b53fc791a 100644 --- a/app/_locales/he/messages.json +++ b/app/_locales/he/messages.json @@ -1250,9 +1250,6 @@ "yourPrivateSeedPhrase": { "message": "ה-seed phrase הפרטי שלך" }, - "yourSigRequested": { - "message": "נדרשת חתימתך" - }, "zeroGasPriceOnSpeedUpError": { "message": "מחיר גז אפס על האצה" } diff --git a/app/_locales/hi/messages.json b/app/_locales/hi/messages.json index 705e55057..e47d4ec18 100644 --- a/app/_locales/hi/messages.json +++ b/app/_locales/hi/messages.json @@ -2096,9 +2096,6 @@ "yourPrivateSeedPhrase": { "message": "आपका निजी सीड फ्रेज़" }, - "yourSigRequested": { - "message": "आपके हस्ताक्षर का अनुरोध किया जा रहा है" - }, "zeroGasPriceOnSpeedUpError": { "message": "ज़ीरो गैस मूल्य में तेज़ी" } diff --git a/app/_locales/hn/messages.json b/app/_locales/hn/messages.json index 4f7ae72af..106db04cb 100644 --- a/app/_locales/hn/messages.json +++ b/app/_locales/hn/messages.json @@ -423,8 +423,5 @@ }, "youSign": { "message": "आप हस्ताक्षर कर रहे हैं" - }, - "yourSigRequested": { - "message": "आपका हस्ताक्षर अनुरोध किया जा रहा है" } } diff --git a/app/_locales/hr/messages.json b/app/_locales/hr/messages.json index 42ffcb611..72e6f3945 100644 --- a/app/_locales/hr/messages.json +++ b/app/_locales/hr/messages.json @@ -1246,9 +1246,6 @@ "yourPrivateSeedPhrase": { "message": "Vaša privatna početna rečenica" }, - "yourSigRequested": { - "message": "Vaš se potpis zahtijeva" - }, "zeroGasPriceOnSpeedUpError": { "message": "Nulta cijena goriva kod ubrzavanja" } diff --git a/app/_locales/ht/messages.json b/app/_locales/ht/messages.json index 1fdfa5843..289501561 100644 --- a/app/_locales/ht/messages.json +++ b/app/_locales/ht/messages.json @@ -780,8 +780,5 @@ }, "yourPrivateSeedPhrase": { "message": "Seed fraz prive ou a" - }, - "yourSigRequested": { - "message": "Yo mande siyati ou" } } diff --git a/app/_locales/hu/messages.json b/app/_locales/hu/messages.json index cf3dda940..ce3ae6148 100644 --- a/app/_locales/hu/messages.json +++ b/app/_locales/hu/messages.json @@ -1246,9 +1246,6 @@ "yourPrivateSeedPhrase": { "message": "Az ön privát seed mondata" }, - "yourSigRequested": { - "message": "Szükség van az aláírására" - }, "zeroGasPriceOnSpeedUpError": { "message": "Nulla gázár a gyorsuláshoz" } diff --git a/app/_locales/id/messages.json b/app/_locales/id/messages.json index da00b134a..98bdb19ba 100644 --- a/app/_locales/id/messages.json +++ b/app/_locales/id/messages.json @@ -1231,9 +1231,6 @@ "yourPrivateSeedPhrase": { "message": "Frase benih pribadi Anda" }, - "yourSigRequested": { - "message": "Tanda tangan Anda sedang diminta" - }, "zeroGasPriceOnSpeedUpError": { "message": "Harga gas nol saat mempercepat" } diff --git a/app/_locales/it/messages.json b/app/_locales/it/messages.json index 20c1f298f..daff32d6d 100644 --- a/app/_locales/it/messages.json +++ b/app/_locales/it/messages.json @@ -1718,9 +1718,6 @@ "yourPrivateSeedPhrase": { "message": "La tua frase seed privata" }, - "yourSigRequested": { - "message": "E' richiesta la tua firma" - }, "zeroGasPriceOnSpeedUpError": { "message": "Prezzo del gas maggiore di zero" } diff --git a/app/_locales/ja/messages.json b/app/_locales/ja/messages.json index 728676097..a8cfd9bbe 100644 --- a/app/_locales/ja/messages.json +++ b/app/_locales/ja/messages.json @@ -474,8 +474,5 @@ }, "youSign": { "message": "署名しています。" - }, - "yourSigRequested": { - "message": "あなたの署名がリクエストされています。" } } diff --git a/app/_locales/kn/messages.json b/app/_locales/kn/messages.json index 8c6c0a9e1..4c3a9add5 100644 --- a/app/_locales/kn/messages.json +++ b/app/_locales/kn/messages.json @@ -1256,9 +1256,6 @@ "yourPrivateSeedPhrase": { "message": "ನಿಮ್ಮ ಖಾಸಗಿ ಸೀಡ್ ಫ್ರೇಸ್" }, - "yourSigRequested": { - "message": "ನಿಮ್ಮ ಸಹಿಯನ್ನು ವಿನಂತಿಸಲಾಗಿದೆ" - }, "zeroGasPriceOnSpeedUpError": { "message": "ವೇಗ ಹೆಚ್ಚಿಸುವುದಕ್ಕೆ ಶೂನ್ಯ ಗ್ಯಾಸ್ ಬೆಲೆ" } diff --git a/app/_locales/ko/messages.json b/app/_locales/ko/messages.json index 43c6278b1..40666c671 100644 --- a/app/_locales/ko/messages.json +++ b/app/_locales/ko/messages.json @@ -1247,9 +1247,6 @@ "yourPrivateSeedPhrase": { "message": "개인 시드 구문" }, - "yourSigRequested": { - "message": "서명을 요청 중입니다." - }, "zeroGasPriceOnSpeedUpError": { "message": "가속 시 가스 비용 없음" } diff --git a/app/_locales/lt/messages.json b/app/_locales/lt/messages.json index 3158cb579..062f00060 100644 --- a/app/_locales/lt/messages.json +++ b/app/_locales/lt/messages.json @@ -1256,9 +1256,6 @@ "yourPrivateSeedPhrase": { "message": "Jūsų asmeninė atkūrimo frazė" }, - "yourSigRequested": { - "message": "Prašoma jūsų parašo" - }, "zeroGasPriceOnSpeedUpError": { "message": "Nustatykite nulinę dujų kainą greitėjant" } diff --git a/app/_locales/lv/messages.json b/app/_locales/lv/messages.json index 43b5a6375..f0000fadc 100644 --- a/app/_locales/lv/messages.json +++ b/app/_locales/lv/messages.json @@ -1252,9 +1252,6 @@ "yourPrivateSeedPhrase": { "message": "Jūsu privātā atkopšanas frāze" }, - "yourSigRequested": { - "message": "Nepieciešams jūsu paraksts" - }, "zeroGasPriceOnSpeedUpError": { "message": "Gas nulles cena pie paātrinājuma" } diff --git a/app/_locales/ms/messages.json b/app/_locales/ms/messages.json index e64b4f582..5c1c373ef 100644 --- a/app/_locales/ms/messages.json +++ b/app/_locales/ms/messages.json @@ -1230,9 +1230,6 @@ "yourPrivateSeedPhrase": { "message": "Ungkapan benih peribadi anda" }, - "yourSigRequested": { - "message": "Tandatangan anda sedang diminta" - }, "zeroGasPriceOnSpeedUpError": { "message": "Sifar harga gas untuk pencepatan" } diff --git a/app/_locales/nl/messages.json b/app/_locales/nl/messages.json index da3b96936..3ed69643b 100644 --- a/app/_locales/nl/messages.json +++ b/app/_locales/nl/messages.json @@ -410,8 +410,5 @@ }, "youSign": { "message": "U ondertekent" - }, - "yourSigRequested": { - "message": "Uw handtekening wordt aangevraagd" } } diff --git a/app/_locales/no/messages.json b/app/_locales/no/messages.json index 816ea9ed8..8beaa8933 100644 --- a/app/_locales/no/messages.json +++ b/app/_locales/no/messages.json @@ -1228,9 +1228,6 @@ "yourPrivateSeedPhrase": { "message": "Din private frøfrase" }, - "yourSigRequested": { - "message": "Det bes om signaturen din " - }, "zeroGasPriceOnSpeedUpError": { "message": "Null bensinpris for fremskynding" } diff --git a/app/_locales/ph/messages.json b/app/_locales/ph/messages.json index cec555fde..ad0441e11 100644 --- a/app/_locales/ph/messages.json +++ b/app/_locales/ph/messages.json @@ -252,8 +252,5 @@ }, "youSign": { "message": "Ikaw ay nagsa-sign" - }, - "yourSigRequested": { - "message": "Hinihiling ang iyong signature" } } diff --git a/app/_locales/pl/messages.json b/app/_locales/pl/messages.json index e1a1c8c9a..ac2c8d18b 100644 --- a/app/_locales/pl/messages.json +++ b/app/_locales/pl/messages.json @@ -1244,9 +1244,6 @@ "yourPrivateSeedPhrase": { "message": "Twoja prywatna fraza seed" }, - "yourSigRequested": { - "message": "Twój podpis jest wymagany" - }, "zeroGasPriceOnSpeedUpError": { "message": "Przyspieszenie z zerową ceną gazu" } diff --git a/app/_locales/pt/messages.json b/app/_locales/pt/messages.json index 3e4aad05e..1e3d1e63b 100644 --- a/app/_locales/pt/messages.json +++ b/app/_locales/pt/messages.json @@ -420,8 +420,5 @@ }, "youSign": { "message": "Está a assinar" - }, - "yourSigRequested": { - "message": "A sua assinatura está a ser pedida" } } diff --git a/app/_locales/pt_BR/messages.json b/app/_locales/pt_BR/messages.json index 154668b75..e61b29f4b 100644 --- a/app/_locales/pt_BR/messages.json +++ b/app/_locales/pt_BR/messages.json @@ -1238,9 +1238,6 @@ "yourPrivateSeedPhrase": { "message": "Sua frase-semente particular" }, - "yourSigRequested": { - "message": "Sua assinatura está sendo solicitada" - }, "zeroGasPriceOnSpeedUpError": { "message": "Preço de Gas zero na agilização" } diff --git a/app/_locales/ro/messages.json b/app/_locales/ro/messages.json index 7c5cc0c8a..efa1eed9b 100644 --- a/app/_locales/ro/messages.json +++ b/app/_locales/ro/messages.json @@ -1237,9 +1237,6 @@ "yourPrivateSeedPhrase": { "message": "Expresia dvs. seed privată" }, - "yourSigRequested": { - "message": "Semnătura dvs. este solicitată" - }, "zeroGasPriceOnSpeedUpError": { "message": "Preț gas zero la accelerare" } diff --git a/app/_locales/ru/messages.json b/app/_locales/ru/messages.json index 04f9ad107..8d354ea34 100644 --- a/app/_locales/ru/messages.json +++ b/app/_locales/ru/messages.json @@ -1292,8 +1292,5 @@ }, "yourPrivateSeedPhrase": { "message": "Ваша сид-фраза" - }, - "yourSigRequested": { - "message": "Запрашивается ваша подпись" } } diff --git a/app/_locales/sk/messages.json b/app/_locales/sk/messages.json index 86e9040ab..ff375b586 100644 --- a/app/_locales/sk/messages.json +++ b/app/_locales/sk/messages.json @@ -1213,9 +1213,6 @@ "yourPrivateSeedPhrase": { "message": "Vaša súkromná seed fráza" }, - "yourSigRequested": { - "message": "Je vyžadován váš podpis" - }, "zeroGasPriceOnSpeedUpError": { "message": "Nulová cena za GAS pri zrýchlení" } diff --git a/app/_locales/sl/messages.json b/app/_locales/sl/messages.json index ffb268e59..024cdfe6d 100644 --- a/app/_locales/sl/messages.json +++ b/app/_locales/sl/messages.json @@ -1235,9 +1235,6 @@ "yourPrivateSeedPhrase": { "message": "Vaš zasebni seed phrase" }, - "yourSigRequested": { - "message": "Zahtevan je bil vaš podpis" - }, "zeroGasPriceOnSpeedUpError": { "message": "Ničelni gas price na pospešitvi" } diff --git a/app/_locales/sr/messages.json b/app/_locales/sr/messages.json index 7aea49f76..e356d79a5 100644 --- a/app/_locales/sr/messages.json +++ b/app/_locales/sr/messages.json @@ -1241,9 +1241,6 @@ "yourPrivateSeedPhrase": { "message": "Vaša privatna šifra za oporavak naloga (seed phrase)" }, - "yourSigRequested": { - "message": "Zahteva se vaš potpis" - }, "zeroGasPriceOnSpeedUpError": { "message": "Nulta cena gasa ubrzava" } diff --git a/app/_locales/sv/messages.json b/app/_locales/sv/messages.json index 183d1064f..9dd41a7ff 100644 --- a/app/_locales/sv/messages.json +++ b/app/_locales/sv/messages.json @@ -1231,9 +1231,6 @@ "yourPrivateSeedPhrase": { "message": "Din privata seedphrase" }, - "yourSigRequested": { - "message": "En begäran om din signatur har skickats" - }, "zeroGasPriceOnSpeedUpError": { "message": "Inget gaspris vid uppsnabbning" } diff --git a/app/_locales/sw/messages.json b/app/_locales/sw/messages.json index f5516ae5f..f807fbcc1 100644 --- a/app/_locales/sw/messages.json +++ b/app/_locales/sw/messages.json @@ -1234,9 +1234,6 @@ "yourPrivateSeedPhrase": { "message": "Kirai chako kianzio cha binafsi" }, - "yourSigRequested": { - "message": "Saini yako inaombwa" - }, "zeroGasPriceOnSpeedUpError": { "message": "Bei ya gesi sifuri kwenye kuongeza kasi" } diff --git a/app/_locales/ta/messages.json b/app/_locales/ta/messages.json index 02ce79837..1b305017a 100644 --- a/app/_locales/ta/messages.json +++ b/app/_locales/ta/messages.json @@ -552,8 +552,5 @@ }, "youSign": { "message": "நீங்கள் கையெழுத்திடுகிறீர்கள்" - }, - "yourSigRequested": { - "message": "உங்கள் கையொப்பம் கோரப்படுகிறது" } } diff --git a/app/_locales/th/messages.json b/app/_locales/th/messages.json index 330d10cb7..5135a467f 100644 --- a/app/_locales/th/messages.json +++ b/app/_locales/th/messages.json @@ -573,8 +573,5 @@ }, "youSign": { "message": "คุณกำลังเซ็นชื่อ" - }, - "yourSigRequested": { - "message": "ลายเซ็นของคุณกำลังได้รับการร้องขอ" } } diff --git a/app/_locales/tr/messages.json b/app/_locales/tr/messages.json index 929aa00aa..a2471b68f 100644 --- a/app/_locales/tr/messages.json +++ b/app/_locales/tr/messages.json @@ -486,8 +486,5 @@ }, "youSign": { "message": "İmzalıyorsunuz" - }, - "yourSigRequested": { - "message": "İmzanız isteniyor" } } diff --git a/app/_locales/uk/messages.json b/app/_locales/uk/messages.json index c613908bd..0a659eb40 100644 --- a/app/_locales/uk/messages.json +++ b/app/_locales/uk/messages.json @@ -1256,9 +1256,6 @@ "yourPrivateSeedPhrase": { "message": "Ваша секретна seed-фраза" }, - "yourSigRequested": { - "message": "Надійшов запит вашого підпису" - }, "zeroGasPriceOnSpeedUpError": { "message": "Ціна пального на прискорення - нуль" } diff --git a/app/_locales/vi/messages.json b/app/_locales/vi/messages.json index ca18217ee..815e46881 100644 --- a/app/_locales/vi/messages.json +++ b/app/_locales/vi/messages.json @@ -303,8 +303,5 @@ }, "youSign": { "message": "Bạn đang ký nhận" - }, - "yourSigRequested": { - "message": "Chữ ký của bạn đang được yêu cầu" } } diff --git a/app/_locales/zh_CN/messages.json b/app/_locales/zh_CN/messages.json index 80759a362..c584e0fc3 100644 --- a/app/_locales/zh_CN/messages.json +++ b/app/_locales/zh_CN/messages.json @@ -1241,9 +1241,6 @@ "yourPrivateSeedPhrase": { "message": "你的私有助记词" }, - "yourSigRequested": { - "message": "正在请求你的签名" - }, "zeroGasPriceOnSpeedUpError": { "message": "Gas 价格加速上涨" } diff --git a/app/_locales/zh_TW/messages.json b/app/_locales/zh_TW/messages.json index 8f6d78b4a..819e80f22 100644 --- a/app/_locales/zh_TW/messages.json +++ b/app/_locales/zh_TW/messages.json @@ -1244,9 +1244,6 @@ "yourPrivateSeedPhrase": { "message": "您的助憶詞" }, - "yourSigRequested": { - "message": "正在請求您的簽署" - }, "zeroGasPriceOnSpeedUpError": { "message": "加速的 Gas 價格為 0" } diff --git a/ui/app/components/app/signature-request-original/index.scss b/ui/app/components/app/signature-request-original/index.scss index c3b4aaf3b..3d90271ed 100644 --- a/ui/app/components/app/signature-request-original/index.scss +++ b/ui/app/components/app/signature-request-original/index.scss @@ -152,19 +152,22 @@ height: 0; } - &__request-info { + &__origin-row { + @include Paragraph; + display: flex; - justify-content: center; + margin: 0 15px; } - &__headline { - @include H4; + &__origin-label { + flex-grow: 1; + margin-right: 5px; + } - height: 48px; - width: 240px; - color: $tundora; - text-align: center; - margin-top: 20px; + &__origin { + margin-left: 5px; + overflow: hidden; + text-overflow: ellipsis; } &__notice, diff --git a/ui/app/components/app/signature-request-original/signature-request-original.component.js b/ui/app/components/app/signature-request-original/signature-request-original.component.js index f20933ad9..32f8aafcc 100644 --- a/ui/app/components/app/signature-request-original/signature-request-original.component.js +++ b/ui/app/components/app/signature-request-original/signature-request-original.component.js @@ -13,6 +13,7 @@ import Identicon from '../../ui/identicon' import AccountListItem from '../account-list-item' import { conversionUtil } from '../../../helpers/utils/conversion-util' import Button from '../../ui/button' +import SiteIcon from '../../ui/site-icon' export default class SignatureRequestOriginal extends Component { static contextTypes = { @@ -34,6 +35,7 @@ export default class SignatureRequestOriginal extends Component { requesterAddress: PropTypes.string, sign: PropTypes.func.isRequired, txData: PropTypes.object.isRequired, + domainMetadata: PropTypes.object, } state = { @@ -148,11 +150,28 @@ export default class SignatureRequestOriginal extends Component { ) } - renderRequestInfo = () => { + renderOriginInfo = () => { + const { txData, domainMetadata } = this.props + const { t } = this.context + + const originMetadata = txData.msgParams.origin + ? domainMetadata?.[txData.msgParams.origin] + : null + return ( -
-
- {this.context.t('yourSigRequested')} +
+
+ {`${t('origin')}:`} +
+ {originMetadata?.icon ? ( + + ) : null} +
+ {txData.msgParams.origin}
) @@ -216,7 +235,7 @@ export default class SignatureRequestOriginal extends Component { return (
{this.renderAccountInfo()} - {this.renderRequestInfo()} + {this.renderOriginInfo()}
Date: Thu, 28 Jan 2021 14:29:45 -0330 Subject: [PATCH 09/48] Add origin to transaction confirmation (#10296) Fixes #5611 The origin that suggests a transaction is now shown on the transaction confirmation page. If the transaction was initiated from within MetaMask (e.g. via the 'Send' flow or swaps), no origin is shown. This was based upon designs that were linked in the PR #9377. This is a temporary measure until our newer transaction confirmation designs can be implemented. --- .../confirm-page-container-content.component.js | 3 +++ .../confirm-page-container-summary.component.js | 5 +++++ .../confirm-page-container-summary/index.scss | 6 ++++++ .../confirm-page-container.component.js | 3 +++ .../confirm-transaction-base.component.js | 2 ++ 5 files changed, 19 insertions(+) diff --git a/ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-content.component.js b/ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-content.component.js index affda4c12..d3542345e 100644 --- a/ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-content.component.js +++ b/ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-content.component.js @@ -21,6 +21,7 @@ export default class ConfirmPageContainerContent extends Component { title: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), titleComponent: PropTypes.node, warning: PropTypes.string, + origin: PropTypes.string.isRequired, // Footer onCancelAll: PropTypes.func, onCancel: PropTypes.func, @@ -79,6 +80,7 @@ export default class ConfirmPageContainerContent extends Component { disabled, unapprovedTxCount, rejectNText, + origin, } = this.props return ( @@ -97,6 +99,7 @@ export default class ConfirmPageContainerContent extends Component { identiconAddress={identiconAddress} nonce={nonce} assetImage={assetImage} + origin={origin} /> {this.renderContent()} {(errorKey || errorMessage) && ( diff --git a/ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-summary/confirm-page-container-summary.component.js b/ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-summary/confirm-page-container-summary.component.js index 94c3e4279..49efb86e5 100644 --- a/ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-summary/confirm-page-container-summary.component.js +++ b/ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-summary/confirm-page-container-summary.component.js @@ -14,10 +14,14 @@ const ConfirmPageContainerSummary = (props) => { identiconAddress, nonce, assetImage, + origin, } = props return (
+ {origin === 'metamask' ? null : ( +
{origin}
+ )}
{action}
{nonce && ( @@ -58,6 +62,7 @@ ConfirmPageContainerSummary.propTypes = { identiconAddress: PropTypes.string, nonce: PropTypes.string, assetImage: PropTypes.string, + origin: PropTypes.string.isRequired, } export default ConfirmPageContainerSummary diff --git a/ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-summary/index.scss b/ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-summary/index.scss index 5ce8f708a..618763684 100644 --- a/ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-summary/index.scss +++ b/ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-summary/index.scss @@ -4,6 +4,12 @@ height: 133px; box-sizing: border-box; + &__origin { + @include H6; + + padding-bottom: 10px; + } + &__action-row { display: flex; justify-content: space-between; diff --git a/ui/app/components/app/confirm-page-container/confirm-page-container.component.js b/ui/app/components/app/confirm-page-container/confirm-page-container.component.js index 69f8fdc33..623b31102 100644 --- a/ui/app/components/app/confirm-page-container/confirm-page-container.component.js +++ b/ui/app/components/app/confirm-page-container/confirm-page-container.component.js @@ -42,6 +42,7 @@ export default class ConfirmPageContainer extends Component { assetImage: PropTypes.string, warning: PropTypes.string, unapprovedTxCount: PropTypes.number, + origin: PropTypes.string.isRequired, // Navigation totalTx: PropTypes.number, positionOfCurrentTx: PropTypes.number, @@ -101,6 +102,7 @@ export default class ConfirmPageContainer extends Component { requestsWaitingText, hideSenderToRecipient, showAccountInHeader, + origin, } = this.props const renderAssetImage = contentComponent || (!contentComponent && !identiconAddress) @@ -160,6 +162,7 @@ export default class ConfirmPageContainer extends Component { disabled={disabled} unapprovedTxCount={unapprovedTxCount} rejectNText={this.context.t('rejectTxsN', [unapprovedTxCount])} + origin={origin} /> )} {contentComponent && ( diff --git a/ui/app/pages/confirm-transaction-base/confirm-transaction-base.component.js b/ui/app/pages/confirm-transaction-base/confirm-transaction-base.component.js index ec079c3da..eeec5a5cd 100644 --- a/ui/app/pages/confirm-transaction-base/confirm-transaction-base.component.js +++ b/ui/app/pages/confirm-transaction-base/confirm-transaction-base.component.js @@ -669,6 +669,7 @@ export default class ConfirmTransactionBase extends Component { transactionCategory, hideSenderToRecipient, showAccountInHeader, + txData, } = this.props const { submitting, submitError, submitWarning } = this.state @@ -736,6 +737,7 @@ export default class ConfirmTransactionBase extends Component { onCancel={() => this.handleCancel()} onSubmit={() => this.handleSubmit()} hideSenderToRecipient={hideSenderToRecipient} + origin={txData.origin} /> ) } From 05f5deb70159b9e3826b66e7f69caffade1379f9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 28 Jan 2021 17:47:18 -0330 Subject: [PATCH 10/48] Bump electron from 9.1.2 to 9.4.2 (#10308) Bumps [electron](https://github.com/electron/electron) from 9.1.2 to 9.4.2. - [Release notes](https://github.com/electron/electron/releases) - [Changelog](https://github.com/electron/electron/blob/master/docs/breaking-changes.md) - [Commits](https://github.com/electron/electron/compare/v9.1.2...v9.4.2) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 136 +++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 94 insertions(+), 42 deletions(-) diff --git a/yarn.lock b/yarn.lock index 197940138..863f99915 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1111,16 +1111,17 @@ integrity sha512-iGDh2M6pFuXg9kyW+U//963LKylSLFpLG5hZvUppCjhkiDwsYquQPyamxCQlLASYySS3gGKAki2eWG9qIHKCew== "@electron/get@^1.0.1": - version "1.12.2" - resolved "https://registry.yarnpkg.com/@electron/get/-/get-1.12.2.tgz#6442066afb99be08cefb9a281e4b4692b33764f3" - integrity sha512-vAuHUbfvBQpYTJ5wB7uVIDq5c/Ry0fiTBMs7lnEYAo/qXXppIVcWdfBr57u6eRnKdVso7KSiH6p/LbQAG6Izrg== + version "1.12.3" + resolved "https://registry.yarnpkg.com/@electron/get/-/get-1.12.3.tgz#fa2723385c4b565a34c4c82f46087aa2a5fbf6d0" + integrity sha512-NFwSnVZQK7dhOYF1NQCt+HGqgL1aNdj0LUSx75uCqnZJqyiWCVdAMFV4b4/kC8HjUJAnsvdSEmjEt4G2qNQ9+Q== dependencies: debug "^4.1.1" env-paths "^2.2.0" + filenamify "^4.1.0" fs-extra "^8.1.0" got "^9.6.0" progress "^2.0.3" - sanitize-filename "^1.6.2" + semver "^6.2.0" sumchecker "^3.0.1" optionalDependencies: global-agent "^2.0.2" @@ -3057,9 +3058,9 @@ form-data "^3.0.0" "@types/node@*", "@types/node@^12.0.12", "@types/node@^12.12.6": - version "12.19.1" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.1.tgz#303f74c8a2b35644594139e948b2be470ae1186f" - integrity sha512-/xaVmBBjOGh55WCqumLAHXU9VhjGtmyTGqJzFBXRWZzByOXI5JAJNx9xPVGEsNizrNwcec92fQMj458MWfjN1A== + version "12.19.15" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.15.tgz#0de7e978fb43db62da369db18ea088a63673c182" + integrity sha512-lowukE3GUI+VSYSu6VcBXl14d61Rp5hA1D+61r16qnwC0lYNSqdxcvRh0pswejorHfS+HgwBasM8jLXz0/aOsw== "@types/node@10.12.18": version "10.12.18" @@ -5902,10 +5903,10 @@ boolbase@^1.0.0, boolbase@~1.0.0: resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24= -boolean@^3.0.0, boolean@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/boolean/-/boolean-3.0.1.tgz#35ecf2b4a2ee191b0b44986f14eb5f052a5cbb4f" - integrity sha512-HRZPIjPcbwAVQvOTxR4YE3o8Xs98NqbbL1iEZDCz7CL8ql0Lt5iOyJFxfnAB0oFs8Oh02F/lLlg30Mexv46LjA== +boolean@^3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/boolean/-/boolean-3.0.2.tgz#df1baa18b6a2b0e70840475e1d93ec8fe75b2570" + integrity sha512-RwywHlpCRc3/Wh81MiCKun4ydaIFyW5Ea6JbL6sRCVx5q5irDw7pMXBUFYF/jArQ6YrG36q0kpovc9P/Kd3I4g== boom@^7.2.0: version "7.3.0" @@ -7638,11 +7639,16 @@ core-js@^2.4.0, core-js@^2.5.0, core-js@^2.5.3: resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.11.tgz#38831469f9922bded8ee21c9dc46985e0399308c" integrity sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg== -core-js@^3.0.1, core-js@^3.0.4, core-js@^3.6.5: +core-js@^3.0.1, core-js@^3.0.4: version "3.6.5" resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.6.5.tgz#7395dc273af37fb2e50e9bd3d9fe841285231d1a" integrity sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA== +core-js@^3.6.5: + version "3.8.3" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.8.3.tgz#c21906e1f14f3689f93abcc6e26883550dd92dd0" + integrity sha512-KPYXeVZYemC2TkNEkX/01I+7yd+nX3KddKwZ1Ww7SKWdI2wQprSgLmrTddT8nw92AjEklTsPBoSdQBhbI1bQ6Q== + core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" @@ -8150,7 +8156,7 @@ debug@3.2.6, debug@3.X, debug@^3.0.0, debug@^3.1.0, debug@^3.2.6: dependencies: ms "^2.1.1" -debug@4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@~4.1.0: +debug@4, debug@^4.0.1, debug@~4.1.0: version "4.1.1" resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== @@ -8164,6 +8170,13 @@ debug@4.1.0: dependencies: ms "^2.1.1" +debug@^4.1.0, debug@^4.1.1: + version "4.3.1" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee" + integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ== + dependencies: + ms "2.1.2" + debuglog@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492" @@ -8340,9 +8353,9 @@ defaults@^1.0.3: clone "^1.0.2" defer-to-connect@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.0.2.tgz#4bae758a314b034ae33902b5aac25a8dd6a8633e" - integrity sha512-k09hcQcTDY+cwgiwa6PYKLm3jlagNzQ+RSvhjzESOGOx+MNOuXkxTfEvPrO1IOQ81tArCFYQgi631clB70RpQw== + version "1.1.3" + resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591" + integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ== deferred-leveldown@~1.2.1: version "1.2.2" @@ -9037,9 +9050,9 @@ electron-to-chromium@^1.3.378, electron-to-chromium@^1.3.47, electron-to-chromiu integrity sha512-eFDC+yVQpEhtlapk4CYDPfV9ajF9cEof5TBcO49L1ETO+aYogrKWDmYpZyxBScMNe8Bo/gJamH4amQ4yyvXg4g== electron@^9.1.0: - version "9.1.2" - resolved "https://registry.yarnpkg.com/electron/-/electron-9.1.2.tgz#bfa26d6b192ea13abb6f1461371fd731a8358988" - integrity sha512-xEYadr3XqIqJ4ktBPo0lhzPdovv4jLCpiUUGc2M1frUhFhwqXokwhPaTUcE+zfu5+uf/ONDnQApwjzznBsRrgQ== + version "9.4.2" + resolved "https://registry.yarnpkg.com/electron/-/electron-9.4.2.tgz#0c76dfc3d317108adac66844b868a9e2e57d48f5" + integrity sha512-WpnJLDFHtj5eIewAi4hMHxGdbwkzjzmxsMu/BtDFCic3wpruchkskL7EV28Sg/IYTAqo6yN5ISfnFaQcLsIdng== dependencies: "@electron/get" "^1.0.1" "@types/node" "^12.0.12" @@ -11328,6 +11341,15 @@ filenamify@^2.0.0: strip-outer "^1.0.0" trim-repeated "^1.0.0" +filenamify@^4.1.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/filenamify/-/filenamify-4.2.0.tgz#c99716d676869585b3b5d328b3f06590d032e89f" + integrity sha512-pkgE+4p7N1n7QieOopmn3TqJaefjdWXwEkj2XLZJLKfOgcQKkn11ahvGNgTD8mLggexLiDFQxeTs14xVU22XPA== + dependencies: + filename-reserved-regex "^2.0.0" + strip-outer "^1.0.1" + trim-repeated "^1.0.0" + filesize@6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/filesize/-/filesize-6.0.1.tgz#f850b509909c7c86f7e450ea19006c31c2ed3d2f" @@ -12102,9 +12124,9 @@ get-stream@^4.0.0, get-stream@^4.1.0: pump "^3.0.0" get-stream@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.1.0.tgz#01203cdc92597f9b909067c3e656cc1f4d3c4dc9" - integrity sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw== + version "5.2.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" + integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== dependencies: pump "^3.0.0" @@ -12612,11 +12634,16 @@ got@^8.3.1: url-parse-lax "^3.0.0" url-to-options "^1.0.1" -graceful-fs@4.X, graceful-fs@^4.0.0, graceful-fs@^4.1.10, graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0: +graceful-fs@4.X, graceful-fs@^4.0.0, graceful-fs@^4.1.10, graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.9: version "4.2.3" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423" integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ== +graceful-fs@^4.1.6, graceful-fs@^4.2.0: + version "4.2.4" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" + integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== + "graceful-readlink@>= 1.0.0": version "1.0.1" resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" @@ -13298,9 +13325,9 @@ http-cache-semantics@3.8.1: integrity sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w== http-cache-semantics@^4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.0.3.tgz#495704773277eeef6e43f9ab2c2c7d259dda25c5" - integrity sha512-TcIMG3qeVLgDr1TEd2XvHaTnMPwYQUQMIBLy+5pLSDKYFc7UIqj39w8EGzZkaxoLv/l2K8HaI0t5AVA+YYgUew== + version "4.1.0" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390" + integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ== http-errors@1.7.2: version "1.7.2" @@ -13663,7 +13690,12 @@ inherits@2.0.3: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= -ini@^1.3.4, ini@^1.3.5, ini@~1.3.0: +ini@^1.3.4: + version "1.3.8" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" + integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== + +ini@^1.3.5, ini@~1.3.0: version "1.3.7" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.7.tgz#a09363e1911972ea16d7a8851005d84cf09a9a84" integrity sha512-iKpRpXP+CrP2jyrxvg1kMUpXDyRUFDWurxbnVT1vQPx+Wz9uCYsMIqYuSBLV+PAaZG/d7kRLKRFc9oDMsH+mFQ== @@ -17965,7 +17997,7 @@ ms@2.1.1: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== -ms@^2.0.0: +ms@2.1.2, ms@^2.0.0: version "2.1.2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== @@ -18632,9 +18664,9 @@ normalize-url@^3.3.0: integrity sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg== normalize-url@^4.1.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.3.0.tgz#9c49e10fc1876aeb76dba88bf1b2b5d9fa57b2ee" - integrity sha512-0NLtR71o4k6GLP+mr6Ty34c5GA6CMoEsncKJxvQd8NzPxaHRJNnb5gZE8R1XF4CPIS7QPHLJ74IFszwtNVAHVQ== + version "4.5.0" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.0.tgz#453354087e6ca96957bd8f5baf753f5982142129" + integrity sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ== now-and-later@^2.0.0: version "2.0.0" @@ -21713,7 +21745,7 @@ read-pkg@^5.2.0: parse-json "^5.0.0" type-fest "^0.6.0" -"readable-stream@1 || 2", readable-stream@2, readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.2.6, readable-stream@^2.2.8, readable-stream@^2.2.9, readable-stream@^2.3.0, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@~2.3.3, readable-stream@~2.3.5, readable-stream@~2.3.6: +"readable-stream@1 || 2", readable-stream@2, readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.1.5, readable-stream@^2.2.6, readable-stream@^2.2.8, readable-stream@^2.2.9, readable-stream@^2.3.0, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@~2.3.3, readable-stream@~2.3.5, readable-stream@~2.3.6: version "2.3.6" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== @@ -21745,6 +21777,19 @@ readable-stream@1.1.x, readable-stream@^1.0.33: string_decoder "^1.1.1" util-deprecate "^1.0.1" +readable-stream@^2.2.2: + version "2.3.7" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" + integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + readable-stream@~1.0.15: version "1.0.34" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" @@ -22589,11 +22634,11 @@ rn-host-detect@^1.1.5: integrity sha512-btNg5kzHcjZZ7t7mvvV/4wNJ9e3MPgrWivkRgWURzXL0JJ0pwWlU4zrbmdlz3HHzHOxhBhHB4D+/dbMFfu4/4A== roarr@^2.15.3: - version "2.15.3" - resolved "https://registry.yarnpkg.com/roarr/-/roarr-2.15.3.tgz#65248a291a15af3ebfd767cbf7e44cb402d1d836" - integrity sha512-AEjYvmAhlyxOeB9OqPUzQCo3kuAkNfuDk/HqWbZdFsqDFpapkTjiw+p4svNEoRLvuqNTxqfL+s+gtD4eDgZ+CA== + version "2.15.4" + resolved "https://registry.yarnpkg.com/roarr/-/roarr-2.15.4.tgz#f5fe795b7b838ccfe35dc608e0282b9eba2e7afd" + integrity sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A== dependencies: - boolean "^3.0.0" + boolean "^3.0.1" detect-node "^2.0.4" globalthis "^1.0.1" json-stringify-safe "^5.0.1" @@ -22744,7 +22789,7 @@ safe-regex@^1.1.0: resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -sanitize-filename@^1.6.1, sanitize-filename@^1.6.2: +sanitize-filename@^1.6.1: version "1.6.3" resolved "https://registry.yarnpkg.com/sanitize-filename/-/sanitize-filename-1.6.3.tgz#755ebd752045931977e30b2025d340d7c9090378" integrity sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg== @@ -23064,11 +23109,18 @@ semver@7.0.0: resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== -semver@^7.2.1, semver@^7.3.2: +semver@^7.2.1: version "7.3.2" resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938" integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ== +semver@^7.3.2: + version "7.3.4" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.4.tgz#27aaa7d2e4ca76452f98d3add093a72c943edc97" + integrity sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw== + dependencies: + lru-cache "^6.0.0" + semver@~5.3.0: version "5.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" @@ -24328,7 +24380,7 @@ strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== -strip-outer@^1.0.0: +strip-outer@^1.0.0, strip-outer@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/strip-outer/-/strip-outer-1.0.1.tgz#b2fd2abf6604b9d1e6013057195df836b8a9d631" integrity sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg== @@ -25619,9 +25671,9 @@ unist-util-visit@^2.0.0: unist-util-visit-parents "^3.0.0" universalify@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.1.tgz#fa71badd4437af4c148841e3b3b165f9e9e590b7" - integrity sha1-+nG63UQ3r0wUiEHjs7Fl+enlkLc= + version "0.1.2" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" + integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== universalify@^1.0.0: version "1.0.0" From d7d2de04bd6631d4ac6887226babaf6574dd46bb Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Fri, 29 Jan 2021 13:35:32 -0330 Subject: [PATCH 11/48] Fix PropType error for Chip component (#10319) The Chip component was emitting a PropType error because it was missing the `labelProps.children` prop. It was never supposed to be given that prop - it was a mistake in the PropType declaration. The PropTypes have been fixed to prevent this warning. --- ui/app/components/ui/chip/chip.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/app/components/ui/chip/chip.js b/ui/app/components/ui/chip/chip.js index 1fa3faf3d..691df480b 100644 --- a/ui/app/components/ui/chip/chip.js +++ b/ui/app/components/ui/chip/chip.js @@ -55,7 +55,7 @@ Chip.propTypes = { label: PropTypes.string, children: PropTypes.node, labelProps: PropTypes.shape({ - ...omit(Typography.propTypes, ['className']), + ...omit(Typography.propTypes, ['children', 'className']), }), leftIcon: PropTypes.node, rightIcon: PropTypes.node, From 6f46253e62c31f7dd0b5baeb5d03dbff76201b02 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Fri, 29 Jan 2021 17:04:15 -0330 Subject: [PATCH 12/48] Fix menu-droppo external click handler (#10311) The `menu-droppo` external click handler would fail to update when the prop changed while the menu wasn't shown. This bug isn't exposed anywhere yet as far as I know, but I ran into it when working on a different bug fix. --- ui/app/components/app/menu-droppo.js | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/ui/app/components/app/menu-droppo.js b/ui/app/components/app/menu-droppo.js index 558dacfe8..7fde88988 100644 --- a/ui/app/components/app/menu-droppo.js +++ b/ui/app/components/app/menu-droppo.js @@ -31,14 +31,6 @@ export default class MenuDroppoComponent extends Component { ) } - manageListeners() { - const { isOpen, onClickOutside } = this.props - - if (isOpen) { - this.outsideClickHandler = onClickOutside - } - } - globalClickOccurred = (event) => { const { target } = event // eslint-disable-next-line react/no-find-dom-node @@ -47,9 +39,9 @@ export default class MenuDroppoComponent extends Component { if ( target !== container && !isDescendant(this.container, event.target) && - this.outsideClickHandler + this.props.onClickOutside ) { - this.outsideClickHandler(event) + this.props.onClickOutside(event) } } @@ -74,8 +66,6 @@ export default class MenuDroppoComponent extends Component { const { useCssTransition } = this.props const zIndex = 'zIndex' in this.props ? this.props.zIndex : 0 - this.manageListeners() - const baseStyle = { position: 'fixed', ...style, From f381f41cb271571372ff1c3be89a7b85569c4b0f Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Sat, 30 Jan 2021 12:12:55 -0330 Subject: [PATCH 13/48] Fix network dropdown button (#10312) This fixes a bug where the network menu would remain present after a second click on the network menu button. The bug was caused by the click being handled _twice_, by two separate handlers. First it was caught by the external click handler of the dropdown menu, which closed the menu. Second, it was caught by the network button itself, which re- opened the menu. This all happens quickly enough that to the user it appears to stay open. The external click handler of the menu now only fires if the menu is open. Additionally, any click that is caught by the network menu is stopped from propagating further, so that it can't trigger additional click handlers. --- test/e2e/metamask-ui.spec.js | 5 +++++ ui/app/components/app/dropdowns/network-dropdown.js | 1 + ui/app/components/app/menu-droppo.js | 1 + 3 files changed, 7 insertions(+) diff --git a/test/e2e/metamask-ui.spec.js b/test/e2e/metamask-ui.spec.js index 52819a7ac..da6d159f6 100644 --- a/test/e2e/metamask-ui.spec.js +++ b/test/e2e/metamask-ui.spec.js @@ -1798,6 +1798,11 @@ describe('MetaMask', function () { By.xpath(`//span[contains(text(), 'http://127.0.0.1:8545/')]`), ) + // click Mainnet to dismiss network dropdown + await driver.clickElement( + By.xpath(`//span[contains(text(), 'Ethereum Mainnet')]`), + ) + assert.equal(customRpcs.length, 2) }) diff --git a/ui/app/components/app/dropdowns/network-dropdown.js b/ui/app/components/app/dropdowns/network-dropdown.js index 613de6b28..4fe270b08 100644 --- a/ui/app/components/app/dropdowns/network-dropdown.js +++ b/ui/app/components/app/dropdowns/network-dropdown.js @@ -255,6 +255,7 @@ class NetworkDropdown extends Component { ) if (notToggleElementIndex === -1) { + event.stopPropagation() this.props.hideNetworkDropdown() } }} diff --git a/ui/app/components/app/menu-droppo.js b/ui/app/components/app/menu-droppo.js index 7fde88988..d9895ec61 100644 --- a/ui/app/components/app/menu-droppo.js +++ b/ui/app/components/app/menu-droppo.js @@ -37,6 +37,7 @@ export default class MenuDroppoComponent extends Component { const container = findDOMNode(this) if ( + this.props.isOpen && target !== container && !isDescendant(this.container, event.target) && this.props.onClickOutside From e6f4c89945e9a317c9f07c1437f40dbc5cf2d33e Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Mon, 1 Feb 2021 14:32:20 -0330 Subject: [PATCH 14/48] Fix signature confirmation PropType error (#10317) Upon the first render, the "original" signature request confirmation page would trigger a PropType error. This was caused by unexpected mutation of the state props. The container has been updated to avoid mutating the props, and now the PropType warning is no longer present. --- .../signature-request-original.container.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/ui/app/components/app/signature-request-original/signature-request-original.container.js b/ui/app/components/app/signature-request-original/signature-request-original.container.js index 5987fcb27..90b78b734 100644 --- a/ui/app/components/app/signature-request-original/signature-request-original.container.js +++ b/ui/app/components/app/signature-request-original/signature-request-original.container.js @@ -44,8 +44,7 @@ function mergeProps(stateProps, dispatchProps, ownProps) { txData, } = ownProps - const { allAccounts } = stateProps - delete stateProps.allAccounts + const { allAccounts, ...otherStateProps } = stateProps const { type, @@ -69,7 +68,7 @@ function mergeProps(stateProps, dispatchProps, ownProps) { return { ...ownProps, - ...stateProps, + ...otherStateProps, ...dispatchProps, fromAccount, txData, From 9269615b26ff27af8640980e40b334de6960ca18 Mon Sep 17 00:00:00 2001 From: Brad Decker Date: Mon, 1 Feb 2021 12:10:19 -0600 Subject: [PATCH 15/48] add inverted info icon, and update props (#10305) --- .../app/asset-list-item/asset-list-item.js | 5 ++-- .../account-mismatch-warning.component.js | 3 +- .../ui/icon-border/icon-border.scss | 3 +- ui/app/components/ui/icon/icon.stories.js | 19 +++++++++++- ui/app/components/ui/icon/index.scss | 8 ++--- .../ui/icon/info-icon-inverted.component.js | 29 +++++++++++++++++++ .../components/ui/icon/info-icon.component.js | 11 +++---- ui/app/helpers/constants/design-system.js | 7 +++++ 8 files changed, 70 insertions(+), 15 deletions(-) create mode 100644 ui/app/components/ui/icon/info-icon-inverted.component.js diff --git a/ui/app/components/app/asset-list-item/asset-list-item.js b/ui/app/components/app/asset-list-item/asset-list-item.js index b5164e39c..b09fb3c3f 100644 --- a/ui/app/components/app/asset-list-item/asset-list-item.js +++ b/ui/app/components/app/asset-list-item/asset-list-item.js @@ -12,6 +12,7 @@ import { useI18nContext } from '../../../hooks/useI18nContext' import { useMetricEvent } from '../../../hooks/useMetricEvent' import { updateSendToken } from '../../../store/actions' import { SEND_ROUTE } from '../../../helpers/constants/routes' +import { SEVERITIES } from '../../../helpers/constants/design-system' const AssetListItem = ({ className, @@ -43,13 +44,13 @@ const AssetListItem = ({ position="bottom" html={warning} > - + ) : null const midContent = warning ? ( <> - +
{warning}
) : null diff --git a/ui/app/components/ui/account-mismatch-warning/account-mismatch-warning.component.js b/ui/app/components/ui/account-mismatch-warning/account-mismatch-warning.component.js index 4e7e9c966..6fcb10e15 100644 --- a/ui/app/components/ui/account-mismatch-warning/account-mismatch-warning.component.js +++ b/ui/app/components/ui/account-mismatch-warning/account-mismatch-warning.component.js @@ -5,6 +5,7 @@ import Tooltip from '../tooltip' import { getSelectedAccount } from '../../../selectors' import InfoIcon from '../icon/info-icon.component' import { useI18nContext } from '../../../hooks/useI18nContext' +import { SEVERITIES } from '../../../helpers/constants/design-system' export default function AccountMismatchWarning({ address }) { const selectedAccount = useSelector(getSelectedAccount) @@ -21,7 +22,7 @@ export default function AccountMismatchWarning({ address }) { containerClassName="account-mismatch-warning__tooltip-container" >
- +
) diff --git a/ui/app/components/ui/icon-border/icon-border.scss b/ui/app/components/ui/icon-border/icon-border.scss index cd18ccc6e..5028617e6 100644 --- a/ui/app/components/ui/icon-border/icon-border.scss +++ b/ui/app/components/ui/icon-border/icon-border.scss @@ -1,8 +1,7 @@ - .icon-border { border-radius: 50%; border: 1px solid #f2f3f4; - background: #fff; + background: #ececf0; display: flex; justify-content: center; align-items: center; diff --git a/ui/app/components/ui/icon/icon.stories.js b/ui/app/components/ui/icon/icon.stories.js index 11209a32a..ff750bc5d 100644 --- a/ui/app/components/ui/icon/icon.stories.js +++ b/ui/app/components/ui/icon/icon.stories.js @@ -1,11 +1,14 @@ import React from 'react' -import { color, number } from '@storybook/addon-knobs' +import { color, number, select } from '@storybook/addon-knobs' +import { SEVERITIES } from '../../../helpers/constants/design-system' import Approve from './approve-icon.component' import Copy from './copy-icon.component' import Interaction from './interaction-icon.component' import Preloader from './preloader' import Receive from './receive-icon.component' import Send from './send-icon.component' +import InfoIcon from './info-icon.component' +import InfoIconInverted from './info-icon-inverted.component' export default { title: 'Icon', @@ -36,3 +39,17 @@ export const preloader = () => export const PaperAirplane = () => ( ) + +export const info = () => ( + +) + +export const infoInverted = () => ( + +) diff --git a/ui/app/components/ui/icon/index.scss b/ui/app/components/ui/icon/index.scss index 4e7e9c782..253f90b8f 100644 --- a/ui/app/components/ui/icon/index.scss +++ b/ui/app/components/ui/icon/index.scss @@ -2,18 +2,18 @@ margin: 0 4px; &--success { - fill: $accent-green; + fill: $success-1; } &--info { - fill: $primary-blue; + fill: $primary-1; } &--warning { - fill: $accent-yellow; + fill: $alert-3; } &--danger { - fill: $accent-red; + fill: $error-1; } } diff --git a/ui/app/components/ui/icon/info-icon-inverted.component.js b/ui/app/components/ui/icon/info-icon-inverted.component.js new file mode 100644 index 000000000..df057aa07 --- /dev/null +++ b/ui/app/components/ui/icon/info-icon-inverted.component.js @@ -0,0 +1,29 @@ +import React from 'react' +import classnames from 'classnames' +import PropTypes from 'prop-types' +import { SEVERITIES } from '../../../helpers/constants/design-system' + +export default function InfoIconInverted({ severity }) { + const className = classnames('info-icon', { + 'info-icon--success': severity === SEVERITIES.SUCCESS, + 'info-icon--warning': severity === SEVERITIES.WARNING, + 'info-icon--danger': severity === SEVERITIES.DANGER, + 'info-icon--info': severity === SEVERITIES.INFO, + }) + return ( + + + + ) +} + +InfoIconInverted.propTypes = { + severity: PropTypes.oneOf(Object.values(SEVERITIES)), +} diff --git a/ui/app/components/ui/icon/info-icon.component.js b/ui/app/components/ui/icon/info-icon.component.js index e177e5b33..3d2ec7e7d 100644 --- a/ui/app/components/ui/icon/info-icon.component.js +++ b/ui/app/components/ui/icon/info-icon.component.js @@ -1,13 +1,14 @@ import React from 'react' import classnames from 'classnames' import PropTypes from 'prop-types' +import { SEVERITIES } from '../../../helpers/constants/design-system' export default function InfoIcon({ severity }) { const className = classnames('info-icon', { - 'info-icon--success': severity === 'success', - 'info-icon--warning': severity === 'warning', - 'info-icon--danger': severity === 'danger', - 'info-icon--info': severity === 'info', + 'info-icon--success': severity === SEVERITIES.SUCCESS, + 'info-icon--warning': severity === SEVERITIES.WARNING, + 'info-icon--danger': severity === SEVERITIES.DANGER, + 'info-icon--info': severity === SEVERITIES.INFO, }) return ( Date: Mon, 1 Feb 2021 12:59:24 -0600 Subject: [PATCH 16/48] Fixup prop types and use constants (#10306) Co-authored-by: Mark Stacey --- .../components/app/dropdowns/network-dropdown.js | 8 ++++---- .../app/network-display/network-display.js | 16 ++++++++++++++-- .../ui/color-indicator/color-indicator.js | 10 ++-------- .../ui/color-indicator/color-indicator.scss | 8 +++++--- .../color-indicator/color-indicator.stories.js | 6 +++--- .../ui/definition-list/definition-list.js | 4 +++- .../networks-tab/networks-tab.component.js | 6 +++--- 7 files changed, 34 insertions(+), 24 deletions(-) diff --git a/ui/app/components/app/dropdowns/network-dropdown.js b/ui/app/components/app/dropdowns/network-dropdown.js index 4fe270b08..4de92e718 100644 --- a/ui/app/components/app/dropdowns/network-dropdown.js +++ b/ui/app/components/app/dropdowns/network-dropdown.js @@ -15,7 +15,7 @@ import { isPrefixedFormattedHexString } from '../../../../../shared/modules/util import { getEnvironmentType } from '../../../../../app/scripts/lib/util' import ColorIndicator from '../../ui/color-indicator' -import { COLORS } from '../../../helpers/constants/design-system' +import { COLORS, SIZES } from '../../../helpers/constants/design-system' import { Dropdown, DropdownMenuItem } from './components/dropdown' // classes from nodes of the toggle element. @@ -149,7 +149,7 @@ class NetworkDropdown extends Component { )} @@ -219,7 +219,7 @@ class NetworkDropdown extends Component { )} @@ -309,7 +309,7 @@ class NetworkDropdown extends Component { type={ColorIndicator.TYPES.FILLED} color={COLORS.TRANSPARENT} borderColor={COLORS.UI2} - size={ColorIndicator.SIZES.LARGE} + size={SIZES.LG} /> ({ @@ -36,7 +42,7 @@ export default function NetworkDisplay({ > ) } NetworkDisplay.propTypes = { colored: PropTypes.bool, + indicatorSize: PropTypes.oneOf(Object.values(SIZES)), + labelProps: PropTypes.shape({ + ...Chip.propTypes.labelProps, + }), outline: PropTypes.bool, disabled: PropTypes.bool, iconClassName: PropTypes.string, @@ -75,4 +86,5 @@ NetworkDisplay.propTypes = { NetworkDisplay.defaultProps = { colored: true, + indicatorSize: SIZES.LG, } diff --git a/ui/app/components/ui/color-indicator/color-indicator.js b/ui/app/components/ui/color-indicator/color-indicator.js index 83718a0f7..22ef28c0c 100644 --- a/ui/app/components/ui/color-indicator/color-indicator.js +++ b/ui/app/components/ui/color-indicator/color-indicator.js @@ -1,7 +1,7 @@ import React from 'react' import classnames from 'classnames' import PropTypes from 'prop-types' -import { COLORS } from '../../../helpers/constants/design-system' +import { COLORS, SIZES } from '../../../helpers/constants/design-system' export default function ColorIndicator({ size = 'small', @@ -29,12 +29,6 @@ export default function ColorIndicator({ ) } -ColorIndicator.SIZES = { - LARGE: 'large', - MEDIUM: 'medium', - SMALL: 'small,', -} - ColorIndicator.TYPES = { FILLED: 'filled', PARTIAL: 'partial-filled', @@ -44,7 +38,7 @@ ColorIndicator.TYPES = { ColorIndicator.propTypes = { color: PropTypes.oneOf(Object.values(COLORS)), borderColor: PropTypes.oneOf(Object.values(COLORS)), - size: PropTypes.oneOf(Object.values(ColorIndicator.SIZES)), + size: PropTypes.oneOf(Object.values(SIZES)), iconClassName: PropTypes.string, type: PropTypes.oneOf(Object.values(ColorIndicator.TYPES)), } diff --git a/ui/app/components/ui/color-indicator/color-indicator.scss b/ui/app/components/ui/color-indicator/color-indicator.scss index b6eb93104..4a3e1ca34 100644 --- a/ui/app/components/ui/color-indicator/color-indicator.scss +++ b/ui/app/components/ui/color-indicator/color-indicator.scss @@ -2,9 +2,11 @@ @use "design-system"; $sizes: ( - 'large': 6, - 'medium': 5, - 'small': 4, + 'xl': 8, + 'lg': 6, + 'md': 5, + 'sm': 4, + 'xs': 2.5, ); .color-indicator { diff --git a/ui/app/components/ui/color-indicator/color-indicator.stories.js b/ui/app/components/ui/color-indicator/color-indicator.stories.js index 81d7a2159..1c661869b 100644 --- a/ui/app/components/ui/color-indicator/color-indicator.stories.js +++ b/ui/app/components/ui/color-indicator/color-indicator.stories.js @@ -1,6 +1,6 @@ import React from 'react' import { select } from '@storybook/addon-knobs' -import { COLORS } from '../../../helpers/constants/design-system' +import { COLORS, SIZES } from '../../../helpers/constants/design-system' import ColorIndicator from './color-indicator' export default { @@ -9,7 +9,7 @@ export default { export const colorIndicator = () => ( ( export const withIcon = () => (
{this.context.t('newNetwork')} From 23bab62008c9137529c586f66356781af4cc3fc9 Mon Sep 17 00:00:00 2001 From: Thomas Huang Date: Mon, 1 Feb 2021 12:39:09 -0800 Subject: [PATCH 17/48] Reject eth_getEncryptionPublicKey for ledger hw wallets (#10326) Fixes #10111 Determine if the msgParams/address for the newRequestEncryptionPublicKey is a ledger keyring via getKeyringForAccount and return a promise rejection. --- app/scripts/metamask-controller.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index ad6483821..a61a40ed0 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -1643,6 +1643,13 @@ export default class MetamaskController extends EventEmitter { * Passed back to the requesting Dapp. */ async newRequestEncryptionPublicKey(msgParams, req) { + const address = msgParams + const keyring = await this.keyringController.getKeyringForAccount(address) + if (keyring.type === 'Ledger Hardware') { + return new Promise((_, reject) => { + reject(new Error('Ledger does not support eth_getEncryptionPublicKey.')) + }) + } const promise = this.encryptionPublicKeyManager.addUnapprovedMessageAsync( msgParams, req, From 6b34fb41840be199cb3fba7ef2af59e14b3a6e73 Mon Sep 17 00:00:00 2001 From: Etienne Dusseault Date: Tue, 2 Feb 2021 12:08:42 +0800 Subject: [PATCH 18/48] Use @lavamoat/allow-scripts (#10009) * use @lavamoat/allow-scripts for package postinstall allow list * dnode: set "weak" to false Co-authored-by: kumavis Co-authored-by: Erik Marks <25517051+rekmarks@users.noreply.github.com> --- .circleci/scripts/deps-install.sh | 21 +--- app/scripts/metamask-controller.js | 4 +- app/scripts/phishing-detect.js | 13 +- app/scripts/ui.js | 13 +- package.json | 30 +++++ yarn.lock | 192 ++++++++++++++++++++++++++++- 6 files changed, 240 insertions(+), 33 deletions(-) diff --git a/.circleci/scripts/deps-install.sh b/.circleci/scripts/deps-install.sh index 828d6e63a..9e1c36c4e 100755 --- a/.circleci/scripts/deps-install.sh +++ b/.circleci/scripts/deps-install.sh @@ -15,23 +15,6 @@ then mv ./*.har build-artifacts/yarn-install-har/ fi -# run each in subshell so directory change does not persist -# scripts can be any of: -# preinstall -# install -# postinstall +# use @lavamoat/allow-scripts instead of manually running install scripts so directory change does not persist -# for build -(cd node_modules/node-sass && yarn run postinstall) -(cd node_modules/optipng-bin && yarn run postinstall) -(cd node_modules/gifsicle && yarn run postinstall) -(cd node_modules/jpegtran-bin && yarn run postinstall) - -# for test -(cd node_modules/scrypt && yarn run install) -(cd node_modules/weak && yarn run install) -(cd node_modules/chromedriver && yarn run install) -(cd node_modules/geckodriver && yarn run postinstall) - -# for release -(cd node_modules/@sentry/cli && yarn run install) +yarn allow-scripts diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index a61a40ed0..732db7006 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -1919,7 +1919,9 @@ export default class MetamaskController extends EventEmitter { */ setupControllerConnection(outStream) { const api = this.getApi() - const dnode = Dnode(api) + // the "weak: false" option is for nodejs only (eg unit tests) + // it is a workaround for node v12 support + const dnode = Dnode(api, { weak: false }) // report new active controller connection this.activeControllerConnections += 1 this.emit('controllerConnectionChanged', this.activeControllerConnections) diff --git a/app/scripts/phishing-detect.js b/app/scripts/phishing-detect.js index cabe08aa3..300fe70fa 100644 --- a/app/scripts/phishing-detect.js +++ b/app/scripts/phishing-detect.js @@ -40,11 +40,16 @@ function start() { function setupControllerConnection(connectionStream, cb) { const eventEmitter = new EventEmitter() - const metaMaskControllerDnode = dnode({ - sendUpdate(state) { - eventEmitter.emit('update', state) + // the "weak: false" option is for nodejs only (eg unit tests) + // it is a workaround for node v12 support + const metaMaskControllerDnode = dnode( + { + sendUpdate(state) { + eventEmitter.emit('update', state) + }, }, - }) + { weak: false }, + ) connectionStream.pipe(metaMaskControllerDnode).pipe(connectionStream) metaMaskControllerDnode.once('remote', (backgroundConnection) => cb(null, backgroundConnection), diff --git a/app/scripts/ui.js b/app/scripts/ui.js index 7aca1b724..a67eb3e6a 100644 --- a/app/scripts/ui.js +++ b/app/scripts/ui.js @@ -139,11 +139,16 @@ function setupWeb3Connection(connectionStream) { */ function setupControllerConnection(connectionStream, cb) { const eventEmitter = new EventEmitter() - const backgroundDnode = Dnode({ - sendUpdate(state) { - eventEmitter.emit('update', state) + // the "weak: false" option is for nodejs only (eg unit tests) + // it is a workaround for node v12 support + const backgroundDnode = Dnode( + { + sendUpdate(state) { + eventEmitter.emit('update', state) + }, }, - }) + { weak: false }, + ) connectionStream.pipe(backgroundDnode).pipe(connectionStream) backgroundDnode.once('remote', function (backgroundConnection) { backgroundConnection.on = eventEmitter.on.bind(eventEmitter) diff --git a/package.json b/package.json index ce7dcaa9b..836898210 100644 --- a/package.json +++ b/package.json @@ -190,6 +190,7 @@ "@babel/preset-env": "^7.5.5", "@babel/preset-react": "^7.0.0", "@babel/register": "^7.5.5", + "@lavamoat/allow-scripts": "^1.0.0", "@metamask/eslint-config": "^4.1.0", "@metamask/forwarder": "^1.1.0", "@metamask/test-dapp": "^4.0.1", @@ -297,5 +298,34 @@ "engines": { "node": "^10.18.1", "yarn": "^1.16.0" + }, + "lavamoat": { + "allowScripts": { + "node-sass": true, + "optipng-bin": true, + "gifsicle": true, + "jpegtran-bin": true, + "scrypt": true, + "chromedriver": true, + "geckodriver": true, + "@sentry/cli": true, + "core-js": false, + "core-js-pure": false, + "keccak": false, + "secp256k1": false, + "web3": false, + "sha3": false, + "bufferutil": false, + "utf-8-validate": false, + "electron": false, + "ejs": false, + "sc-uws": false, + "sqlite3": false, + "leveldown": false, + "ursa-optional": false, + "gc-stats": false, + "github:assemblyscript/assemblyscript": false, + "tiny-secp256k1": false + } } } diff --git a/yarn.lock b/yarn.lock index 863f99915..ee2ea4787 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1951,6 +1951,17 @@ "@types/yargs" "^15.0.0" chalk "^3.0.0" +"@lavamoat/allow-scripts@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@lavamoat/allow-scripts/-/allow-scripts-1.0.0.tgz#b24de0b179f1b16aae7bc15d21948bd774fb05e9" + integrity sha512-xY98CJu2BAFirfZ+w4wRQxAMlolfFj7L5sIkUdZPlhFYIZjNis8kGKxvxN4uscbIOILS14nSIbGqrUwEddPGrA== + dependencies: + "@npmcli/run-script" "^1.8.1" + "@yarnpkg/lockfile" "^1.1.0" + semver "^7.3.4" + yargs "^16.2.0" + yarn-logical-tree "^1.0.2" + "@material-ui/core@^4.11.0": version "4.11.0" resolved "https://registry.yarnpkg.com/@material-ui/core/-/core-4.11.0.tgz#b69b26e4553c9e53f2bfaf1053e216a0af9be15a" @@ -2219,6 +2230,30 @@ dependencies: mkdirp "^1.0.4" +"@npmcli/node-gyp@^1.0.0": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@npmcli/node-gyp/-/node-gyp-1.0.1.tgz#dedc4ea9b3c6ef207081ebcd82c053ef60edc478" + integrity sha512-pBqoKPWmuk9iaEcXlLBVRIA6I1kG9JiICU+sG0NuD6NAR461F+02elHJS4WkQxHW2W5rnsfvP/ClKwmsZ9RaaA== + +"@npmcli/promise-spawn@^1.3.0": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@npmcli/promise-spawn/-/promise-spawn-1.3.2.tgz#42d4e56a8e9274fba180dabc0aea6e38f29274f5" + integrity sha512-QyAGYo/Fbj4MXeGdJcFzZ+FkDkomfRBrPM+9QYJSg+PxgAUL+LU3FneQk37rKR2/zjqkCV1BLHccX98wRXG3Sg== + dependencies: + infer-owner "^1.0.4" + +"@npmcli/run-script@^1.8.1": + version "1.8.1" + resolved "https://registry.yarnpkg.com/@npmcli/run-script/-/run-script-1.8.1.tgz#729c5ac7293f250b654504d263952703af6da39c" + integrity sha512-G8c86g9cQHyRINosIcpovzv0BkXQc3urhL1ORf3KTe4TS4UBsg2O4Z2feca/W3pfzdHEJzc83ETBW4aKbb3SaA== + dependencies: + "@npmcli/node-gyp" "^1.0.0" + "@npmcli/promise-spawn" "^1.3.0" + infer-owner "^1.0.4" + node-gyp "^7.1.0" + puka "^1.0.1" + read-package-json-fast "^1.1.3" + "@pmmmwh/react-refresh-webpack-plugin@^0.4.2": version "0.4.3" resolved "https://registry.yarnpkg.com/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.4.3.tgz#1eec460596d200c0236bf195b078a5d1df89b766" @@ -3800,7 +3835,7 @@ ajv@^4.7.0: co "^4.6.0" json-stable-stringify "^1.0.1" -ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.4, ajv@^6.12.5, ajv@^6.5.5, ajv@^6.9.1: +ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.3, ajv@^6.12.4, ajv@^6.12.5, ajv@^6.5.5, ajv@^6.9.1: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== @@ -7103,6 +7138,15 @@ cliui@^6.0.0: strip-ansi "^6.0.0" wrap-ansi "^6.2.0" +cliui@^7.0.2: + version "7.0.4" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" + integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^7.0.0" + clone-buffer@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/clone-buffer/-/clone-buffer-1.0.0.tgz#e3e25b207ac4e701af721e2cb5a16792cac3dc58" @@ -12048,7 +12092,7 @@ get-caller-file@^1.0.1: resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.2.tgz#f702e63127e7e231c160a80c1554acb70d5047e5" integrity sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U= -get-caller-file@^2.0.1: +get-caller-file@^2.0.1, get-caller-file@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== @@ -12639,7 +12683,7 @@ graceful-fs@4.X, graceful-fs@^4.0.0, graceful-fs@^4.1.10, graceful-fs@^4.1.11, g resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423" integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ== -graceful-fs@^4.1.6, graceful-fs@^4.2.0: +graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.3: version "4.2.4" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== @@ -12957,6 +13001,14 @@ har-validator@~5.1.0: ajv "^6.5.5" har-schema "^2.0.0" +har-validator@~5.1.3: + version "5.1.5" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd" + integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w== + dependencies: + ajv "^6.12.3" + har-schema "^2.0.0" + hard-rejection@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/hard-rejection/-/hard-rejection-2.1.0.tgz#1c6eda5c1685c63942766d79bb40ae773cecd883" @@ -15449,6 +15501,11 @@ json-parse-better-errors@^1.0.1, json-parse-better-errors@^1.0.2: resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== +json-parse-even-better-errors@^2.3.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" + integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== + json-rpc-engine@^3.4.0, json-rpc-engine@^3.6.0: version "3.8.0" resolved "https://registry.yarnpkg.com/json-rpc-engine/-/json-rpc-engine-3.8.0.tgz#9d4ff447241792e1d0a232f6ef927302bb0c62a9" @@ -18447,6 +18504,22 @@ node-gyp@^3.8.0: tar "^2.0.0" which "1" +node-gyp@^7.1.0: + version "7.1.2" + resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-7.1.2.tgz#21a810aebb187120251c3bcec979af1587b188ae" + integrity sha512-CbpcIo7C3eMu3dL1c3d0xw449fHIGALIJsRP4DDPHpyiW8vcriNY7ubh9TE4zEKfSxscY7PjeFnshE7h75ynjQ== + dependencies: + env-paths "^2.2.0" + glob "^7.1.4" + graceful-fs "^4.2.3" + nopt "^5.0.0" + npmlog "^4.1.2" + request "^2.88.2" + rimraf "^3.0.2" + semver "^7.3.2" + tar "^6.0.2" + which "^2.0.2" + node-libs-browser@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.2.1.tgz#b64f513d18338625f90346d27b0d235e631f6425" @@ -18617,6 +18690,13 @@ nopt@^4.0.1: abbrev "1" osenv "^0.1.4" +nopt@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-5.0.0.tgz#530942bb58a512fccafe53fe210f13a25355dc88" + integrity sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ== + dependencies: + abbrev "1" + normalize-package-data@^2.0.0, normalize-package-data@^2.3.2, normalize-package-data@^2.3.4, normalize-package-data@^2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" @@ -18688,6 +18768,16 @@ npm-conf@^1.1.0, npm-conf@^1.1.3: config-chain "^1.1.11" pify "^3.0.0" +npm-logical-tree@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/npm-logical-tree/-/npm-logical-tree-1.2.1.tgz#44610141ca24664cad35d1e607176193fd8f5b88" + integrity sha512-AJI/qxDB2PWI4LG1CYN579AY1vCiNyWfkiquCsJWqntRu/WwimVrC8yXeILBFHDwxfOejxewlmnvW9XXjMlYIg== + +npm-normalize-package-bin@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz#6e79a41f23fd235c0623218228da7d9c23b8f6e2" + integrity sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA== + npm-packlist@^1.1.6: version "1.4.1" resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.1.tgz#19064cdf988da80ea3cee45533879d90192bbfbc" @@ -20767,6 +20857,11 @@ psl@^1.1.24: resolved "https://registry.yarnpkg.com/psl/-/psl-1.4.0.tgz#5dd26156cdb69fa1fdb8ab1991667d3f80ced7c2" integrity sha512-HZzqCGPecFLyoRj5HLfuDSKYTJkAfB5thKBIkRHtGjWwY7p1dAyveIbXIq4tO0KYfDF2tHqPUgY9SDnGm00uFw== +psl@^1.1.28: + version "1.8.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24" + integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ== + public-encrypt@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.0.tgz#39f699f3a46560dd5ebacbca693caf7c65c18cc6" @@ -20789,6 +20884,11 @@ pubnub@4.27.3: superagent "^3.8.1" superagent-proxy "^2.0.0" +puka@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/puka/-/puka-1.0.1.tgz#a2df782b7eb4cf9564e4c93a5da422de0dfacc02" + integrity sha512-ssjRZxBd7BT3dte1RR3VoeT2cT/ODH8x+h0rUF1rMqB0srHYf48stSDWfiYakTp5UBZMxroZhB2+ExLDHm7W3g== + pull-abortable@^4.1.0, pull-abortable@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/pull-abortable/-/pull-abortable-4.1.1.tgz#b3ad5aefb4116b25916d26db89393ac98d0dcea1" @@ -21671,6 +21771,14 @@ read-only-stream@^2.0.0: dependencies: readable-stream "^2.0.2" +read-package-json-fast@^1.1.3: + version "1.2.1" + resolved "https://registry.yarnpkg.com/read-package-json-fast/-/read-package-json-fast-1.2.1.tgz#e8518d6f37c99eb3afc26704c5cbb50d7ead82dd" + integrity sha512-OFbpwnHcv74Oa5YN5WvbOBfLw6yPmPcwvyJJw/tj9cWFBF7juQUDLDSZiOjEcgzfweWeeROOmbPpNN1qm4hcRg== + dependencies: + json-parse-even-better-errors "^2.3.0" + npm-normalize-package-bin "^1.0.1" + read-package-json@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/read-package-json/-/read-package-json-2.1.0.tgz#e3d42e6c35ea5ae820d9a03ab0c7291217fc51d5" @@ -22336,6 +22444,32 @@ request@^2.79.0, request@^2.83.0, request@^2.85.0, request@^2.87.0, request@^2.8 tunnel-agent "^0.6.0" uuid "^3.3.2" +request@^2.88.2: + version "2.88.2" + resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" + integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.8.0" + caseless "~0.12.0" + combined-stream "~1.0.6" + extend "~3.0.2" + forever-agent "~0.6.1" + form-data "~2.3.2" + har-validator "~5.1.3" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.19" + oauth-sign "~0.9.0" + performance-now "^2.1.0" + qs "~6.5.2" + safe-buffer "^5.1.2" + tough-cookie "~2.5.0" + tunnel-agent "^0.6.0" + uuid "^3.3.2" + require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" @@ -23114,7 +23248,7 @@ semver@^7.2.1: resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938" integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ== -semver@^7.3.2: +semver@^7.3.2, semver@^7.3.4: version "7.3.4" resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.4.tgz#27aaa7d2e4ca76452f98d3add093a72c943edc97" integrity sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw== @@ -25156,6 +25290,14 @@ tough-cookie@>=2.3.3, tough-cookie@^2.3.3, tough-cookie@~2.4.3: psl "^1.1.24" punycode "^1.4.1" +tough-cookie@~2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" + integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== + dependencies: + psl "^1.1.28" + punycode "^2.1.1" + tr46@^1.0.0, tr46@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/tr46/-/tr46-1.0.1.tgz#a8b13fd6bfd2489519674ccde55ba3693b706d09" @@ -26718,7 +26860,7 @@ which@1, which@1.3.1, which@^1.2.14, which@^1.2.9, which@^1.3.1: dependencies: isexe "^2.0.0" -which@^2.0.1: +which@^2.0.1, which@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== @@ -26808,6 +26950,15 @@ wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" @@ -26993,6 +27144,11 @@ y18n@^4.0.0: resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w== +y18n@^5.0.5: + version "5.0.5" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.5.tgz#8769ec08d03b1ea2df2500acef561743bbb9ab18" + integrity sha512-hsRUr4FFrvhhRH12wOdfs38Gy7k2FFzB9qgN9v3aLykRq0dRcdcpz5C9FxdS2NuhOrI/628b/KSTJ3rwHysYSg== + yaeti@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/yaeti/-/yaeti-0.0.6.tgz#f26f484d72684cf42bedfb76970aa1608fbf9577" @@ -27044,6 +27200,11 @@ yargs-parser@^18.1.2, yargs-parser@^18.1.3: camelcase "^5.0.0" decamelize "^1.2.0" +yargs-parser@^20.2.2: + version "20.2.4" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" + integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== + yargs-promise@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/yargs-promise/-/yargs-promise-1.1.0.tgz#97ebb5198df734bb3b11745133ae5b501b16ab1f" @@ -27125,6 +27286,19 @@ yargs@^15.0.0, yargs@^15.0.2, yargs@^15.3.1: y18n "^4.0.0" yargs-parser "^18.1.2" +yargs@^16.2.0: + version "16.2.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" + integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.0" + y18n "^5.0.5" + yargs-parser "^20.2.2" + yargs@^7.1.0: version "7.1.1" resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.1.tgz#67f0ef52e228d4ee0d6311acede8850f53464df6" @@ -27144,6 +27318,14 @@ yargs@^7.1.0: y18n "^3.2.1" yargs-parser "5.0.0-security.0" +yarn-logical-tree@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/yarn-logical-tree/-/yarn-logical-tree-1.0.2.tgz#11130e00333b02174efcfd5599a5e68ca356fa14" + integrity sha512-ra0Bl8oB7sN4fkWSSC2+P3luaFiwFFJ/KcCLSjY6HHRvKcBMjOcIIF1z6IHU+plmEYyZOc546cWwi0f0QiOQtw== + dependencies: + npm-logical-tree "^1.2.1" + semver "^5.5.0" + yauzl@2.10.0, yauzl@^2.10.0, yauzl@^2.4.2: version "2.10.0" resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" From 99b6fee0ed7cd7224a7473c47c051d3d5e548ffe Mon Sep 17 00:00:00 2001 From: Thomas Huang Date: Tue, 2 Feb 2021 00:55:12 -0800 Subject: [PATCH 19/48] Stub out background and bg methods in actions test (#10321) Move from using the backgound/metamask-controller instance to a stubbed/mocked out verison of the background methods. --- test/unit/ui/app/actions.spec.js | 1240 +++++++++++++++++++----------- 1 file changed, 770 insertions(+), 470 deletions(-) diff --git a/test/unit/ui/app/actions.spec.js b/test/unit/ui/app/actions.spec.js index 5e9ad3909..6a02830a8 100644 --- a/test/unit/ui/app/actions.spec.js +++ b/test/unit/ui/app/actions.spec.js @@ -1,135 +1,119 @@ import assert from 'assert' import sinon from 'sinon' -import { cloneDeep } from 'lodash' import configureStore from 'redux-mock-store' import thunk from 'redux-thunk' import EthQuery from 'eth-query' import Eth from 'ethjs' -import KeyringController from 'eth-keyring-controller' import { createTestProviderTools } from '../../../stub/provider' import enLocale from '../../../../app/_locales/en/messages.json' import * as actions from '../../../../ui/app/store/actions' import MetaMaskController from '../../../../app/scripts/metamask-controller' -import firstTimeState from '../../localhostState' import { TRANSACTION_STATUSES } from '../../../../shared/constants/transaction' const { provider } = createTestProviderTools({ scaffold: {} }) const middleware = [thunk] -const defaultState = { metamask: { provider: { chainId: '0x1' } } } -const mockStore = (state = defaultState) => configureStore(middleware)(state) -const extensionMock = { - runtime: { - onInstalled: { - addListener: () => undefined, - }, +const defaultState = { + metamask: { + currentLocale: 'test', + selectedAddress: '0xFirstAddress', + provider: { chainId: '0x1' }, }, } +const mockStore = (state = defaultState) => configureStore(middleware)(state) describe('Actions', function () { - const noop = () => undefined + let background const currentNetworkId = '42' - let background, metamaskController - - const TEST_SEED = - 'debris dizzy just program just float decrease vacant alarm reduce speak stadium' - const password = 'a-fake-password' - const importPrivkey = - '4cfd3e90fc78b0f86bf7524722150bb8da9c60cd532564d7ff43f5716514f553' - beforeEach(async function () { - metamaskController = new MetaMaskController({ - extension: extensionMock, - platform: { getVersion: () => 'foo' }, - provider, - keyringController: new KeyringController({}), - showUserConfirmation: noop, - encryptor: { - encrypt(_, object) { - this.object = object - return Promise.resolve('mock-encrypted') - }, - decrypt() { - return Promise.resolve(this.object) - }, - }, - initLangCode: 'en_US', - initState: cloneDeep(firstTimeState), - infuraProjectId: 'foo', + background = sinon.createStubInstance(MetaMaskController, { + getState: sinon.stub().callsFake((cb) => + cb(null, { + currentLocale: 'test', + selectedAddress: '0xFirstAddress', + }), + ), }) - metamaskController.threeBoxController = { - new3Box: sinon.spy(), - getThreeBoxSyncingState: sinon.spy(), - } - - await metamaskController.createNewVaultAndRestore(password, TEST_SEED) - - await metamaskController.importAccountWithStrategy('Private Key', [ - importPrivkey, - ]) - - background = metamaskController.getApi() - - actions._setBackgroundConnection(background) - global.ethQuery = new EthQuery(provider) }) describe('#tryUnlockMetamask', function () { - let submitPasswordSpy, verifySeedPhraseSpy - afterEach(function () { - submitPasswordSpy.restore() - verifySeedPhraseSpy.restore() + sinon.restore() }) it('calls submitPassword and verifySeedPhrase', async function () { const store = mockStore() - submitPasswordSpy = sinon.spy(background, 'submitPassword') - verifySeedPhraseSpy = sinon.spy(background, 'verifySeedPhrase') + const submitPassword = background.submitPassword.callsFake((_, cb) => + cb(), + ) + + const verifySeedPhrase = background.verifySeedPhrase.callsFake((cb) => + cb(), + ) + + actions._setBackgroundConnection(background) + + const expectedActions = [ + { type: 'SHOW_LOADING_INDICATION', value: undefined }, + { type: 'UNLOCK_IN_PROGRESS' }, + { type: 'UNLOCK_SUCCEEDED', value: undefined }, + { + type: 'UPDATE_METAMASK_STATE', + value: { + currentLocale: 'test', + selectedAddress: '0xFirstAddress', + }, + }, + { type: 'HIDE_LOADING_INDICATION' }, + ] await store.dispatch(actions.tryUnlockMetamask()) - assert(submitPasswordSpy.calledOnce) - assert(verifySeedPhraseSpy.calledOnce) + + assert(submitPassword.calledOnce) + assert(verifySeedPhrase.calledOnce) + + assert.deepStrictEqual(store.getActions(), expectedActions) }) it('errors on submitPassword will fail', async function () { const store = mockStore() + background.submitPassword.callsFake((_, cb) => cb(new Error('error'))) + + actions._setBackgroundConnection(background) + const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', value: undefined }, { type: 'UNLOCK_IN_PROGRESS' }, - { type: 'UNLOCK_FAILED', value: 'error in submitPassword' }, + { type: 'UNLOCK_FAILED', value: 'error' }, { type: 'HIDE_LOADING_INDICATION' }, ] - submitPasswordSpy = sinon.stub(background, 'submitPassword') - - submitPasswordSpy.callsFake((_, callback) => { - callback(new Error('error in submitPassword')) - }) - try { await store.dispatch(actions.tryUnlockMetamask('test')) assert.fail('Should have thrown error') } catch (_) { - assert.deepEqual(store.getActions(), expectedActions) + assert.deepStrictEqual(store.getActions(), expectedActions) } }) it('displays warning error and unlock failed when verifySeed fails', async function () { const store = mockStore() + + background.submitPassword.callsFake((_, cb) => cb()) + background.verifySeedPhrase.callsFake((cb) => { + cb(new Error('error')) + }) + + actions._setBackgroundConnection(background) + const displayWarningError = [{ type: 'DISPLAY_WARNING', value: 'error' }] const unlockFailedError = [{ type: 'UNLOCK_FAILED', value: 'error' }] - verifySeedPhraseSpy = sinon.stub(background, 'verifySeedPhrase') - verifySeedPhraseSpy.callsFake((callback) => { - callback(new Error('error')) - }) - try { await store.dispatch(actions.tryUnlockMetamask('test')) assert.fail('Should have thrown error') @@ -141,111 +125,149 @@ describe('Actions', function () { const unlockFailed = actions1.filter( (action) => action.type === 'UNLOCK_FAILED', ) - assert.deepEqual(warning, displayWarningError) - assert.deepEqual(unlockFailed, unlockFailedError) + assert.deepStrictEqual(warning, displayWarningError) + assert.deepStrictEqual(unlockFailed, unlockFailedError) } }) }) describe('#createNewVaultAndRestore', function () { - let createNewVaultAndRestoreSpy - afterEach(function () { - createNewVaultAndRestoreSpy.restore() + sinon.restore() }) - it('restores new vault', async function () { + it('calls createNewVaultAndRestore', async function () { const store = mockStore() - createNewVaultAndRestoreSpy = sinon.spy( - background, - 'createNewVaultAndRestore', + const createNewVaultAndRestore = background.createNewVaultAndRestore.callsFake( + (_, __, cb) => cb(), ) - try { - await store.dispatch(actions.createNewVaultAndRestore()) - assert.fail('Should have thrown error') - } catch (_) { - assert(createNewVaultAndRestoreSpy.calledOnce) - } + background.unMarkPasswordForgotten.callsFake((cb) => cb()) + + actions._setBackgroundConnection(background) + + await store.dispatch(actions.createNewVaultAndRestore()) + assert(createNewVaultAndRestore.calledOnce) + }) + + it('calls the expected actions', async function () { + const store = mockStore() + + background.createNewVaultAndRestore.callsFake((_, __, cb) => cb()) + background.unMarkPasswordForgotten.callsFake((cb) => cb()) + + actions._setBackgroundConnection(background) + + const expectedActions = [ + { type: 'SHOW_LOADING_INDICATION', value: undefined }, + { type: 'FORGOT_PASSWORD', value: false }, + { + type: 'UPDATE_METAMASK_STATE', + value: { + currentLocale: 'test', + selectedAddress: '0xFirstAddress', + }, + }, + { type: 'SHOW_ACCOUNTS_PAGE' }, + { type: 'HIDE_LOADING_INDICATION' }, + ] + + await store.dispatch(actions.createNewVaultAndRestore()) + + assert.deepStrictEqual(store.getActions(), expectedActions) }) it('errors when callback in createNewVaultAndRestore throws', async function () { const store = mockStore() + background.createNewVaultAndRestore.callsFake((_, __, cb) => + cb(new Error('error')), + ) + + actions._setBackgroundConnection(background) + const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', value: undefined }, { type: 'DISPLAY_WARNING', value: 'error' }, { type: 'HIDE_LOADING_INDICATION' }, ] - createNewVaultAndRestoreSpy = sinon.stub( - background, - 'createNewVaultAndRestore', - ) - - createNewVaultAndRestoreSpy.callsFake((_, __, callback) => { - callback(new Error('error')) - }) - try { await store.dispatch(actions.createNewVaultAndRestore()) assert.fail('Should have thrown error') } catch (_) { - assert.deepEqual(store.getActions(), expectedActions) + assert.deepStrictEqual(store.getActions(), expectedActions) } }) }) describe('#requestRevealSeedWords', function () { - let submitPasswordSpy - afterEach(function () { - submitPasswordSpy.restore() + sinon.restore() }) - it('calls submitPassword in background', async function () { + it('calls verifyPassword in background', async function () { const store = mockStore() - submitPasswordSpy = sinon.spy(background, 'verifySeedPhrase') + const verifyPassword = background.verifyPassword.callsFake((_, cb) => + cb(), + ) + const verifySeedPhrase = background.verifySeedPhrase.callsFake((cb) => + cb(), + ) + + actions._setBackgroundConnection(background) await store.dispatch(actions.requestRevealSeedWords()) - assert(submitPasswordSpy.calledOnce) + assert(verifyPassword.calledOnce) + assert(verifySeedPhrase.calledOnce) }) it('displays warning error message then callback in background errors', async function () { const store = mockStore() + background.verifyPassword.callsFake((_, cb) => cb()) + background.verifySeedPhrase.callsFake((cb) => { + cb(new Error('error')) + }) + + actions._setBackgroundConnection(background) + const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', value: undefined }, { type: 'DISPLAY_WARNING', value: 'error' }, { type: 'HIDE_LOADING_INDICATION' }, ] - submitPasswordSpy = sinon.stub(background, 'verifySeedPhrase') - submitPasswordSpy.callsFake((callback) => { - callback(new Error('error')) - }) - try { await store.dispatch(actions.requestRevealSeedWords()) assert.fail('Should have thrown error') } catch (_) { - assert.deepEqual(store.getActions(), expectedActions) + assert.deepStrictEqual(store.getActions(), expectedActions) } }) }) describe('#removeAccount', function () { - let removeAccountStub - afterEach(function () { - removeAccountStub.restore() + sinon.restore() }) it('calls removeAccount in background and expect actions to show account', async function () { const store = mockStore() + background.getState.callsFake((cb) => + cb(null, { + currentLocale: 'test', + selectedAddress: '0xAnotherAddress', + }), + ) + + const removeAccount = background.removeAccount.callsFake((_, cb) => cb()) + + actions._setBackgroundConnection(background) + const expectedActions = [ 'SHOW_LOADING_INDICATION', 'SELECTED_ADDRESS_CHANGED', @@ -254,31 +276,29 @@ describe('Actions', function () { 'SHOW_ACCOUNTS_PAGE', ] - removeAccountStub = sinon.stub(background, 'removeAccount') - removeAccountStub.callsFake((_, callback) => callback()) - await store.dispatch( actions.removeAccount('0xe18035bf8712672935fdb4e5e431b1a0183d2dfc'), ) - assert(removeAccountStub.calledOnce) + assert(removeAccount.calledOnce) const actionTypes = store.getActions().map((action) => action.type) - assert.deepEqual(actionTypes, expectedActions) + assert.deepStrictEqual(actionTypes, expectedActions) }) it('displays warning error message when removeAccount callback errors', async function () { const store = mockStore() + background.removeAccount.callsFake((_, cb) => { + cb(new Error('error')) + }) + + actions._setBackgroundConnection(background) + const expectedActions = [ 'SHOW_LOADING_INDICATION', 'DISPLAY_WARNING', 'HIDE_LOADING_INDICATION', ] - removeAccountStub = sinon.stub(background, 'removeAccount') - removeAccountStub.callsFake((_, callback) => { - callback(new Error('error')) - }) - try { await store.dispatch( actions.removeAccount('0xe18035bf8712672935fdb4e5e431b1a0183d2dfc'), @@ -286,83 +306,91 @@ describe('Actions', function () { assert.fail('Should have thrown error') } catch (_) { const actionTypes = store.getActions().map((action) => action.type) - assert.deepEqual(actionTypes, expectedActions) + assert.deepStrictEqual(actionTypes, expectedActions) } }) }) describe('#resetAccount', function () { - let resetAccountSpy - afterEach(function () { - resetAccountSpy.restore() + sinon.restore() }) it('resets account', async function () { const store = mockStore() + const resetAccount = background.resetAccount.callsFake((cb) => cb()) + + actions._setBackgroundConnection(background) + const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', value: undefined }, { type: 'HIDE_LOADING_INDICATION' }, { type: 'SHOW_ACCOUNTS_PAGE' }, ] - resetAccountSpy = sinon.spy(background, 'resetAccount') - await store.dispatch(actions.resetAccount()) - assert(resetAccountSpy.calledOnce) - assert.deepEqual(store.getActions(), expectedActions) + assert(resetAccount.calledOnce) + assert.deepStrictEqual(store.getActions(), expectedActions) }) it('throws if resetAccount throws', async function () { const store = mockStore() + background.resetAccount.callsFake((cb) => { + cb(new Error('error')) + }) + + actions._setBackgroundConnection(background) + const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', value: undefined }, { type: 'HIDE_LOADING_INDICATION' }, { type: 'DISPLAY_WARNING', value: 'error' }, ] - resetAccountSpy = sinon.stub(background, 'resetAccount') - resetAccountSpy.callsFake((callback) => { - callback(new Error('error')) - }) - try { await store.dispatch(actions.resetAccount()) assert.fail('Should have thrown error') } catch (_) { - assert.deepEqual(store.getActions(), expectedActions) + assert.deepStrictEqual(store.getActions(), expectedActions) } }) }) describe('#importNewAccount', function () { - let importAccountWithStrategySpy - afterEach(function () { - importAccountWithStrategySpy.restore() + sinon.restore() }) it('calls importAccountWithStrategies in background', async function () { const store = mockStore() - importAccountWithStrategySpy = sinon.spy( - background, - 'importAccountWithStrategy', + const importAccountWithStrategy = background.importAccountWithStrategy.callsFake( + (_, __, cb) => { + cb() + }, ) + actions._setBackgroundConnection(background) + await store.dispatch( actions.importNewAccount('Private Key', [ 'c87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3', ]), ) - assert(importAccountWithStrategySpy.calledOnce) + assert(importAccountWithStrategy.calledOnce) }) it('displays warning error message when importAccount in background callback errors', async function () { const store = mockStore() + background.importAccountWithStrategy.callsFake((_, __, cb) => + cb(new Error('error')), + ) + + actions._setBackgroundConnection(background) + const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', @@ -372,19 +400,11 @@ describe('Actions', function () { { type: 'HIDE_LOADING_INDICATION' }, ] - importAccountWithStrategySpy = sinon.stub( - background, - 'importAccountWithStrategy', - ) - importAccountWithStrategySpy.callsFake((_, __, callback) => { - callback(new Error('error')) - }) - try { await store.dispatch(actions.importNewAccount()) assert.fail('Should have thrown error') } catch (_) { - assert.deepEqual(store.getActions(), expectedActions) + assert.deepStrictEqual(store.getActions(), expectedActions) } }) }) @@ -393,38 +413,73 @@ describe('Actions', function () { it('Adds a new account', async function () { const store = mockStore({ metamask: { identities: {} } }) - const addNewAccountSpy = sinon.spy(background, 'addNewAccount') + const addNewAccount = background.addNewAccount.callsFake((cb) => + cb(null, { + identities: {}, + }), + ) + + actions._setBackgroundConnection(background) await store.dispatch(actions.addNewAccount()) - assert(addNewAccountSpy.calledOnce) + assert(addNewAccount.calledOnce) + }) + + it('displays warning error message when addNewAccount in background callback errors', async function () { + const store = mockStore() + + background.addNewAccount.callsFake((cb) => { + cb(new Error('error')) + }) + + actions._setBackgroundConnection(background) + + const expectedActions = [ + { type: 'SHOW_LOADING_INDICATION', value: undefined }, + { type: 'DISPLAY_WARNING', value: 'error' }, + { type: 'HIDE_LOADING_INDICATION' }, + ] + + try { + await store.dispatch(actions.addNewAccount()) + assert.fail('Should have thrown error') + } catch (_) { + assert.deepStrictEqual(store.getActions(), expectedActions) + } }) }) describe('#checkHardwareStatus', function () { - let checkHardwareStatusSpy - afterEach(function () { - checkHardwareStatusSpy.restore() + sinon.restore() }) it('calls checkHardwareStatus in background', async function () { - checkHardwareStatusSpy = sinon - .stub(background, 'checkHardwareStatus') - .callsArgWith(2, null) const store = mockStore() + const checkHardwareStatus = background.checkHardwareStatus.callsFake( + (_, __, cb) => { + cb() + }, + ) + + actions._setBackgroundConnection(background) + await store.dispatch( actions.checkHardwareStatus('ledger', `m/44'/60'/0'/0`), ) - assert.equal(checkHardwareStatusSpy.calledOnce, true) + assert.strictEqual(checkHardwareStatus.calledOnce, true) }) it('shows loading indicator and displays error', async function () { - checkHardwareStatusSpy = sinon - .stub(background, 'checkHardwareStatus') - .callsArgWith(2, new Error('error')) const store = mockStore() + background.checkHardwareStatus.callsFake((_, __, cb) => + cb(new Error('error')), + ) + + actions._setBackgroundConnection(background) + const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', value: undefined }, { type: 'DISPLAY_WARNING', value: 'error' }, @@ -435,34 +490,34 @@ describe('Actions', function () { await store.dispatch(actions.checkHardwareStatus()) assert.fail('Should have thrown error') } catch (_) { - assert.deepEqual(store.getActions(), expectedActions) + assert.deepStrictEqual(store.getActions(), expectedActions) } }) }) describe('#forgetDevice', function () { - let forgetDeviceSpy - afterEach(function () { - forgetDeviceSpy.restore() + sinon.restore() }) it('calls forgetDevice in background', async function () { - forgetDeviceSpy = sinon - .stub(background, 'forgetDevice') - .callsArgWith(1, null) const store = mockStore() + const forgetDevice = background.forgetDevice.callsFake((_, cb) => cb()) + + actions._setBackgroundConnection(background) + await store.dispatch(actions.forgetDevice('ledger')) - assert.equal(forgetDeviceSpy.calledOnce, true) + assert(forgetDevice.calledOnce) }) it('shows loading indicator and displays error', async function () { - forgetDeviceSpy = sinon - .stub(background, 'forgetDevice') - .callsArgWith(1, new Error('error')) const store = mockStore() + background.forgetDevice.callsFake((_, cb) => cb(new Error('error'))) + + actions._setBackgroundConnection(background) + const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', value: undefined }, { type: 'DISPLAY_WARNING', value: 'error' }, @@ -473,36 +528,40 @@ describe('Actions', function () { await store.dispatch(actions.forgetDevice()) assert.fail('Should have thrown error') } catch (_) { - assert.deepEqual(store.getActions(), expectedActions) + assert.deepStrictEqual(store.getActions(), expectedActions) } }) }) describe('#connectHardware', function () { - let connectHardwareSpy - afterEach(function () { - connectHardwareSpy.restore() + sinon.restore() }) it('calls connectHardware in background', async function () { - connectHardwareSpy = sinon - .stub(background, 'connectHardware') - .callsArgWith(3, null) const store = mockStore() + const connectHardware = background.connectHardware.callsFake( + (_, __, ___, cb) => cb(), + ) + + actions._setBackgroundConnection(background) + await store.dispatch( actions.connectHardware('ledger', 0, `m/44'/60'/0'/0`), ) - assert.equal(connectHardwareSpy.calledOnce, true) + assert(connectHardware.calledOnce) }) it('shows loading indicator and displays error', async function () { - connectHardwareSpy = sinon - .stub(background, 'connectHardware') - .callsArgWith(3, new Error('error')) const store = mockStore() + background.connectHardware.callsFake((_, __, ___, cb) => + cb(new Error('error')), + ) + + actions._setBackgroundConnection(background) + const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', @@ -516,36 +575,39 @@ describe('Actions', function () { await store.dispatch(actions.connectHardware('ledger')) assert.fail('Should have thrown error') } catch (_) { - assert.deepEqual(store.getActions(), expectedActions) + assert.deepStrictEqual(store.getActions(), expectedActions) } }) }) describe('#unlockHardwareWalletAccount', function () { - let unlockHardwareWalletAccountSpy - afterEach(function () { - unlockHardwareWalletAccountSpy.restore() + sinon.restore() }) it('calls unlockHardwareWalletAccount in background', async function () { - unlockHardwareWalletAccountSpy = sinon - .stub(background, 'unlockHardwareWalletAccount') - .callsArgWith(3, null) const store = mockStore() + const unlockHardwareWalletAccount = background.unlockHardwareWalletAccount.callsFake( + (_, __, ___, cb) => cb(), + ) + + actions._setBackgroundConnection(background) await store.dispatch( actions.unlockHardwareWalletAccount('ledger', 0, `m/44'/60'/0'/0`), ) - assert.equal(unlockHardwareWalletAccountSpy.calledOnce, true) + assert(unlockHardwareWalletAccount.calledOnce) }) it('shows loading indicator and displays error', async function () { - unlockHardwareWalletAccountSpy = sinon - .stub(background, 'unlockHardwareWalletAccount') - .callsArgWith(3, new Error('error')) const store = mockStore() + background.unlockHardwareWalletAccount.callsFake((_, __, ___, cb) => + cb(new Error('error')), + ) + + actions._setBackgroundConnection(background) + const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', value: undefined }, { type: 'HIDE_LOADING_INDICATION' }, @@ -556,33 +618,40 @@ describe('Actions', function () { await store.dispatch(actions.unlockHardwareWalletAccount()) assert.fail('Should have thrown error') } catch (error) { - assert.deepEqual(store.getActions(), expectedActions) + assert.deepStrictEqual(store.getActions(), expectedActions) } }) }) describe('#setCurrentCurrency', function () { - let setCurrentCurrencySpy - afterEach(function () { - setCurrentCurrencySpy.restore() + sinon.restore() }) it('calls setCurrentCurrency', async function () { - setCurrentCurrencySpy = sinon - .stub(background, 'setCurrentCurrency') - .callsArgWith(1, null, {}) const store = mockStore() + const setCurrentCurrency = background.setCurrentCurrency.callsFake( + (_, cb) => + cb(null, { + currentCurrency: 'currency', + conversionRate: 100, + conversionDate: 1611839083653, + }), + ) + + actions._setBackgroundConnection(background) await store.dispatch(actions.setCurrentCurrency('jpy')) - assert(setCurrentCurrencySpy.calledOnce) + assert(setCurrentCurrency.calledOnce) }) it('throws if setCurrentCurrency throws', async function () { - setCurrentCurrencySpy = sinon - .stub(background, 'setCurrentCurrency') - .callsArgWith(1, new Error('error')) const store = mockStore() + + background.setCurrentCurrency.callsFake((_, cb) => cb(new Error('error'))) + + actions._setBackgroundConnection(background) + const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', value: undefined }, { type: 'DISPLAY_WARNING', value: 'error' }, @@ -590,104 +659,96 @@ describe('Actions', function () { ] await store.dispatch(actions.setCurrentCurrency()) - assert.deepEqual(store.getActions(), expectedActions) + assert.deepStrictEqual(store.getActions(), expectedActions) }) }) describe('#signMsg', function () { - let signMessageSpy, metamaskMsgs, msgId, messages - const msgParams = { + metamaskId: 123, from: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc', data: '0x879a053d4800c6354e76c7985a865d2922c82fb5b3f4577b2fe08b998954f2e0', } - beforeEach(function () { - metamaskController.newUnsignedMessage(msgParams, noop) - metamaskMsgs = metamaskController.messageManager.getUnapprovedMsgs() - messages = metamaskController.messageManager.messages - msgId = Object.keys(metamaskMsgs)[0] - messages[0].msgParams.metamaskId = parseInt(msgId, 10) - }) - afterEach(function () { - signMessageSpy.restore() + sinon.restore() }) it('calls signMsg in background', async function () { const store = mockStore() - signMessageSpy = sinon.spy(background, 'signMessage') + const signMessage = background.signMessage.callsFake((_, cb) => + cb(null, defaultState), + ) + + actions._setBackgroundConnection(background) + await store.dispatch(actions.signMsg(msgParams)) - assert(signMessageSpy.calledOnce) + assert(signMessage.calledOnce) }) it('errors when signMessage in background throws', async function () { const store = mockStore() + + background.signMessage.callsFake((_, cb) => cb(new Error('error'))) + + actions._setBackgroundConnection(background) + const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', value: undefined }, { type: 'DISPLAY_WARNING', value: 'error' }, { type: 'HIDE_LOADING_INDICATION' }, ] - signMessageSpy = sinon.stub(background, 'signMessage') - signMessageSpy.callsFake((_, callback) => { - callback(new Error('error')) - }) - try { - await store.dispatch(actions.signMsg()) + await store.dispatch(actions.signMsg(msgParams)) assert.fail('Should have thrown error') } catch (_) { - assert.deepEqual(store.getActions(), expectedActions) + assert.deepStrictEqual(store.getActions(), expectedActions) } }) }) describe('#signPersonalMsg', function () { - let signPersonalMessageSpy, metamaskMsgs, msgId, personalMessages - const msgParams = { from: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc', data: '0x879a053d4800c6354e76c7985a865d2922c82fb5b3f4577b2fe08b998954f2e0', } - beforeEach(function () { - metamaskController.newUnsignedPersonalMessage(msgParams, noop) - metamaskMsgs = metamaskController.personalMessageManager.getUnapprovedMsgs() - personalMessages = metamaskController.personalMessageManager.messages - msgId = Object.keys(metamaskMsgs)[0] - personalMessages[0].msgParams.metamaskId = parseInt(msgId, 10) - }) - afterEach(function () { - signPersonalMessageSpy.restore() + sinon.restore() }) it('calls signPersonalMessage', async function () { const store = mockStore() - signPersonalMessageSpy = sinon.spy(background, 'signPersonalMessage') + const signPersonalMessage = background.signPersonalMessage.callsFake( + (_, cb) => cb(null, defaultState), + ) + + actions._setBackgroundConnection(background) await store.dispatch(actions.signPersonalMsg(msgParams)) - assert(signPersonalMessageSpy.calledOnce) + assert(signPersonalMessage.calledOnce) }) it('throws if signPersonalMessage throws', async function () { const store = mockStore() + + background.signPersonalMessage.callsFake((_, cb) => { + cb(new Error('error')) + }) + + actions._setBackgroundConnection(background) + const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', value: undefined }, { type: 'DISPLAY_WARNING', value: 'error' }, { type: 'HIDE_LOADING_INDICATION' }, ] - signPersonalMessageSpy = sinon.stub(background, 'signPersonalMessage') - signPersonalMessageSpy.callsFake((_, callback) => { - callback(new Error('error')) - }) - try { await store.dispatch(actions.signPersonalMsg(msgParams)) assert.fail('Should have thrown error') @@ -698,8 +759,6 @@ describe('Actions', function () { }) describe('#signTypedMsg', function () { - let signTypedMsgSpy, messages, typedMessages, msgId - const msgParamsV3 = { from: '0x0DCD5D886577d5081B0c52e242Ef29E70Be3E7bc', data: JSON.stringify({ @@ -740,33 +799,30 @@ describe('Actions', function () { }), } - beforeEach(function () { - metamaskController.newUnsignedTypedMessage(msgParamsV3, null, 'V3') - messages = metamaskController.typedMessageManager.getUnapprovedMsgs() - typedMessages = metamaskController.typedMessageManager.messages - msgId = Object.keys(messages)[0] - typedMessages[0].msgParams.metamaskId = parseInt(msgId, 10) - }) - afterEach(function () { - signTypedMsgSpy.restore() + sinon.restore() }) it('calls signTypedMsg in background with no error', async function () { - signTypedMsgSpy = sinon - .stub(background, 'signTypedMessage') - .callsArgWith(1, null, defaultState) const store = mockStore() + const signTypedMsg = background.signTypedMessage.callsFake((_, cb) => + cb(null, defaultState), + ) + + actions._setBackgroundConnection(background) + await store.dispatch(actions.signTypedMsg(msgParamsV3)) - assert(signTypedMsgSpy.calledOnce) + assert(signTypedMsg.calledOnce) }) it('returns expected actions with error', async function () { - signTypedMsgSpy = sinon - .stub(background, 'signTypedMessage') - .callsArgWith(1, new Error('error')) const store = mockStore() + + background.signTypedMessage.callsFake((_, cb) => cb(new Error('error'))) + + actions._setBackgroundConnection(background) + const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', value: undefined }, { type: 'DISPLAY_WARNING', value: 'error' }, @@ -777,27 +833,27 @@ describe('Actions', function () { await store.dispatch(actions.signTypedMsg()) assert.fail('Should have thrown error') } catch (_) { - assert.deepEqual(store.getActions(), expectedActions) + assert.deepStrictEqual(store.getActions(), expectedActions) } }) }) describe('#signTx', function () { - let sendTransactionSpy + let sendTransaction beforeEach(function () { - sendTransactionSpy = sinon.stub(global.ethQuery, 'sendTransaction') + sendTransaction = sinon.stub(global.ethQuery, 'sendTransaction') }) afterEach(function () { - sendTransactionSpy.restore() + sendTransaction.restore() }) it('calls sendTransaction in global ethQuery', function () { const store = mockStore() store.dispatch(actions.signTx()) - assert(sendTransactionSpy.calledOnce) + assert(sendTransaction.calledOnce) }) it('errors in when sendTransaction throws', function () { @@ -806,12 +862,12 @@ describe('Actions', function () { { type: 'DISPLAY_WARNING', value: 'error' }, { type: 'SHOW_CONF_TX_PAGE', id: undefined }, ] - sendTransactionSpy.callsFake((_, callback) => { + sendTransaction.callsFake((_, callback) => { callback(new Error('error')) }) store.dispatch(actions.signTx()) - assert.deepEqual(store.getActions(), expectedActions) + assert.deepStrictEqual(store.getActions(), expectedActions) }) }) @@ -840,7 +896,7 @@ describe('Actions', function () { await store.dispatch(actions.updateGasData(mockData)) assert.fail('Should have thrown error') } catch (error) { - assert.deepEqual(store.getActions(), expectedActions) + assert.deepStrictEqual(store.getActions(), expectedActions) } }) @@ -867,7 +923,7 @@ describe('Actions', function () { ] await store.dispatch(actions.updateGasData(mockData)) - assert.deepEqual(store.getActions(), expectedActions) + assert.deepStrictEqual(store.getActions(), expectedActions) global.eth.getCode.reset() }) }) @@ -884,8 +940,6 @@ describe('Actions', function () { }) describe('#updateTransaction', function () { - let updateTransactionSpy - const txParams = { from: '0x1', gas: '0x5208', @@ -901,24 +955,32 @@ describe('Actions', function () { txParams, } - beforeEach(async function () { - await metamaskController.txController.txStateManager.addTx(txData) - }) - afterEach(function () { - updateTransactionSpy.restore() + sinon.restore() }) it('updates transaction', async function () { const store = mockStore() - updateTransactionSpy = sinon.spy(background, 'updateTransaction') + const updateTransactionStub = sinon.stub().callsFake((_, cb) => cb()) + + background.getApi.returns({ + updateTransaction: updateTransactionStub, + getState: sinon.stub().callsFake((cb) => + cb(null, { + currentLocale: 'test', + selectedAddress: '0xFirstAddress', + }), + ), + }) + + actions._setBackgroundConnection(background.getApi()) await store.dispatch(actions.updateTransaction(txData)) const resultantActions = store.getActions() - assert.ok(updateTransactionSpy.calledOnce) - assert.deepEqual(resultantActions[1], { + assert(updateTransactionStub.calledOnce) + assert.deepStrictEqual(resultantActions[1], { type: 'UPDATE_TRANSACTION_PARAMS', id: txData.id, value: txParams, @@ -928,72 +990,86 @@ describe('Actions', function () { it('rejects with error message', async function () { const store = mockStore() - updateTransactionSpy = sinon.stub(background, 'updateTransaction') - updateTransactionSpy.callsFake((_, callback) => { - callback(new Error('error')) + background.getApi.returns({ + updateTransaction: (_, callback) => { + callback(new Error('error')) + }, + getState: sinon.stub().callsFake((cb) => + cb(null, { + currentLocale: 'test', + selectedAddress: '0xFirstAddress', + }), + ), }) + actions._setBackgroundConnection(background.getApi()) + try { await store.dispatch(actions.updateTransaction(txData)) assert.fail('Should have thrown error') } catch (error) { - assert.equal(error.message, 'error') + assert.strictEqual(error.message, 'error') } }) }) describe('#lockMetamask', function () { - let backgroundSetLockedSpy - afterEach(function () { - backgroundSetLockedSpy.restore() + sinon.restore() }) it('calls setLocked', async function () { const store = mockStore() - backgroundSetLockedSpy = sinon.spy(background, 'setLocked') + const backgroundSetLocked = background.setLocked.callsFake((cb) => cb()) + + actions._setBackgroundConnection(background) await store.dispatch(actions.lockMetamask()) - assert(backgroundSetLockedSpy.calledOnce) + assert(backgroundSetLocked.calledOnce) }) it('returns display warning error with value when setLocked in background callback errors', async function () { const store = mockStore() + background.setLocked.callsFake((cb) => { + cb(new Error('error')) + }) + + actions._setBackgroundConnection(background) + const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', value: undefined }, { type: 'DISPLAY_WARNING', value: 'error' }, { type: 'HIDE_LOADING_INDICATION' }, { type: 'LOCK_METAMASK' }, ] - backgroundSetLockedSpy = sinon.stub(background, 'setLocked') - backgroundSetLockedSpy.callsFake((callback) => { - callback(new Error('error')) - }) try { await store.dispatch(actions.lockMetamask()) assert.fail('Should have thrown error') } catch (error) { - assert.deepEqual(store.getActions(), expectedActions) + assert.deepStrictEqual(store.getActions(), expectedActions) } }) }) describe('#setSelectedAddress', function () { - let setSelectedAddressSpy - afterEach(function () { - setSelectedAddressSpy.restore() + sinon.restore() }) it('calls setSelectedAddress in background', async function () { - setSelectedAddressSpy = sinon - .stub(background, 'setSelectedAddress') - .callsArgWith(1, null) const store = mockStore() + const setSelectedAddressSpy = sinon.stub().callsFake((_, cb) => cb()) + + background.getApi.returns({ + setSelectedAddress: setSelectedAddressSpy, + }) + + actions._setBackgroundConnection(background.getApi()) + await store.dispatch( actions.setSelectedAddress( '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc', @@ -1003,10 +1079,18 @@ describe('Actions', function () { }) it('errors when setSelectedAddress throws', async function () { - setSelectedAddressSpy = sinon - .stub(background, 'setSelectedAddress') - .callsArgWith(1, new Error('error')) const store = mockStore() + + const setSelectedAddressSpy = sinon + .stub() + .callsFake((_, cb) => cb(new Error('error'))) + + background.getApi.returns({ + setSelectedAddress: setSelectedAddressSpy, + }) + + actions._setBackgroundConnection(background.getApi()) + const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', value: undefined }, { type: 'DISPLAY_WARNING', value: 'error' }, @@ -1014,38 +1098,49 @@ describe('Actions', function () { ] await store.dispatch(actions.setSelectedAddress()) - assert.deepEqual(store.getActions(), expectedActions) + assert.deepStrictEqual(store.getActions(), expectedActions) }) }) describe('#showAccountDetail', function () { - let setSelectedAddressSpy - afterEach(function () { - setSelectedAddressSpy.restore() + sinon.restore() }) it('#showAccountDetail', async function () { - setSelectedAddressSpy = sinon - .stub(background, 'setSelectedAddress') - .callsArgWith(1, null) const store = mockStore({ activeTab: {}, metamask: { alertEnabledness: {}, selectedAddress: '0x123' }, }) + const setSelectedAddressSpy = sinon.stub().callsFake((_, cb) => cb()) + + background.getApi.returns({ + setSelectedAddress: setSelectedAddressSpy, + }) + + actions._setBackgroundConnection(background.getApi()) + await store.dispatch(actions.showAccountDetail()) assert(setSelectedAddressSpy.calledOnce) }) it('displays warning if setSelectedAddress throws', async function () { - setSelectedAddressSpy = sinon - .stub(background, 'setSelectedAddress') - .callsArgWith(1, new Error('error')) const store = mockStore({ activeTab: {}, metamask: { alertEnabledness: {}, selectedAddress: '0x123' }, }) + + const setSelectedAddressSpy = sinon + .stub() + .callsFake((_, cb) => cb(new Error('error'))) + + background.getApi.returns({ + setSelectedAddress: setSelectedAddressSpy, + }) + + actions._setBackgroundConnection(background.getApi()) + const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', value: undefined }, { type: 'DISPLAY_WARNING', value: 'error' }, @@ -1053,30 +1148,78 @@ describe('Actions', function () { ] await store.dispatch(actions.showAccountDetail()) - assert.deepEqual(store.getActions(), expectedActions) + assert.deepStrictEqual(store.getActions(), expectedActions) }) }) describe('#addToken', function () { - let addTokenSpy - afterEach(function () { - addTokenSpy.restore() + sinon.restore() }) it('calls addToken in background', async function () { - addTokenSpy = sinon.stub(background, 'addToken').callsArgWith(4, null) const store = mockStore() + const addTokenStub = sinon + .stub() + .callsFake((_, __, ___, ____, cb) => cb()) + + background.getApi.returns({ + addToken: addTokenStub, + }) + + actions._setBackgroundConnection(background.getApi()) + await store.dispatch(actions.addToken()) - assert(addTokenSpy.calledOnce) + assert(addTokenStub.calledOnce) + }) + + it('expected actions', async function () { + const store = mockStore() + + const tokenDetails = { + address: 'tokenAddress', + symbol: 'token', + decimal: 18, + } + + const addTokenStub = sinon + .stub() + .callsFake((_, __, ___, ____, cb) => cb(null, tokenDetails)) + + background.getApi.returns({ + addToken: addTokenStub, + }) + + actions._setBackgroundConnection(background.getApi()) + + const expectedActions = [ + { type: 'SHOW_LOADING_INDICATION', value: undefined }, + { type: 'HIDE_LOADING_INDICATION' }, + { + type: 'UPDATE_TOKENS', + newTokens: tokenDetails, + }, + ] + + await store.dispatch(actions.addToken()) + + assert.deepStrictEqual(store.getActions(), expectedActions) }) it('errors when addToken in background throws', async function () { - addTokenSpy = sinon - .stub(background, 'addToken') - .callsArgWith(4, new Error('error')) const store = mockStore() + + const addTokenStub = sinon + .stub() + .callsFake((_, __, ___, ____, cb) => cb(new Error('error'))) + + background.getApi.returns({ + addToken: addTokenStub, + }) + + actions._setBackgroundConnection(background.getApi()) + const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', value: undefined }, { type: 'HIDE_LOADING_INDICATION' }, @@ -1093,26 +1236,34 @@ describe('Actions', function () { }) describe('#removeToken', function () { - let removeTokenSpy - afterEach(function () { - removeTokenSpy.restore() + sinon.restore() }) it('calls removeToken in background', async function () { - removeTokenSpy = sinon - .stub(background, 'removeToken') - .callsArgWith(1, null) const store = mockStore() + + const removeTokenStub = sinon.stub().callsFake((_, cb) => cb()) + + background.getApi.returns({ + removeToken: removeTokenStub, + }) + + actions._setBackgroundConnection(background.getApi()) + await store.dispatch(actions.removeToken()) - assert(removeTokenSpy.calledOnce) + assert(removeTokenStub.calledOnce) }) it('errors when removeToken in background fails', async function () { - removeTokenSpy = sinon - .stub(background, 'removeToken') - .callsArgWith(1, new Error('error')) const store = mockStore() + + background.getApi.returns({ + removeToken: sinon.stub().callsFake((_, cb) => cb(new Error('error'))), + }) + + actions._setBackgroundConnection(background.getApi()) + const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', value: undefined }, { type: 'HIDE_LOADING_INDICATION' }, @@ -1123,149 +1274,190 @@ describe('Actions', function () { await store.dispatch(actions.removeToken()) assert.fail('Should have thrown error') } catch (_) { - assert.deepEqual(store.getActions(), expectedActions) + assert.deepStrictEqual(store.getActions(), expectedActions) } }) }) describe('#setProviderType', function () { - let setProviderTypeSpy - let store - - beforeEach(function () { - store = mockStore({ metamask: { provider: {} } }) - }) - afterEach(function () { - setProviderTypeSpy.restore() + sinon.restore() }) it('calls setProviderType', async function () { - setProviderTypeSpy = sinon - .stub(background, 'setProviderType') - .callsArgWith(1, null) + const store = mockStore() + + const setProviderTypeStub = sinon.stub().callsFake((_, cb) => cb()) + + background.getApi.returns({ + setProviderType: setProviderTypeStub, + }) + + actions._setBackgroundConnection(background.getApi()) + await store.dispatch(actions.setProviderType()) - assert(setProviderTypeSpy.calledOnce) + assert(setProviderTypeStub.calledOnce) }) it('displays warning when setProviderType throws', async function () { - setProviderTypeSpy = sinon - .stub(background, 'setProviderType') - .callsArgWith(1, new Error('error')) + const store = mockStore() + + background.getApi.returns({ + setProviderType: sinon + .stub() + .callsFake((_, cb) => cb(new Error('error'))), + }) + + actions._setBackgroundConnection(background.getApi()) + const expectedActions = [ { type: 'DISPLAY_WARNING', value: 'Had a problem changing networks!' }, ] await store.dispatch(actions.setProviderType()) - assert(setProviderTypeSpy.calledOnce) - assert.deepEqual(store.getActions(), expectedActions) + assert.deepStrictEqual(store.getActions(), expectedActions) }) }) describe('#setRpcTarget', function () { - let setRpcTargetSpy - afterEach(function () { - setRpcTargetSpy.restore() + sinon.restore() }) it('calls setRpcTarget', async function () { - setRpcTargetSpy = sinon - .stub(background, 'setCustomRpc') - .callsArgWith(4, null) const store = mockStore() + + background.setCustomRpc.callsFake((_, __, ___, ____, cb) => cb()) + + actions._setBackgroundConnection(background) + await store.dispatch(actions.setRpcTarget('http://localhost:8545')) - assert(setRpcTargetSpy.calledOnce) + assert(background.setCustomRpc.calledOnce) }) it('displays warning when setRpcTarget throws', async function () { - setRpcTargetSpy = sinon - .stub(background, 'setCustomRpc') - .callsArgWith(4, new Error('error')) const store = mockStore() + + background.setCustomRpc.callsFake((_, __, ___, ____, cb) => + cb(new Error('error')), + ) + + actions._setBackgroundConnection(background) + const expectedActions = [ { type: 'DISPLAY_WARNING', value: 'Had a problem changing networks!' }, ] await store.dispatch(actions.setRpcTarget()) - assert.deepEqual(store.getActions(), expectedActions) + assert.deepStrictEqual(store.getActions(), expectedActions) }) }) describe('#addToAddressBook', function () { it('calls setAddressBook', async function () { - const addToAddressBookSpy = sinon - .stub(background, 'setAddressBook') - .callsArgWith(4, null, true) const store = mockStore() + + const setAddressBookStub = sinon + .stub() + .callsFake((_, __, ___, ____, cb) => cb()) + + background.getApi.returns({ + setAddressBook: setAddressBookStub, + }) + + actions._setBackgroundConnection(background.getApi()) + await store.dispatch(actions.addToAddressBook('test')) - assert(addToAddressBookSpy.calledOnce) - addToAddressBookSpy.restore() + assert(setAddressBookStub.calledOnce) + sinon.restore() }) }) describe('#exportAccount', function () { - let verifyPasswordSpy, exportAccountSpy - afterEach(function () { - verifyPasswordSpy.restore() - exportAccountSpy.restore() + sinon.restore() }) it('returns expected actions for successful action', async function () { const store = mockStore() + + const testPrivKey = 'a-test-priv-key' + + const verifyPasswordStub = sinon.stub().callsFake((_, cb) => cb()) + + const exportAccountStub = sinon + .stub() + .callsFake((_, cb) => cb(null, testPrivKey)) + + background.getApi.returns({ + verifyPassword: verifyPasswordStub, + exportAccount: exportAccountStub, + }) + + actions._setBackgroundConnection(background.getApi()) + const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', value: undefined }, { type: 'HIDE_LOADING_INDICATION' }, { type: 'SHOW_PRIVATE_KEY', - value: - '7ec73b91bb20f209a7ff2d32f542c3420b4fccf14abcc7840d2eff0ebcb18505', + value: testPrivKey, }, ] - verifyPasswordSpy = sinon.spy(background, 'verifyPassword') - exportAccountSpy = sinon.spy(background, 'exportAccount') - await store.dispatch( - actions.exportAccount( - password, - '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc', - ), + actions.exportAccount('a-test-password', '0xAddress'), ) - assert(verifyPasswordSpy.calledOnce) - assert(exportAccountSpy.calledOnce) - assert.deepEqual(store.getActions(), expectedActions) + assert(verifyPasswordStub.calledOnce) + assert(exportAccountStub.calledOnce) + assert.deepStrictEqual(store.getActions(), expectedActions) }) it('returns action errors when first func callback errors', async function () { const store = mockStore() + + const verifyPasswordStub = sinon + .stub() + .callsFake((_, cb) => cb(new Error('error'))) + + background.getApi.returns({ + verifyPassword: verifyPasswordStub, + }) + + actions._setBackgroundConnection(background.getApi()) + const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', value: undefined }, { type: 'HIDE_LOADING_INDICATION' }, { type: 'DISPLAY_WARNING', value: 'Incorrect Password.' }, ] - verifyPasswordSpy = sinon.stub(background, 'verifyPassword') - verifyPasswordSpy.callsFake((_, callback) => { - callback(new Error('error')) - }) - try { await store.dispatch( - actions.exportAccount( - password, - '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc', - ), + actions.exportAccount('a-test-password', '0xAddress'), ) assert.fail('Should have thrown error') } catch (_) { - assert.deepEqual(store.getActions(), expectedActions) + assert.deepStrictEqual(store.getActions(), expectedActions) } }) it('returns action errors when second func callback errors', async function () { const store = mockStore() + + const verifyPasswordStub = sinon.stub().callsFake((_, cb) => cb()) + + const exportAccountStub = sinon + .stub() + .callsFake((_, cb) => cb(new Error('error'))) + + background.getApi.returns({ + verifyPassword: verifyPasswordStub, + exportAccount: exportAccountStub, + }) + + actions._setBackgroundConnection(background.getApi()) + const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', value: undefined }, { type: 'HIDE_LOADING_INDICATION' }, @@ -1275,63 +1467,104 @@ describe('Actions', function () { }, ] - exportAccountSpy = sinon.stub(background, 'exportAccount') - exportAccountSpy.callsFake((_, callback) => { - callback(new Error('error')) - }) - try { await store.dispatch( - actions.exportAccount( - password, - '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc', - ), + actions.exportAccount('a-test-password', '0xAddress'), ) assert.fail('Should have thrown error') } catch (_) { - assert.deepEqual(store.getActions(), expectedActions) + assert.deepStrictEqual(store.getActions(), expectedActions) } }) }) describe('#setAccountLabel', function () { + afterEach(function () { + sinon.restore() + }) + it('calls setAccountLabel', async function () { - const setAccountLabelSpy = sinon - .stub(background, 'setAccountLabel') - .callsArgWith(2, null) const store = mockStore() + + const setAccountLabelStub = sinon.stub().callsFake((_, __, cb) => cb()) + + background.getApi.returns({ + setAccountLabel: setAccountLabelStub, + }) + + actions._setBackgroundConnection(background.getApi()) + await store.dispatch( actions.setAccountLabel( '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc', 'test', ), ) - assert(setAccountLabelSpy.calledOnce) + assert(setAccountLabelStub.calledOnce) + }) + + it('returns action errors when func callback errors', async function () { + const store = mockStore() + + background.getApi.returns({ + setAccountLabel: sinon + .stub() + .callsFake((_, __, cb) => cb(new Error('error'))), + }) + + actions._setBackgroundConnection(background.getApi()) + + const expectedActions = [ + { type: 'SHOW_LOADING_INDICATION', value: undefined }, + { type: 'HIDE_LOADING_INDICATION' }, + { type: 'DISPLAY_WARNING', value: 'error' }, + ] + + try { + await store.dispatch( + actions.setAccountLabel( + '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc', + 'test', + ), + ) + assert.fail('Should have thrown error') + } catch (error) { + assert.deepStrictEqual(store.getActions(), expectedActions) + } }) }) describe('#setFeatureFlag', function () { - let setFeatureFlagSpy - afterEach(function () { - setFeatureFlagSpy.restore() + sinon.restore() }) it('calls setFeatureFlag in the background', async function () { - setFeatureFlagSpy = sinon - .stub(background, 'setFeatureFlag') - .callsArgWith(2, null) const store = mockStore() + const setFeatureFlagStub = sinon.stub().callsFake((_, __, cb) => cb()) + + background.getApi.returns({ + setFeatureFlag: setFeatureFlagStub, + }) + + actions._setBackgroundConnection(background.getApi()) + await store.dispatch(actions.setFeatureFlag()) - assert(setFeatureFlagSpy.calledOnce) + assert(setFeatureFlagStub.calledOnce) }) it('errors when setFeatureFlag in background throws', async function () { - setFeatureFlagSpy = sinon - .stub(background, 'setFeatureFlag') - .callsArgWith(2, new Error('error')) const store = mockStore() + + background.getApi.returns({ + setFeatureFlag: sinon + .stub() + .callsFake((_, __, cb) => cb(new Error('error'))), + }) + + actions._setBackgroundConnection(background.getApi()) + const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', value: undefined }, { type: 'HIDE_LOADING_INDICATION' }, @@ -1342,42 +1575,81 @@ describe('Actions', function () { await store.dispatch(actions.setFeatureFlag()) assert.fail('Should have thrown error') } catch (_) { - assert.deepEqual(store.getActions(), expectedActions) + assert.deepStrictEqual(store.getActions(), expectedActions) } }) }) describe('#setCompletedOnboarding', function () { + afterEach(function () { + sinon.restore() + }) + it('completes onboarding', async function () { - const completeOnboardingSpy = sinon.stub(background, 'completeOnboarding') - completeOnboardingSpy.callsFake((cb) => cb()) const store = mockStore() + const completeOnboardingStub = sinon.stub().callsFake((cb) => cb()) + + background.getApi.returns({ + completeOnboarding: completeOnboardingStub, + }) + + actions._setBackgroundConnection(background.getApi()) + await store.dispatch(actions.setCompletedOnboarding()) - assert.equal(completeOnboardingSpy.callCount, 1) - completeOnboardingSpy.restore() + assert(completeOnboardingStub.calledOnce) + }) + + it('errors when setCompletedOnboarding in background throws', async function () { + const store = mockStore() + + background.getApi.returns({ + completeOnboarding: sinon + .stub() + .callsFake((cb) => cb(new Error('error'))), + }) + + actions._setBackgroundConnection(background.getApi()) + + const expectedActions = [ + { type: 'SHOW_LOADING_INDICATION', value: undefined }, + { type: 'DISPLAY_WARNING', value: 'error' }, + { type: 'HIDE_LOADING_INDICATION' }, + ] + + try { + await store.dispatch(actions.setCompletedOnboarding()) + assert.fail('Should have thrown error') + } catch (_) { + assert.deepStrictEqual(store.getActions(), expectedActions) + } }) }) describe('#setUseBlockie', function () { - let setUseBlockieSpy - - beforeEach(function () { - setUseBlockieSpy = sinon.stub(background, 'setUseBlockie') - }) - afterEach(function () { - setUseBlockieSpy.restore() + sinon.restore() }) - it('calls setUseBlockie in background', function () { + it('calls setUseBlockie in background', async function () { const store = mockStore() - store.dispatch(actions.setUseBlockie()) - assert(setUseBlockieSpy.calledOnce) + const setUseBlockStub = background.setUseBlockie.callsFake((_, cb) => + cb(), + ) + + actions._setBackgroundConnection(background) + + await store.dispatch(actions.setUseBlockie()) + assert(setUseBlockStub.calledOnce) }) - it('errors when setUseBlockie in background throws', function () { + it('errors when setUseBlockie in background throws', async function () { const store = mockStore() + + background.setUseBlockie.callsFake((_, cb) => cb(new Error('error'))) + + actions._setBackgroundConnection(background) + const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', value: undefined }, { type: 'HIDE_LOADING_INDICATION' }, @@ -1385,18 +1657,12 @@ describe('Actions', function () { { type: 'SET_USE_BLOCKIE', value: undefined }, ] - setUseBlockieSpy.callsFake((_, callback) => { - callback(new Error('error')) - }) - - store.dispatch(actions.setUseBlockie()) - assert.deepEqual(store.getActions(), expectedActions) + await store.dispatch(actions.setUseBlockie()) + assert.deepStrictEqual(store.getActions(), expectedActions) }) }) describe('#updateCurrentLocale', function () { - let setCurrentLocaleSpy - beforeEach(function () { sinon.stub(window, 'fetch').resolves({ json: async () => enLocale, @@ -1404,84 +1670,118 @@ describe('Actions', function () { }) afterEach(function () { - setCurrentLocaleSpy.restore() - window.fetch.restore() + sinon.restore() }) it('calls expected actions', async function () { const store = mockStore() - setCurrentLocaleSpy = sinon.spy(background, 'setCurrentLocale') + + background.setCurrentLocale.callsFake((_, cb) => cb()) + + actions._setBackgroundConnection(background) const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', value: undefined }, { type: 'SET_CURRENT_LOCALE', - value: { locale: 'en', messages: enLocale }, + value: { locale: 'test', messages: enLocale }, }, { type: 'HIDE_LOADING_INDICATION' }, ] - await store.dispatch(actions.updateCurrentLocale('en')) - assert(setCurrentLocaleSpy.calledOnce) - assert.deepEqual(store.getActions(), expectedActions) + await store.dispatch(actions.updateCurrentLocale('test')) + assert(background.setCurrentLocale.calledOnce) + assert.deepStrictEqual(store.getActions(), expectedActions) }) it('errors when setCurrentLocale throws', async function () { const store = mockStore() + + background.setCurrentLocale.callsFake((_, cb) => cb(new Error('error'))) + + actions._setBackgroundConnection(background) + const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', value: undefined }, { type: 'DISPLAY_WARNING', value: 'error' }, { type: 'HIDE_LOADING_INDICATION' }, ] - setCurrentLocaleSpy = sinon.stub(background, 'setCurrentLocale') - setCurrentLocaleSpy.callsFake((_, callback) => { - callback(new Error('error')) - }) try { - await store.dispatch(actions.updateCurrentLocale('en')) + await store.dispatch(actions.updateCurrentLocale('test')) assert.fail('Should have thrown error') } catch (_) { - assert.deepEqual(store.getActions(), expectedActions) + assert.deepStrictEqual(store.getActions(), expectedActions) } }) }) describe('#markPasswordForgotten', function () { + afterEach(function () { + sinon.restore() + }) + it('calls markPasswordForgotten', async function () { const store = mockStore() - const markPasswordForgottenSpy = sinon - .stub(background, 'markPasswordForgotten') - .callsArg(0) + + background.markPasswordForgotten.callsFake((cb) => cb()) + + actions._setBackgroundConnection(background) await store.dispatch(actions.markPasswordForgotten()) const resultantActions = store.getActions() - assert.deepEqual(resultantActions[1], { + assert.deepStrictEqual(resultantActions[1], { type: 'FORGOT_PASSWORD', value: true, }) - assert.ok(markPasswordForgottenSpy.calledOnce) - markPasswordForgottenSpy.restore() + assert(background.markPasswordForgotten.calledOnce) + }) + + it('errors when markPasswordForgotten throws', async function () { + const store = mockStore() + + background.markPasswordForgotten.callsFake((cb) => cb(new Error('error'))) + + actions._setBackgroundConnection(background) + + const expectedActions = [ + { type: 'HIDE_LOADING_INDICATION' }, + { type: 'FORGOT_PASSWORD', value: true }, + { + type: 'UPDATE_METAMASK_STATE', + value: { + currentLocale: 'test', + selectedAddress: '0xFirstAddress', + }, + }, + ] + + try { + await store.dispatch(actions.markPasswordForgotten('test')) + assert.fail('Should have thrown error') + } catch (_) { + assert.deepStrictEqual(store.getActions(), expectedActions) + } }) }) describe('#unMarkPasswordForgotten', function () { it('calls unMarkPasswordForgotten', async function () { const store = mockStore() - const unMarkPasswordForgottenSpy = sinon - .stub(background, 'unMarkPasswordForgotten') - .callsArg(0) + + background.unMarkPasswordForgotten.callsFake((cb) => cb()) + + actions._setBackgroundConnection(background) await store.dispatch(actions.unMarkPasswordForgotten()) const resultantActions = store.getActions() - assert.deepEqual(resultantActions[0], { + assert.deepStrictEqual(resultantActions[0], { type: 'FORGOT_PASSWORD', value: false, }) - assert.ok(unMarkPasswordForgottenSpy.calledOnce) - unMarkPasswordForgottenSpy.restore() + assert(background.unMarkPasswordForgotten.calledOnce) }) }) }) From f9b5b7ee37a395b260faf7dd7136683e51398a75 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Tue, 2 Feb 2021 11:22:52 -0330 Subject: [PATCH 20/48] Update `ko` localized messages (#10266) * Update `ko` localized messages These translations were provided by Lionbridge. * Update `lockoutTimeTooGreat` message * Update statements with bold 'Never' The sentences did not make sense previously. They have been updated to be grammatically correct and to emphasize the negation. * Apply suggested change to 'swapNewQuoteIn' --- app/_locales/ko/messages.json | 1445 ++++++++++++++++++++++++++------- 1 file changed, 1147 insertions(+), 298 deletions(-) diff --git a/app/_locales/ko/messages.json b/app/_locales/ko/messages.json index 40666c671..08dc33108 100644 --- a/app/_locales/ko/messages.json +++ b/app/_locales/ko/messages.json @@ -3,10 +3,18 @@ "message": "정보" }, "aboutSettingsDescription": { - "message": "버전, 지원 센터, 그리고 연락처 정보" + "message": "버전, 지원 센터, 연락처" }, "acceleratingATransaction": { - "message": "* 더 높은 가스 요금을 사용하여 트랜잭션을 가속화하면 네트워크에 의해 더 빨리 처리될 가능성이 증가하지만 항상 빠른 처리가 보장되는 것은 아닙니다." + "message": "* 높은 Gas 가격을 이용한 거래 가속화는 네트워크를 통한 처리 속도 개선 확률을 높이지만, 항상 그렇지는 않습니다." + }, + "acceptTermsOfUse": { + "message": "$1을(를) 읽고 이에 동의합니다.", + "description": "$1 is the `terms` message" + }, + "accessAndSpendNotice": { + "message": "$1은(는) 이 최대 금액까지 액세스 및 지출할 수 있습니다.", + "description": "$1 is the url of the site requesting ability to spend" }, "accessingYourCamera": { "message": "카메라에 접근 중..." @@ -15,7 +23,7 @@ "message": "계정" }, "accountDetails": { - "message": "계정 상세보기" + "message": "계정 세부 정보" }, "accountName": { "message": "계정 이름" @@ -24,31 +32,40 @@ "message": "계정 옵션" }, "accountSelectionRequired": { - "message": "계정을 선택하셔야 합니다!" + "message": "계정을 선택해야 합니다!" + }, + "active": { + "message": "활성" + }, + "activity": { + "message": "활동" }, "activityLog": { "message": "활동 로그" }, + "addAccount": { + "message": "계정 추가" + }, "addAcquiredTokens": { - "message": "메타마스크를 통해 획득한 토큰 추가" + "message": "MetaMask를 이용해 얻은 토큰 추가" }, "addAlias": { - "message": "가명 추가" + "message": "별칭 추가" }, "addNetwork": { "message": "네트워크 추가" }, "addRecipient": { - "message": "수신자 추가" + "message": "수신인 추가" }, "addSuggestedTokens": { - "message": "제안된 토큰 추가" + "message": "추천 토큰 추가" }, "addToAddressBook": { "message": "주소록에 추가" }, "addToAddressBookModalPlaceholder": { - "message": "예. 존 D." + "message": "예: John D." }, "addToken": { "message": "토큰 추가" @@ -63,91 +80,155 @@ "message": "고급 옵션" }, "advancedSettingsDescription": { - "message": "개발자 기능 사용, 상태 로그 다운로드, 계정 재설정, 테스트넷 및 사용자 정의 RPC 설정" + "message": "개발자 기능 액세스, 상태 로그 다운로드, 계정 재설정, 테스트넷 및 맞춤형 RPC 설정" + }, + "affirmAgree": { + "message": "동의함" + }, + "aggregatorFeeCost": { + "message": "애그리게이터 네트워크 요금" + }, + "alertDisableTooltip": { + "message": "\"설정 > 경고\"에서 변경할 수 있습니다." + }, + "alertSettingsUnconnectedAccount": { + "message": "연결되지 않은 계정을 선택하여 웹사이트 탐색" + }, + "alertSettingsUnconnectedAccountDescription": { + "message": "이 경고는 연결된 Web3 사이트를 탐색하고 있지만 현재 선택된 계정이 연결되지 않은 경우 팝업에 표시됩니다." + }, + "alerts": { + "message": "경고" + }, + "alertsSettingsDescription": { + "message": "각 경고 활성화 또는 비활성화" + }, + "allowExternalExtensionTo": { + "message": "이 외부 확장을 통해 다음을 하도록 허용:" + }, + "allowOriginSpendToken": { + "message": "$1에서 $2을(를) 사용하도록 허용하시겠습니까?", + "description": "$1 is the url of the site and $2 is the symbol of the token they are requesting to spend" + }, + "allowThisSiteTo": { + "message": "이 사이트에서 다음을 하도록 허용:" + }, + "allowWithdrawAndSpend": { + "message": "$1에서 다음 금액까지 인출 및 지출하도록 허용:", + "description": "The url of the site that requested permission to 'withdraw and spend'" }, "amount": { - "message": "수량" + "message": "금액" + }, + "amountInEth": { + "message": "$1 ETH", + "description": "Displays an eth amount to the user. $1 is a decimal number" + }, + "amountWithColon": { + "message": "금액:" }, "appDescription": { - "message": "이더리움 브라우저 확장 프로그램", + "message": "브라우저의 이더리움 지갑", "description": "The description of the application" }, "appName": { - "message": "메타마스크", + "message": "MetaMask", "description": "The name of the application" }, + "approvalAndAggregatorTxFeeCost": { + "message": "승인 및 애그리게이터 네트워크 요금" + }, + "approvalTxGasCost": { + "message": "승인 Tx Gas 비용" + }, "approve": { - "message": "수락" + "message": "지출 한도 승인" + }, + "approveSpendLimit": { + "message": "$1 지출 한도 승인", + "description": "The token symbol that is being approved" }, "approved": { - "message": "수락" + "message": "승인됨" }, "asset": { "message": "자산" }, + "assets": { + "message": "자산" + }, "attemptToCancel": { - "message": "취소 하시겠습니까?" + "message": "취소하시겠습니까?" }, "attemptToCancelDescription": { - "message": "이 취소 시도가 기존 트랜잭션의 취소를 보장하지 않습니다. 취소 시도가 성공하면 위 거래 수수료가 부과됩니다." + "message": "이 시도를 제출한다고 해서 원래 거래가 반드시 취소되지는 않습니다. 취소 시도가 성공하면 위의 거래 수수료가 부과됩니다." }, "attemptingConnect": { - "message": "블록체인에 접속을 시도하는 중입니다." + "message": "블록체인 연결 시도 중입니다." }, "attributions": { "message": "속성" }, + "authorizedPermissions": { + "message": "다음 권한을 승인받았습니다." + }, "autoLockTimeLimit": { - "message": "자동 로그아웃 타이머 (분)" + "message": "자동 잠금 타이머(분)" }, "autoLockTimeLimitDescription": { - "message": "MetaMask가 자동으로 로그아웃되기 전 유휴 시간을 분 단위로 설정하세요" + "message": "MetaMask가 잠길 때까지 걸리는 시간을 분 단위로 설정합니다." }, "average": { "message": "평균" }, "back": { - "message": "돌아가기" + "message": "뒤로" }, "backToAll": { - "message": "전체로 돌아가기" + "message": "전체 목록으로 돌아가기" }, "backupApprovalInfo": { - "message": "이 비밀 코드는 기기를 분실해서 월렛을 복구해야 하거나, 비밀번호를 잊어버리거나, MetaMask를 재설치해야 하거나, 다른 기기에서 월렛에 접속하고 싶은 경우에 필요합니다." + "message": "이 비밀 코드는 장치를 분실하여 지갑을 복구하거나, 암호를 잊거나, MetaMask를 다시 설치해야 하거나, 다른 장치에서 지갑에 액세스해야 할 때 필요합니다." }, "backupApprovalNotice": { - "message": "비밀 복구 코드를 백업하여 월렛과 자금을 안전하게 유지하세요." + "message": "비밀 복구 코드를 백업하여 지갑과 자금을 안전하게 보호하세요." }, "backupNow": { - "message": "지금 백업하기" + "message": "지금 백업" }, "balance": { "message": "잔액" }, "balanceOutdated": { - "message": "잔액이 오래된 정보일 수 있습니다" + "message": "최신 잔액이 아닐 수도 있습니다." + }, + "basic": { + "message": "기본" }, "blockExplorerUrl": { - "message": "익스플로러 차단" + "message": "블록 탐색기" }, "blockExplorerView": { - "message": "$1에 계정을 보세요", + "message": "$1의 계정 보기", "description": "$1 replaced by URL for custom block explorer" }, "blockiesIdenticon": { "message": "Blockies 아이덴티콘 사용" }, "browserNotSupported": { - "message": "브라우저를 지원하지 않습니다..." + "message": "지원되지 않는 브라우저입니다..." }, "builtInCalifornia": { - "message": "메타마스크는 캘리포니아에서 디자인되고 만들어졌습니다." + "message": "MetaMask는 캘리포니아에서 설계 및 제작됩니다." + }, + "buy": { + "message": "구매" }, "buyWithWyre": { "message": "Wyre로 ETH 구매" }, "buyWithWyreDescription": { - "message": "Wyre는 신용 카드를 사용하여 ETH을 바로 MetaMask 계정에 입금할 수 있게 해줍니다." + "message": "Wyre를 사용하면 체크카드를 이용해 ETH를 MetaMask 계정에 바로 예치할 수 있습니다." }, "bytes": { "message": "바이트" @@ -156,7 +237,7 @@ "message": "취소" }, "cancellationGasFee": { - "message": "취소 가스 수수료" + "message": "취소 Gas 수수료" }, "cancelled": { "message": "취소됨" @@ -165,25 +246,25 @@ "message": "체인 ID" }, "chromeRequiredForHardwareWallets": { - "message": "하드웨어 지갑을 연결하기 위해서는 구글 크롬에서 메타마스크를 사용하셔야 합니다." + "message": "하드웨어 지갑에 연결하려면 Google Chrome에서 MetaMask를 사용해야 합니다." }, "clickToRevealSeed": { - "message": "비밀 단어를 보기 위해 여기를 클릭하세요." + "message": "암호를 표시하려면 여기를 클릭하세요" }, "close": { "message": "닫기" }, "confirm": { - "message": "승인" + "message": "확인" }, "confirmPassword": { - "message": "비밀번호 확인" + "message": "암호 확인" }, "confirmSecretBackupPhrase": { "message": "비밀 백업 구문 확인" }, "confirmed": { - "message": "승인됨" + "message": "확인됨" }, "congratulations": { "message": "축하합니다." @@ -191,92 +272,186 @@ "connect": { "message": "연결" }, + "connectAccountOrCreate": { + "message": "계정을 연결하거나 새 계정 만들기" + }, "connectHardwareWallet": { "message": "하드웨어 지갑 연결" }, + "connectManually": { + "message": "현재 사이트에 수동으로 연결" + }, + "connectTo": { + "message": "$1에 연결", + "description": "$1 is the name/origin of a web3 site/application that the user can connect to metamask" + }, + "connectToAll": { + "message": "모든 $1에 연결", + "description": "$1 will be replaced by the translation of connectToAllAccounts" + }, + "connectToAllAccounts": { + "message": "계정", + "description": "will replace $1 in connectToAll, completing the sentence 'connect to all of your accounts', will be text that shows list of accounts on hover" + }, + "connectToMultiple": { + "message": "$1에 연결", + "description": "$1 will be replaced by the translation of connectToMultipleNumberOfAccounts" + }, + "connectToMultipleNumberOfAccounts": { + "message": "$1 계정", + "description": "$1 is the number of accounts to which the web3 site/application is asking to connect; this will substitute $1 in connectToMultiple" + }, + "connectWithMetaMask": { + "message": "MetaMask에 연결" + }, + "connectedAccountsDescriptionPlural": { + "message": "이 사이트에 계정 $1개가 연결되어 있습니다.", + "description": "$1 is the number of accounts" + }, + "connectedAccountsDescriptionSingular": { + "message": "이 사이트에 계정 1개가 연결되어 있습니다." + }, + "connectedAccountsEmptyDescription": { + "message": "MetaMask가 이 사이트에 연결되어 있지 않습니다. web3 사이트를 연결하려면 사이트에서 연결 버튼을 찾으세요." + }, + "connectedSites": { + "message": "연결된 사이트" + }, + "connectedSitesDescription": { + "message": "$1이(가) 이 사이트에 연결되어 있습니다. 귀하의 계정 주소를 볼 수 있습니다.", + "description": "$1 is the account name" + }, + "connectedSitesEmptyDescription": { + "message": "$1이(가) 어떤 사이트에도 연결되어 있지 않습니다.", + "description": "$1 is the account name" + }, + "connecting": { + "message": "연결 중..." + }, "connectingTo": { - "message": "$1에 연결" + "message": "$1에 연결 중" }, "connectingToGoerli": { - "message": "Goerli 테스트 네트워크에 연결하는 중" + "message": "Goerli 테스트 네트워크에 연결 중" }, "connectingToKovan": { - "message": "Kovan 테스트넷 접속 중" + "message": "Kovan 테스트 네트워크에 연결 중" }, "connectingToMainnet": { - "message": "이더리움 메인넷 접속 중" + "message": "이더리움 메인넷에 연결 중" }, "connectingToRinkeby": { - "message": "Rinkeby 테스트넷 접속 중" + "message": "Rinkeby 테스트 네트워크에 연결 중" }, "connectingToRopsten": { - "message": "Ropsten 테스트넷 접속 중" + "message": "Ropsten 테스트 네트워크에 연결 중" + }, + "contactUs": { + "message": "당사에 문의하세요" + }, + "contacts": { + "message": "연락처" + }, + "contactsSettingsDescription": { + "message": "연락처 추가, 편집, 제거 및 관리" }, "continueToWyre": { - "message": "Wyre로 계속 진행" + "message": "Wyre로 넘어가기" }, "contractDeployment": { - "message": "컨트랙트 배포" + "message": "계약 배포" }, "contractInteraction": { "message": "계약 상호 작용" }, "copiedExclamation": { - "message": "복사됨!" + "message": "복사 완료!" }, "copiedTransactionId": { - "message": "트랜잭션 아이디 복사됨" + "message": "거래 ID 복사됨" }, "copyAddress": { - "message": "클립보드로 주소 복사" + "message": "주소를 클립보드에 복사" }, "copyPrivateKey": { - "message": "비밀 키입니다 (클릭하여 복사)" + "message": "귀하의 비공개 키입니다(클릭하여 복사)" }, "copyToClipboard": { - "message": "클립보드로 복사" + "message": "클립보드에 복사" }, "copyTransactionId": { - "message": "트랜잭션 아이디 복사" + "message": "거래 ID 복사" }, "create": { "message": "생성" }, "createAWallet": { - "message": "지갑 생성하기" + "message": "지갑 생성" }, "createAccount": { "message": "계정 생성" }, "createPassword": { - "message": "비밀번호 생성" + "message": "암호 생성" }, "currencyConversion": { "message": "통화 변환" }, + "currentAccountNotConnected": { + "message": "현재 계정이 연결되어 있지 있습니다." + }, + "currentExtension": { + "message": "현재 확장 페이지" + }, "currentLanguage": { "message": "현재 언어" }, "customGas": { - "message": "가스 설정" + "message": "Gas 맞춤화" }, "customGasSubTitle": { - "message": "수수료를 높히면 처리 시간이 단축될 수 있지만, 그것이 보장되진 않습니다." + "message": "요금을 올리면 처리 시간이 줄어들 수 있지만 반드시 그렇지는 않습니다." }, "customRPC": { - "message": "사용자 정의 RPC" + "message": "맞춤형 RPC" + }, + "customSpendLimit": { + "message": "맞춤형 지출 한도" }, "customToken": { - "message": "사용자 정의 토큰" + "message": "맞춤형 토큰" + }, + "dataBackupFoundInfo": { + "message": "계정 데이터 일부가 MetaMask 이전 설치 도중에 백업되었습니다. 여기에는 설정, 연락처, 토큰이 포함될 수 있습니다. 지금 이 데이터를 복구하시겠습니까?" }, "decimal": { - "message": "소수 자릿수" + "message": "정밀도 소수 자릿수" }, "decimalsMustZerotoTen": { - "message": "소수점은 0 이상이고 36 이하여야 합니다." + "message": "소수 자릿수는 0 이상, 36 이하여야 합니다." + }, + "decrypt": { + "message": "암호 해독" + }, + "decryptCopy": { + "message": "암호 해독된 메시지 복사" + }, + "decryptInlineError": { + "message": "다음 오류 때문에 이 메시지를 해독할 수 없습니다. $1", + "description": "$1 is error message" + }, + "decryptMessageNotice": { + "message": "$1에서 귀하의 작업 완수를 위해 이 메시지를 읽고자 합니다.", + "description": "$1 is the web3 site name" + }, + "decryptMetamask": { + "message": "메시지 암호 해독" + }, + "decryptRequest": { + "message": "요청 암호 해독" }, "defaultNetwork": { - "message": "이더리움 트랜잭션의 기본 네트워크는 메인넷입니다." + "message": "Ether 거래의 기존 네트워크는 메인 넷입니다." }, "delete": { "message": "삭제" @@ -285,34 +460,55 @@ "message": "계정 삭제" }, "deleteNetwork": { - "message": "네트워크를 삭제할까요?" + "message": "네트워크를 삭제합니까?" }, "deleteNetworkDescription": { - "message": "정말로 이 네트워크를 삭제하시겠습니까?" + "message": "이 네트워크를 삭제하시겠습니까?" }, "depositEther": { - "message": "이더리움 입금하기" + "message": "Ether 예치" }, "details": { - "message": "세부사항" + "message": "세부 정보" }, "directDepositEther": { - "message": "이더 즉시 입금" + "message": "Ether 직접 예치" }, "directDepositEtherExplainer": { - "message": "약간의 이더를 이미 보유하고 있다면, 새로 만든 지갑에 직접 입금하여 이더를 보유할 수 있습니다." + "message": "Ether가 어느 정도 있다면 Ether를 새 지갑에 넣는 가장 빠른 방법은 직접 예치입니다." + }, + "disconnect": { + "message": "연결 해제" + }, + "disconnectAllAccounts": { + "message": "모든 계정 연결 해제" + }, + "disconnectAllAccountsConfirmationDescription": { + "message": "이 네트워크의 연결을 해제하시겠습니까? 사이트 기능을 이용하지 못하게 될 수도 있습니다." + }, + "disconnectPrompt": { + "message": "$1 연결 해제" + }, + "disconnectThisAccount": { + "message": "이 계정 연결 해제" + }, + "dismiss": { + "message": "해지" }, "done": { "message": "완료" }, "dontHaveAHardwareWallet": { - "message": "하드웨어 지갑이 없나요?" + "message": "하드웨어 지갑이 없으신가요?" + }, + "dontShowThisAgain": { + "message": "이 메시지를 다시 표시하지 않음" }, "downloadGoogleChrome": { - "message": "구글 크롬 다운로드" + "message": "Google Chrome 다운로드" }, "downloadSecretBackup": { - "message": "이 비밀 백업 구문을 다운로드하여 암호화된 외장 하드 드라이브나 저장 매체에 안전하게 보관하세요." + "message": "이 비밀 백업 구문을 다운로드하고 암호화된 외장 하드 드라이브나 저장 매체에 안전하게 보관하세요." }, "downloadStateLogs": { "message": "상태 로그 다운로드" @@ -321,130 +517,227 @@ "message": "중단됨" }, "edit": { - "message": "수정" + "message": "편집" }, "editContact": { - "message": "연락처 수정" + "message": "연락처 편집" + }, + "editPermission": { + "message": "권한 편집" + }, + "encryptionPublicKeyNotice": { + "message": "$1에서 귀하의 공개 암호화 키를 요구합니다. 동의하면 이 사이트에서 암호화된 메시지를 작성하여 귀하에게 전송할 수 있습니다.", + "description": "$1 is the web3 site name" + }, + "encryptionPublicKeyRequest": { + "message": "암호화 공개 키 요구" }, "endOfFlowMessage1": { - "message": "인증을 통과했습니다 - 시드 구문을 안전하게 보관하세요. 그것은 당신의 의무입니다." + "message": "테스트를 통과하셨습니다. 시드 구문을 안전하게 보관할 책임은 귀하에게 있습니다!" }, "endOfFlowMessage10": { "message": "모두 완료" }, "endOfFlowMessage2": { - "message": "안전하게 시드 구문을 보관하는 팁" + "message": "안전한 보관 관련 팁" }, "endOfFlowMessage3": { - "message": "여러 군데에 시드 구문을 백업하세요." + "message": "백업을 여러 장소에 보관하세요." }, "endOfFlowMessage4": { - "message": "누구와도 시드 구문을 공유하지마세요." + "message": "구문을 누구와도 공유하지 마세요." }, "endOfFlowMessage5": { - "message": "피싱에 주의하세요! 메타마스크는 절대 갑작스럽게 당신의 시드 구문을 묻지 않습니다." + "message": "피싱을 조심하세요! MetaMask에서는 절대로 시드 구문을 갑자기 물어보지 않습니다." }, "endOfFlowMessage6": { - "message": "만약 시드 구문을 다시 백업해야한다면, 설정 -> 보안에서 확인할 수 있습니다. " + "message": "시드 구문을 다시 백업해야 한다면 설정 -> 보안에서 시드 구문을 찾을 수 있습니다." }, "endOfFlowMessage7": { - "message": "만약 질문이 있거나 피싱을 목격했다면 support@metamask.io으로 메일을 보내주세요." + "message": "질문이 있거나 피싱으로 의심되는 행위를 목격했다면 support@metamask.io로 이메일을 보내세요." }, "endOfFlowMessage8": { - "message": "메타마스크는 당신의 시드 구문을 복원해줄 수 없습니다. 더 알아보기." + "message": "MetaMask에서는 시드 구문을 복구할 수 없습니다." }, "endOfFlowMessage9": { - "message": "더 알아보기." + "message": "자세한 내용을 알아보세요." + }, + "endpointReturnedDifferentChainId": { + "message": "엔드포인트에서 다른 체인 ID를 반환했습니다. $1", + "description": "$1 is the return value of eth_chainId from an RPC endpoint" }, "ensNotFoundOnCurrentNetwork": { - "message": "현재 네트워크에서 ENS 이름을 찾을 수 없습니다. 주요 이더리움 네트워크로 전환해 보세요." + "message": "현재 네트워크에서 ENS 이름을 찾을 수 없습니다. 이더리움 메인넷으로 전환해 보세요." }, "ensRegistrationError": { - "message": "ENS 이름 등록 오류" + "message": "ENS 이름 등록 중 오류 발생" }, "enterAnAlias": { - "message": "가명을 입력하세요" + "message": "별칭 입력" + }, + "enterMaxSpendLimit": { + "message": "최대 지출 한도 입력" }, "enterPassword": { - "message": "비밀번호를 입력해주세요" + "message": "암호 입력" }, "enterPasswordContinue": { - "message": "계속하기 위해 비밀번호 입력" + "message": "계속하려면 암호 입력" + }, + "errorCode": { + "message": "코드: $1", + "description": "Displayed error code for debugging purposes. $1 is the error code" + }, + "errorDetails": { + "message": "오류 세부 정보", + "description": "Title for collapsible section that displays error details for debugging purposes" + }, + "errorMessage": { + "message": "메시지: $1", + "description": "Displayed error message for debugging purposes. $1 is the error message" + }, + "errorName": { + "message": "코드: $1", + "description": "Displayed error name for debugging purposes. $1 is the error name" + }, + "errorPageMessage": { + "message": "페이지를 새로고침하여 다시 시도하거나 support@metamask.io에 요청하여 도움을 받으세요.", + "description": "Message displayed on generic error page in the fullscreen or notification UI" + }, + "errorPagePopupMessage": { + "message": "팝업을 닫은 후 다시 열어 다시 시도하거나 support@metamask.io에 요청하여 도움을 받으세요.", + "description": "Message displayed on generic error page in the popup UI" + }, + "errorPageTitle": { + "message": "MetaMask에서 오류 발생", + "description": "Title of generic error page" + }, + "errorStack": { + "message": "스택:", + "description": "Title for error stack, which is displayed for debugging purposes" }, "estimatedProcessingTimes": { "message": "예상 처리 시간" }, + "eth_accounts": { + "message": "허용되는 계정의 주소 보기(필수)", + "description": "The description for the `eth_accounts` permission" + }, "ethereumPublicAddress": { "message": "이더리움 공개 주소" }, + "etherscan": { + "message": "Etherscan" + }, "etherscanView": { - "message": "이더스캔에서 계정보기" + "message": "Etherscan에서 계정 보기" }, "expandView": { - "message": "큰 화면으로 보기" + "message": "보기 확장" }, "exportPrivateKey": { - "message": "개인키 내보내기" + "message": "비공개 키 내보내기" + }, + "externalExtension": { + "message": "외부 확장" + }, + "extraApprovalGas": { + "message": "+$1 승인 Gas", + "description": "Expresses an additional gas amount the user will have to pay, on top of some other displayed amount. $1 is a decimal amount of gas" }, "failed": { "message": "실패" }, + "failedToFetchChainId": { + "message": "체인 ID를 가져올 수 없습니다. RPC URL이 올바른가요?" + }, + "failureMessage": { + "message": "문제가 발생했습니다. 작업을 완료할 수 없습니다." + }, "fast": { "message": "빠름" }, + "fastest": { + "message": "가장 빠름" + }, + "feeAssociatedRequest": { + "message": "요금이 이 권한과 연결되어 있습니다." + }, "fiat": { - "message": "FIAT", + "message": "명목", "description": "Exchange type" }, "fileImportFail": { - "message": "파일을 가져올 수 없나요? 이곳을 클릭해주세요!", + "message": "파일 가져오기가 작동하지 않나요? 여기를 클릭하세요!", "description": "Helps user import their account from a JSON file" }, + "forbiddenIpfsGateway": { + "message": "금지된 IPFS 게이트웨이: CID 게이트웨이를 지정하세요." + }, "forgetDevice": { - "message": "장치 연결 해제" + "message": "이 장치 잊기" }, "from": { - "message": "보내는 이" + "message": "발신" + }, + "fromAddress": { + "message": "발신: $1", + "description": "$1 is the address to include in the From label. It is typically shortened first using shortenAddress" + }, + "functionApprove": { + "message": "기능: 승인" }, "functionType": { - "message": "함수 유형" + "message": "기능 유형" }, "gasLimit": { - "message": "가스 한도" + "message": "Gas 한도" }, "gasLimitInfoTooltipContent": { - "message": "가스 한도는 당신이 기꺼이 소비할 수 있는 가스의 최대 수량입니다." + "message": "Gas 한도는 지불할 Gas 단위의 최대 금액입니다." }, "gasLimitTooLow": { - "message": "가스 한도는 최소 21000 이상이어야 합니다." + "message": "Gas 한도는 21000 이상이어야 합니다." + }, + "gasLimitTooLowWithDynamicFee": { + "message": "Gas 한도는 $1 이상이어야 합니다.", + "description": "$1 is the custom gas limit, in decimal." }, "gasPrice": { - "message": "가스 가격 (GWEI)" + "message": "Gas 가격(GWEI)" }, "gasPriceExtremelyLow": { - "message": "가스 가격 매우 낮음" + "message": "Gas 가격이 너무 낮음" }, "gasPriceInfoTooltipContent": { - "message": "가스 가격은 가스 1당 지불할 gwei 단위의 이더 수량을 명시합니다." + "message": "Gas 가격은 각 Gas 단위에 대해 지불할 Ether 금액을 지정합니다." }, "gasUsed": { - "message": "사용된 가스" + "message": "사용한 Gas" + }, + "gdprMessage": { + "message": "이 데이터는 집계되므로 개인정보보호 규정(EU) 2016/679의 목적에 따라 익명으로 관리됩니다. 당사 개인정보 보호 관행과 관련된 자세한 내용은 $1을(를) 참조하세요.", + "description": "$1 refers to the gdprMessagePrivacyPolicy message, the translation of which is meant to be used exclusively in the context of gdprMessage" + }, + "gdprMessagePrivacyPolicy": { + "message": "개인정보 보호정책", + "description": "this translation is intended to be exclusively used as the replacement for the $1 in the gdprMessage translation" }, "general": { "message": "일반" }, "generalSettingsDescription": { - "message": "환전, 기본 통화, 언어, 블로키 아이덴티콘" + "message": "통화 전환, 기본 통화, 언어, blockies 식별" }, "getEther": { - "message": "이더 얻기" + "message": "Ether 얻기" }, "getEtherFromFaucet": { - "message": "파우셋에서 $1에 달하는 이더를 얻으세요.", + "message": "$1용 포시트에서 Ether 얻기", "description": "Displays network name for Ether faucet" }, "getHelp": { - "message": "도움말" + "message": "도움을 받으세요." }, "getStarted": { "message": "시작하기" @@ -452,36 +745,43 @@ "goerli": { "message": "Goerli 테스트 네트워크" }, + "happyToSeeYou": { + "message": "반갑습니다." + }, "hardware": { "message": "하드웨어" }, "hardwareWalletConnected": { - "message": "하드웨어 지갑이 연결됨" + "message": "하드웨어 지갑 연결됨" }, "hardwareWallets": { "message": "하드웨어 지갑 연결" }, "hardwareWalletsMsg": { - "message": "메타마스크에서 사용할 하드웨어 지갑을 선택해주세요" + "message": "MetaMask와 함께 사용할 하드웨어 지갑 선택" }, "havingTroubleConnecting": { - "message": "연결에 문제가 있나요?" + "message": "연결에 문제가 있으신가요?" }, "here": { "message": "여기", "description": "as in -click here- for more information (goes with troubleTokenBalances)" }, "hexData": { - "message": "Hex 데이터" + "message": "16진수 데이터" }, "hide": { "message": "숨기기" }, "hideTokenPrompt": { - "message": "토큰 숨기기?" + "message": "토큰을 숨기시겠습니까?" + }, + "hideTokenSymbol": { + "message": "$1 숨기기", + "description": "$1 is the symbol for a token (e.g. 'DAI')" }, "history": { - "message": "히스토리" + "message": "기록" }, "import": { "message": "가져오기", @@ -491,7 +791,7 @@ "message": "계정 가져오기" }, "importAccountMsg": { - "message": " 가져온 계정은 메타마스크에서 원래 생성된 계정의 시드구문과 연관성이 없습니다. 가져온 계정에 대해 더 배우기 " + "message": " 가져온 계정은 생성한 MetaMask 계정 시드 구문 원본에 연결되지 않습니다. 가져온 계정에 대해 자세히 알아보세요. " }, "importAccountSeedPhrase": { "message": "시드 구문으로 계정 가져오기" @@ -503,84 +803,128 @@ "message": "지갑 가져오기" }, "importYourExisting": { - "message": "12개 단어로 구성된 시드 구문으로 이미 만들어진 지갑을 가져오기" + "message": "12단어 시드 구문을 사용하여 지갑 가져오기" }, "imported": { - "message": "가져온 계정", + "message": "가져옴", "description": "status showing that an account has been fully loaded into the keyring" }, "infoHelp": { "message": "정보 및 도움말" }, "initialTransactionConfirmed": { - "message": "초기 트랜잭션이 네트워크를 통해 확정되었습니다. 확인을 누르면 이전으로 돌아갑니다." + "message": "최초 거래를 네트워크에서 확인했습니다. 확인을 클릭하여 뒤로 돌아가세요." }, "insufficientBalance": { - "message": "잔액 부족." + "message": "잔액이 부족합니다." }, "insufficientFunds": { - "message": "충분하지 않은 자금." + "message": "자금이 부족합니다." }, "insufficientTokens": { - "message": "충분하지 않은 토큰." + "message": "토큰이 부족합니다." }, "invalidAddress": { - "message": "올바르지 않은 주소" + "message": "잘못된 주소" }, "invalidAddressRecipient": { - "message": "수신 주소가 올바르지 않습니다" + "message": "수신인 주소가 올바르지 않음" }, "invalidAddressRecipientNotEthNetwork": { - "message": "ETH 네트워크 아님, 소문자로 설정" + "message": "ETH 네트워크가 아닙니다. 소문자로 설정하세요." }, "invalidBlockExplorerURL": { - "message": "올바르지 않은 Block Explorer URI" + "message": "잘못된 블록 탐색기 URL" + }, + "invalidCustomNetworkAlertContent1": { + "message": "맞춤형 네트워크 '$1의 체인 ID를 다시 입력해야 합니다.", + "description": "$1 is the name/identifier of the network." + }, + "invalidCustomNetworkAlertContent2": { + "message": "악성 또는 결함이 있는 네트워크 공급업체의 공격을 방어하기 위해, 이제 모든 맞춤형 네트워크에 체인 ID를 사용해야 합니다." + }, + "invalidCustomNetworkAlertContent3": { + "message": "설정 > 네트워크로 이동한 후 체인 ID를 입력하세요. $1에서 가장 인기 있는 네트워크의 체인 ID를 찾을 수 있습니다.", + "description": "$1 is a link to https://chainid.network" + }, + "invalidCustomNetworkAlertTitle": { + "message": "잘못된 맞춤형 네트워크" + }, + "invalidHexNumber": { + "message": "잘못된 16진수입니다." + }, + "invalidHexNumberLeadingZeros": { + "message": "잘못된 16진수입니다. 앞에 있는 0을 모두 제거하세요." + }, + "invalidIpfsGateway": { + "message": "잘못된 IPFS 게이트웨이: 값은 올바른 URL이어야 합니다." + }, + "invalidNumber": { + "message": "숫자가 올바르지 않습니다. 십진수나 '0x'로 시작하는 16진수를 입력하세요." + }, + "invalidNumberLeadingZeros": { + "message": "숫자가 올바르지 않습니다. 앞에 있는 0을 모두 제거하세요." }, "invalidRPC": { - "message": "올바르지 않은 RPC URI" + "message": "잘못된 RPC URL" }, "invalidSeedPhrase": { "message": "잘못된 시드 구문" }, + "ipfsGateway": { + "message": "IPFS 게이트웨이" + }, + "ipfsGatewayDescription": { + "message": "ENS 콘텐츠 해결에 사용할 IPFS CID 게이트웨이의 URL을 입력하세요." + }, "jsonFile": { "message": "JSON 파일", "description": "format for importing an account" }, "knownAddressRecipient": { - "message": "알려진 계약 주소." + "message": "알려진 계약 주소입니다." + }, + "knownTokenWarning": { + "message": "이 작업은 피싱에 사용할 수 있는, 지갑에 이미 나열된 토큰을 편집합니다. 이 토큰이 나타내는 내용을 변경해야 할 때만 작업을 승인하세요." }, "kovan": { - "message": "Kovan 테스트넷" + "message": "Kovan 테스트 네트워크" + }, + "lastConnected": { + "message": "마지막 연결" }, "learnMore": { - "message": "더 알아보기." + "message": "자세히 알아보기" }, "ledgerAccountRestriction": { - "message": "새 계정을 추가하려면 최소 마지막 계정을 사용해야 합니다." + "message": "새 계정을 추가하려면 먼저 마지막 계정을 사용해야 합니다." }, "letsGoSetUp": { - "message": "네, 설정해볼게요!" + "message": "설정을 시작하죠!" }, "likeToAddTokens": { - "message": "토큰을 추가하시겠습니까?" + "message": "이 토큰을 추가하시겠습니까?" }, "links": { "message": "링크" }, "loadMore": { - "message": "더 많이 로딩" + "message": "추가 항목 로드" }, "loading": { - "message": "로딩 중..." + "message": "로드 중..." }, "loadingTokens": { - "message": "토큰 로딩 중..." + "message": "토큰 로드 중..." }, "localhost": { - "message": "로컬호스트 8545" + "message": "Localhost 8545" }, "lock": { - "message": "로그아웃" + "message": "잠금" + }, + "lockTimeTooGreat": { + "message": "잠금 시간이 너무 김" }, "mainnet": { "message": "이더리움 메인넷" @@ -592,206 +936,318 @@ "message": "메모" }, "memorizePhrase": { - "message": "이 구문을 기억하세요." + "message": "이 구문을 기억합니다." }, "message": { "message": "메시지" }, + "metaMaskConnectStatusParagraphOne": { + "message": "MetaMask의 계정 연결에 대한 제어 기능이 강화되었습니다." + }, + "metaMaskConnectStatusParagraphThree": { + "message": "클릭하여 연결된 계정을 관리하세요." + }, + "metaMaskConnectStatusParagraphTwo": { + "message": "방문 중인 웹사이트가 현재 선택된 계정에 연결되어 있다면 연결 상태 버튼이 표시됩니다." + }, "metamaskDescription": { - "message": "메타마스크는 이더리움을 위한 안전한 저장소입니다." + "message": "이더리움 및 분산형 웹에 연결합니다." + }, + "metamaskSwapsOfflineDescription": { + "message": "MetaMask Swaps가 점검 중입니다. 나중에 다시 확인하세요." }, "metamaskVersion": { - "message": "메타마스크 버전" + "message": "MetaMask 버전" + }, + "metametricsCommitmentsAllowOptOut": { + "message": "언제든 설정을 통해 옵트아웃할 수 있습니다." + }, + "metametricsCommitmentsBoldNever": { + "message": "절대", + "description": "This string is localized separately from some of the commitments so that we can bold it" + }, + "metametricsCommitmentsIntro": { + "message": "MetaMask에서는.." + }, + "metametricsCommitmentsNeverCollectIP": { + "message": "전체 IP 주소를 $1 수집하지 않습니다.", + "description": "The $1 is the bolded word 'Never', from 'metametricsCommitmentsBoldNever'" + }, + "metametricsCommitmentsNeverCollectKeysEtc": { + "message": "키, 주소, 거래, 잔액, 해시 또는 개인 정보를 $1 수집하지 않습니다.", + "description": "The $1 is the bolded word 'Never', from 'metametricsCommitmentsBoldNever'" + }, + "metametricsCommitmentsNeverSellDataForProfit": { + "message": "수익을 위해 데이터를 $1 판매하지 않습니다.", + "description": "The $1 is the bolded word 'Never', from 'metametricsCommitmentsBoldNever'" + }, + "metametricsCommitmentsSendAnonymizedEvents": { + "message": "익명화된 클릭 및 페이지뷰 이벤트 보내기" + }, + "metametricsHelpImproveMetaMask": { + "message": "MetaMask 개선에 참여" + }, + "metametricsOptInDescription": { + "message": "MetaMask는 사용자의 확장 사용 방식을 더 잘 이해하기 위해 사용 데이터를 수집하려 합니다. 이 데이터는 제품과 이더리움 생태계의 사용 편의성과 사용자 경험을 지속적으로 개선하는 데 사용됩니다." }, "mobileSyncText": { - "message": "본인 여부를 확인하기 위해 비밀번호를 입력해 주세요!" + "message": "암호를 입력하여 본인임을 확인하세요!" }, "mustSelectOne": { - "message": "적어도 하나의 토큰을 선택하세요." + "message": "토큰을 1개 이상 선택해야 합니다." }, "myAccounts": { "message": "내 계정" }, "myWalletAccounts": { - "message": "나의 월렛 계정" + "message": "내 지갑 계정" }, "myWalletAccountsDescription": { - "message": "MetaMask가 생성한 모든 계정이 이 섹션에 자동으로 추가됩니다." + "message": "MetaMask에서 생성한 모든 계정으로 이 섹션에 자동으로 추가됩니다." }, "needEtherInWallet": { - "message": "메타마스크를 통한 dApp을 이용하기 위해서는 지갑에 이더가 있어야 합니다." + "message": "MetaMask를 이용하는 분산형 애플리케이션과 상호작용하려면 지갑에 Ether가 있어야 합니다." }, "needImportFile": { - "message": "가져올 파일을 선택해주세요.", + "message": "가져올 파일을 선택해야 합니다.", "description": "User is important an account and needs to add a file to continue" }, "negativeETH": { - "message": "음수값의 이더를 보낼 수 없습니다." + "message": "음수 ETH 양은 전송할 수 없습니다." }, "networkName": { "message": "네트워크 이름" }, + "networkSettingsChainIdDescription": { + "message": "체인 ID는 거래 서명에 사용합니다. 네트워크에서 반환하는 체인 ID와 일치해야 합니다. 십진수나 '0x'로 시작하는 16진수를 입력할 수 있지만, 표시될 때는 십진수로 표시됩니다." + }, "networkSettingsDescription": { - "message": "사용자 정의 RPC 네트워크 추가 및 수정" + "message": "맞춤형 RPC 네트워크 추가 및 편집" }, "networks": { "message": "네트워크" }, "nevermind": { - "message": "상관 안 함" + "message": "괜찮습니다" }, "newAccount": { "message": "새 계정" }, "newAccountDetectedDialogMessage": { - "message": "새로운 주소가 감지됐습니다! 여기를 클릭해 주수록에 추가하세요." + "message": "새 주소가 발견되었습니다! 여기를 클릭하여 주소록에 추가하세요." }, "newAccountNumberName": { - "message": "새 계정 $1", + "message": "계정 $1", "description": "Default name of next account to be created on create account screen" }, "newContact": { - "message": "새로운 연락처" + "message": "새 연락처" }, "newContract": { - "message": "새 컨트랙트" + "message": "새 계약" }, "newNetwork": { "message": "새 네트워크" }, "newPassword": { - "message": "새 비밀번호 (최소 8자 이상)" + "message": "새 암호(8자 이상)" }, "newToMetaMask": { - "message": "메타마스크를 처음 사용하시나요?" + "message": "MetaMask가 처음이세요?" }, "newTotal": { "message": "새 합계" }, "newTransactionFee": { - "message": "새 트랜잭션 수수료" + "message": "새 거래 수수료" }, "next": { "message": "다음" }, + "nextNonceWarning": { + "message": "임시값이 추천 임시값($1)보다 큼", + "description": "The next nonce according to MetaMask's internal logic" + }, + "noAccountsFound": { + "message": "검색 쿼리에 맞는 계정 없음" + }, "noAddressForName": { - "message": "이 이름에 대해 주소가 설정되어 있지 않습니다." + "message": "이 이름에 설정된 주소가 없습니다." }, "noAlreadyHaveSeed": { - "message": "아니요, 이미 시드 구문을 가지고 있습니다." + "message": "아니요. 이미 시드 구문이 있습니다." }, "noConversionRateAvailable": { - "message": "변환 비율을 찾을 수 없습니다" + "message": "사용 가능한 전환율 없음" + }, + "noThanks": { + "message": "괜찮습니다" }, "noTransactions": { - "message": "트랜잭션이 없습니다" + "message": "거래가 없습니다." }, "noWebcamFound": { - "message": "컴퓨터의 웹캠을 찾을 수 없습니다. 다시 시도해보세요." + "message": "컴퓨터의 웹캠을 찾을 수 없습니다. 다시 시도하세요." }, "noWebcamFoundTitle": { - "message": "웹캠이 없습니다" + "message": "웹캠을 찾을 수 없음" + }, + "nonceField": { + "message": "거래 임시값 맞춤화" + }, + "nonceFieldDescription": { + "message": "이 기능을 켜면 확인 화면에서 임시값(거래 번호)을 변경할 수 있습니다. 이것은 고급 기능으로, 주의해서 사용해야 합니다." + }, + "nonceFieldHeading": { + "message": "맞춤 임시값" + }, + "notCurrentAccount": { + "message": "이(가) 올바른 계정인가요? 지갑에서 현재 선택된 계정과 다릅니다." }, "notEnoughGas": { - "message": "가스가 충분하지 않습니다" + "message": "Gas 부족" }, "ofTextNofM": { - "message": "~의" + "message": "/" }, "off": { "message": "끄기" }, + "offlineForMaintenance": { + "message": "점검을 위해 오프라인임" + }, "ok": { "message": "확인" }, "on": { - "message": "사용" + "message": "켜기" + }, + "onboardingReturnNotice": { + "message": "\"$1\"에서 이 탭을 닫고 $2(으)로 돌아갑니다.", + "description": "Return the user to the site that initiated onboarding" + }, + "onlyAddTrustedNetworks": { + "message": "악성 이더리움 네트워크 공급업체는 블록체인 상태를 거짓으로 보고하고 네트워크 활동을 기록할 수 있습니다. 신뢰하는 맞춤형 네트워크만 추가하세요." + }, + "onlyAvailableOnMainnet": { + "message": "메인넷에서만 사용 가능" + }, + "onlyConnectTrust": { + "message": "신뢰하는 사이트에만 연결하세요." }, "optionalBlockExplorerUrl": { - "message": "익스플로러 URL 차단 (선택 사항)" + "message": "블록 탐색기 URL(선택 사항)" }, "optionalCurrencySymbol": { - "message": "Symbol (선택)" + "message": "통화 기호(선택 사항)" }, "orderOneHere": { - "message": "Trezor 혹은 Ledger를 구입하고 자금을 콜드 스토리지에 저장합니다" + "message": "Trezor나 Ledger를 주문하고 자금을 냉동 창고에 보관하세요." + }, + "origin": { + "message": "원본" }, "parameters": { "message": "매개변수" }, "participateInMetaMetrics": { - "message": "MetaMetrics 참여" + "message": "MetaMetrics에 참여" }, "participateInMetaMetricsDescription": { - "message": "메타마스크를 더 좋게 만들기 위해 MetaMetrics에 참여하세요." + "message": "MetaMetrics에 참여하여 MetaMask 개선에 도움을 주세요." }, "password": { - "message": "비밀번호" + "message": "암호" }, "passwordNotLongEnough": { - "message": "비밀번호가 충분히 길지 않습니다" + "message": "암호가 짧습니다." }, "passwordsDontMatch": { - "message": "비밀번호가 맞지 않습니다" + "message": "암호가 일치하지 않습니다." }, "pastePrivateKey": { - "message": "개인키를 입력해주세요:", + "message": "여기에 비공개 키 문자열을 붙여넣으세요.", "description": "For importing an account from a private key" }, "pending": { - "message": "펜딩 중" + "message": "보류 중" + }, + "permissionCheckedIconDescription": { + "message": "이 권한을 수락하셨습니다." + }, + "permissionUncheckedIconDescription": { + "message": "이 권한을 수락하지 않으셨습니다." + }, + "permissions": { + "message": "권한" }, "personalAddressDetected": { - "message": "개인 주소가 탐지됨. 토큰 컨트랙트 주소를 입력하세요." + "message": "개인 주소가 발견되었습니다. 토큰 계약 주소를 입력하세요." + }, + "plusXMore": { + "message": "+ 외 $1개", + "description": "$1 is a number of additional but unshown items in a list- this message will be shown in place of those items" }, "prev": { "message": "이전" }, "primaryCurrencySetting": { - "message": "주 화폐" + "message": "기본 통화" }, "primaryCurrencySettingDescription": { - "message": "체인의 고유 통화 값으로 우선 표기하시려면 네이티브를 선택하세요. (예: ETH) 설정하신 Fiat 통화 값으로 우선 표기하시려면 Fiat을 선택하세요." + "message": "체인의 고유 통화(예: ETH)로 값을 우선 표시하려면 고유를 선택합니다. 선택한 명목 통화로 값을 우선 표시하려면 명목을 선택합니다." }, "privacyMsg": { - "message": "개인정보 보호 정책" + "message": "개인정보 보호정책" }, "privateKey": { - "message": "개인키", + "message": "비공개 키", "description": "select this type of file to use to import an account" }, "privateKeyWarning": { - "message": "절대 이 키를 노출하지 마십시오. 개인키가 노출되면 누구나 당신의 계정에서 자산을 빼갈 수 있습니다." + "message": "경고: 이 키를 노출하지 마세요. 비공개 키가 있는 사람이라면 누구든 귀하의 계정에 있는 자산을 훔칠 수 있습니다." }, "privateNetwork": { - "message": "프라이빗 네트워크" + "message": "비공개 네트워크" + }, + "proposedApprovalLimit": { + "message": "제안된 승인 한도" }, "protectYourKeys": { "message": "키를 보호하세요!" }, "protectYourKeysMessage1": { - "message": "시드 문구에 주의하세요 - MetaMask를 모방하려고 한 웹사이트들이 신고됐습니다. MetaMask는 절대로 시드 문구를 묻지 않습니다!" + "message": "시드 구문을 조심하세요. MetaMask를 흉내 내는 웹사이트가 보고되고 있습니다. MetaMask에서는 시드 구문을 절대로 물어보지 않습니다!" }, "protectYourKeysMessage2": { - "message": "시드 문구를 안전하게 유지하세요. 수상한 점을 발견하거나, 웹사이트에 확신이 들지 않으면 support@metamask.io로 이메일을 보내 주세요" + "message": "시드 구문을 안전하게 보관하세요. 피싱으로 의심되는 행위를 목격했거나 웹사이트가 수상하다면 support@metamask.io로 이메일을 보내세요." + }, + "provide": { + "message": "제공" }, "queue": { - "message": "큐" + "message": "대기열" + }, + "queued": { + "message": "대기열에 지정됨" }, "readdToken": { - "message": "옵션 메뉴에서 “토큰 추가”를 눌러서 추후에 다시 이 토큰을 추가하실 수 있습니다." + "message": "나중에 계정 옵션 메뉴의 “토큰 추가”로 이동하면 이 토큰을 다시 추가할 수 있습니다." }, "readyToConnect": { - "message": "접속 준비되었나요?" + "message": "연결할 준비가 되셨나요?" + }, + "receive": { + "message": "받기" }, "recents": { "message": "최근" }, "recipientAddress": { - "message": "받는 주소" + "message": "수신인 주소" }, "recipientAddressPlaceholder": { - "message": "검색, 공개 주소 (0x), 또는 ENS" + "message": "검색, 공개 주소(0x) 또는 ENS" }, "reject": { "message": "거부" @@ -800,16 +1256,16 @@ "message": "모두 거부" }, "rejectTxsDescription": { - "message": "$1 트랜잭션을 거부합니다." + "message": "거래 $1개를 모두 거부합니다." }, "rejectTxsN": { - "message": "$1 트랜잭션 거부" + "message": "거래 $1개 거부" }, "rejected": { "message": "거부됨" }, "remindMeLater": { - "message": "나중에 알려 주세요" + "message": "나중에 알림" }, "remove": { "message": "제거" @@ -818,55 +1274,65 @@ "message": "계정 제거" }, "removeAccountDescription": { - "message": "이 계정은 지갑에서 삭제될 것입니다. 지우기 전에 이 계정에 대한 개인 키 혹은 시드 구문을 가지고 있는지 확인하세요. 계정 드롭다운 메뉴를 통해서 계정을 가져오거나 생성할 수 있습니다." + "message": "이 계정이 지갑에서 제거됩니다. 계속하기 전에 가져온 이 계정에 대한 원본 시드 구문이나 비공개 키가 있는지 확인하세요. 계정 드롭다운에서 계정을 가져오거나 다시 만들 수 있습니다. " }, "requestsAwaitingAcknowledgement": { - "message": "요청이 인정되기까지 대기중" + "message": "확인 대기 중인 요청" }, "required": { - "message": "필요함" + "message": "필요" }, "reset": { - "message": "초기화" + "message": "재설정" }, "resetAccount": { - "message": "계정 초기화" + "message": "계정 재설정" }, "resetAccountDescription": { - "message": "계정을 초기화 하는 경우에 트랜잭션 기록이 삭제됩니다." + "message": "계정을 재설정하면 거래 내역이 지워집니다. 계정의 잔액이 변경되지는 않으면 시드 구문을 다시 입력하지 않아도 됩니다." }, "restore": { "message": "복구" }, "restoreAccountWithSeed": { - "message": "시드 구문으로 계정 복구하기" + "message": "시드 구문으로 계정 복구" }, "restoreFromSeed": { "message": "계정을 복구하시겠습니까?" }, + "restoreWalletPreferences": { + "message": "$1의 데이터 백업이 발견되었습니다. 지갑 환경설정을 복구하시겠습니까?", + "description": "$1 is the date at which the data was backed up" + }, + "retryTransaction": { + "message": "거래 재시도" + }, + "reusedTokenNameWarning": { + "message": "여기에 있는 토큰은 사용자가 확인한 다른 토큰의 기호를 재사용하기 때문에 혼란스럽거나 속기 쉽습니다." + }, "revealSeedWords": { - "message": "시드 단어 보이기" + "message": "시드 단어 공개" }, "revealSeedWordsDescription": { - "message": "브라우저를 바꾸거나 컴퓨터를 옮기는 경우 이 시드 구문이 필요하며 이를 통해 계정에 접근할 수 있습니다. 시드 구문을 안전한 곳에 보관하세요." + "message": "브라우저를 변경하거나 컴퓨터를 옮긴 경우, 계정에 액세스하려면 이 시드 구문이 필요합니다. 기밀이 보장된 안전한 곳에 보관하세요." }, "revealSeedWordsTitle": { - "message": "시드 단어" + "message": "시드 구문" }, "revealSeedWordsWarning": { - "message": "이 단어 모음은 당신의 모든 계정을 훔치는데 사용할 수 있습니다." + "message": "이 구문은 계정 전체를 도용하는 데 사용될 수 있습니다." }, "revealSeedWordsWarningTitle": { - "message": "이 구문을 다른 사람과 절대로 공유하지 마세요!" + "message": "이 구문은 누구와도 공유하지 마세요!" }, "rinkeby": { - "message": "Rinkeby 테스트넷" + "message": "Rinkeby 테스트 네트워크" }, "ropsten": { - "message": "Ropsten 테스트넷" + "message": "Ropsten 테스트 네트워크" }, "rpcUrl": { - "message": "새로운 RPC URL" + "message": "새 RPC URL" }, "save": { "message": "저장" @@ -875,14 +1341,20 @@ "message": "CSV 파일로 저장" }, "scanInstructions": { - "message": "QR 코드를 카메라 앞에 가져다 놓아주세요" + "message": "QR 코드를 카메라 앞에 놓으세요" }, "scanQrCode": { "message": "QR 코드 스캔" }, + "scrollDown": { + "message": "화면을 아래로 내리세요" + }, "search": { "message": "검색" }, + "searchAccounts": { + "message": "계정 검색" + }, "searchResults": { "message": "검색 결과" }, @@ -893,94 +1365,122 @@ "message": "비밀 백업 구문" }, "secretBackupPhraseDescription": { - "message": "비밀 백업 구문을 사용하면 계정을 쉽게 백업하고 복원할 수 있습니다." + "message": "비밀 백업 구문을 이용하면 계정을 쉽게 백업하고 복구할 수 있습니다." }, "secretBackupPhraseWarning": { - "message": "경고: 백업 구문을 절대 공개하지 마세요. 이 구문을 가진 누군가 당신의 이더를 영원히 가지고 갈 수 있습니다." + "message": "경고: 백업 구문은 절대로 공개하지 마세요. 이 구문이 있는 사람은 귀하의 Ether를 영원히 소유할 수 있습니다." }, "secretPhrase": { - "message": "12개 단어로 구성된 비밀 구문을 입력하여 저장소를 복구하세요." + "message": "금고를 복구하려면 비밀 12단어 구문을 여기에 입력하세요." }, "securityAndPrivacy": { - "message": "보안 및 개인 정보 보호" + "message": "보안 및 개인정보 보호" }, "securitySettingsDescription": { - "message": "개인 정보 보호 설정 및 월렛 시드 문구" + "message": "개인정보 설정 및 지갑 시드 구문" }, "seedPhrasePlaceholder": { - "message": "각 단어를 스페이스로 구분해주세요" + "message": "공백 한 칸으로 각 단어를 구분하세요" + }, + "seedPhrasePlaceholderPaste": { + "message": "클립보드에서 시드 구문 붙여넣기" }, "seedPhraseReq": { - "message": "시드 구문은 12개의 단어입니다" + "message": "시드 구문에 12, 15, 18, 21 또는 24단어 포함" }, "selectAHigherGasFee": { - "message": "트랜잭션 처리를 가속하기 위해 더 높은 가스 요금을 선택하세요.*" + "message": "높은 Gas 요금을 선택하면 거래 처리 속도를 높일 수 있습니다.*" + }, + "selectAccounts": { + "message": "계정 선택" + }, + "selectAll": { + "message": "모두 선택" }, "selectAnAccount": { "message": "계정 선택" }, "selectAnAccountHelp": { - "message": "메타마스크에서 보기 위한 계정 선택" + "message": "MetaMask에서 확인할 계정 선택" }, "selectCurrency": { "message": "통화 선택" }, "selectEachPhrase": { - "message": "백업 구문이 올바른지 확인하기 위해 각 단어를 순서에 맞게 선택해주세요." + "message": "각 구문을 선택하여 구문이 올바른지 확인하세요." }, "selectHdPath": { - "message": "HD 경로 지정" + "message": "HD 경로 선택" }, "selectLocale": { - "message": "언어 선택" + "message": "로캘 선택" }, "selectPathHelp": { - "message": "하단에서 Ledger 지갑 계정을 찾지 못하겠으면 \"Legacy (MEW / MyCrypto)\" 경로로 바꿔보세요" + "message": "아래에 기존 Ledger 계정이 표시되지 않는다면 경로를 \"Legacy(MEW / MyCrypto)\"로 변경해 보세요." }, "selectType": { - "message": "형식 선택" + "message": "유형 선택" + }, + "selectingAllWillAllow": { + "message": "모두 선택하면 이 사이트에서 귀하의 현재 계정을 모두 볼 수 있습니다. 이 사이트를 신뢰하는지 확인하세요." }, "send": { - "message": "전송" + "message": "보내기" }, "sendAmount": { - "message": "전송 수량" + "message": "금액 보내기" }, "sendETH": { "message": "ETH 보내기" }, + "sendSpecifiedTokens": { + "message": "$1 보내기", + "description": "Symbol of the specified token" + }, "sendTokens": { - "message": "토큰 전송" + "message": "토큰 보내기" }, "sentEther": { - "message": "전송된 이더" + "message": "Ether 보냄" }, "separateEachWord": { - "message": "각 단어는 공백 한칸으로 분리합니다" + "message": "공백 한 칸으로 각 단어를 구분하세요" }, "settings": { "message": "설정" }, "showAdvancedGasInline": { - "message": "고급 가스 제어" + "message": "고급 Gas 제어 기능" }, "showAdvancedGasInlineDescription": { - "message": "전송 및 확인 화면에서 직접 가스 가격과 한도 제어를 표시하려면 이 옵션을 선택해주세요." + "message": "이 항목을 선택하면 보내기 및 확인 화면에 Gas 가격이 표시되며 제어 기능을 바로 제한할 수 있습니다." }, "showFiatConversionInTestnets": { - "message": "테스트 넷에서 fiat 변환 보여주기" + "message": "테스트넷에 전환 표시" }, "showFiatConversionInTestnetsDescription": { - "message": "테스트 넷에서 fiat 변환을 보기 위해 활성화하세요" + "message": "이 항목을 선택하면 테스트넷에 명목 전환을 표시합니다." }, "showHexData": { - "message": "Hex 데이터 보기" + "message": "16진수 데이터 표시" }, "showHexDataDescription": { - "message": "선택하면 전송화면의 hex 데이터 필드 값을 보여줍니다." + "message": "이 항목을 선택하면 보내기 화면에 16진수 데이터 필드가 표시됩니다." + }, + "showIncomingTransactions": { + "message": "수신 거래 표시" + }, + "showIncomingTransactionsDescription": { + "message": "이 항목을 선택하면 Etherscan을 사용하여 거래 목록에 수신 거래를 표시합니다." + }, + "showPermissions": { + "message": "권한 표시" }, "showPrivateKeys": { - "message": "개인키 보기" + "message": "비공개 키 표시" + }, + "showSeedPhrase": { + "message": "시드 구문 표시" }, "sigRequest": { "message": "서명 요청" @@ -989,11 +1489,14 @@ "message": "서명" }, "signNotice": { - "message": "이 메시지에 대한 서명은 위험할 수 있습니다.\n 완전히 신뢰할 수 있는 사이트에서만 서명해주세요.\n 안전을 위해 추후의 버전에서는 삭제될 기능입니다. " + "message": "이 메시지에 서명하면 \n위험한 부작용이 발생할 수 있습니다. 전체 계정으로 신뢰할 수 있는 \n사이트에서 보내는 메시지만 서명하세요.\n 위험한 이 방법은 이후 버전에서 제거될 예정입니다. " }, "signatureRequest": { "message": "서명 요청" }, + "signatureRequest1": { + "message": "메시지" + }, "signed": { "message": "서명됨" }, @@ -1001,106 +1504,418 @@ "message": "느림" }, "somethingWentWrong": { - "message": "헉! 뭔가 잘못됐어요." + "message": "이런! 문제가 발생했습니다." }, "speedUp": { - "message": "속도 향상" + "message": "가속화" }, "speedUpCancellation": { - "message": "취소 속도 향상" + "message": "이 취소 가속화" }, "speedUpTransaction": { - "message": "트랜잭션 속도 향상" + "message": "이 거래 가속화" + }, + "spendLimitAmount": { + "message": "지출 한도 금액" + }, + "spendLimitInsufficient": { + "message": "지출 한도 부족" + }, + "spendLimitInvalid": { + "message": "지출 한도가 올바르지 않습니다. 지출 한도는 양수여야 합니다." + }, + "spendLimitPermission": { + "message": "지출 한도 권한" + }, + "spendLimitRequestedBy": { + "message": "$1에서 요청한 지출 한도", + "description": "Origin of the site requesting the spend limit" + }, + "spendLimitTooLarge": { + "message": "지출 한도가 너무 큼" }, "stateLogError": { - "message": "상태 로그 받기 실패." + "message": "상태 로그를 가져오는 도중 오류가 발생했습니다." + }, + "stateLogFileName": { + "message": "MetaMask 상태 로그" }, "stateLogs": { "message": "상태 로그" }, "stateLogsDescription": { - "message": "상태 로그에는 공개 계정 주소와 송신 트랜잭션 정보가 들어있습니다." + "message": "상태 로그에 공개 계정 주소와 전송된 거래가 있습니다." + }, + "statusConnected": { + "message": "연결됨" + }, + "statusNotConnected": { + "message": "연결되지 않음" }, "step1HardwareWallet": { "message": "1. 하드웨어 지갑 연결" }, "step1HardwareWalletMsg": { - "message": "하드웨어 지갑을 컴퓨터에 연결해주세요." + "message": "하드웨어 지갑을 컴퓨터에 바로 연결합니다." }, "step2HardwareWallet": { "message": "2. 계정 선택" }, "step2HardwareWalletMsg": { - "message": "보고 싶은 계정을 선택합니다. 한 번에 하나의 계정만 선택할 수 있습니다." + "message": "확인할 계정을 선택하세요. 한 번에 하나만 선택할 수 있습니다." }, "step3HardwareWallet": { - "message": "3. dApps을 사용하거나 다른 것을 합니다!" + "message": "3. web3 사이트 등을 사용해 시작하세요!" }, "step3HardwareWalletMsg": { - "message": "다른 이더리움 계정을 사용하듯 하드웨어 계정을 사용합니다. dApps을 로그인하거나, 이더를 보내거나, ERC20 토큰 혹은 대체 가능하지 않은 토큰 (예를 들어 CryptoKitties)을 사거나 저장하거나 합니다." + "message": "하드웨어 계정을 이더리움 계정에서처럼 사용하세요. web3 사이트에 연결하고, ETH를 보내고, ERC20 토큰 및 CryptoKitties 같은 대체 불가능 토큰을 구매하고 저장하세요." }, "storePhrase": { - "message": "이 구문을 1Password같은 암호 관리자에 저장하세요." + "message": "이 구문을 1Password 같은 암호 관리자에 저장하세요." + }, + "submit": { + "message": "제출" }, "submitted": { "message": "제출됨" }, "supportCenter": { - "message": "지원 센터에 방문하기" + "message": "지원 센터 방문하기" + }, + "swap": { + "message": "스왑" + }, + "swapAdvancedSlippageInfo": { + "message": "주문 시점과 확인 시점 사이에 가격이 변동되는 현상을 “슬리패지”라고 합니다. 슬리패지가 \"최대 슬리패지\" 설정을 초과하면 스왑이 자동으로 취소됩니다." + }, + "swapAggregator": { + "message": "애그리게이터" + }, + "swapAmountReceived": { + "message": "보장 금액" + }, + "swapAmountReceivedInfo": { + "message": "수신하는 최소 금액입니다. 슬리패지에 따라 추가 금액을 받을 수도 있습니다." + }, + "swapApproval": { + "message": "$1 스왑 승인", + "description": "Used in the transaction display list to describe a transaction that is an approve call on a token that is to be swapped.. $1 is the symbol of a token that has been approved." + }, + "swapApproveNeedMoreTokens": { + "message": "이 스왑을 완료하려면 $1와(과) 추가 $2이(가) 필요합니다.", + "description": "Tells the user how many more of a given token they need for a specific swap. $1 is an amount of tokens and $2 is the token symbol." + }, + "swapBuildQuotePlaceHolderText": { + "message": "$1와(과) 일치하는 가용 토큰 없음", + "description": "Tells the user that a given search string does not match any tokens in our token lists. $1 can be any string of text" + }, + "swapCheckingQuote": { + "message": "$1 확인 중", + "description": "Shown to the user during quote loading. $1 is the name of an aggregator. The message indicates that metamask is currently checking if that aggregator has a trade/quote for their requested swap." + }, + "swapCustom": { + "message": "맞춤형" + }, + "swapDecentralizedExchange": { + "message": "분산형 교환" + }, + "swapEditLimit": { + "message": "한도 편집" + }, + "swapEnableDescription": { + "message": "필수이며 MetaMask에게 $1을(를) 스왑할 권한을 제공합니다.", + "description": "Gives the user info about the required approval transaction for swaps. $1 will be the symbol of a token being approved for swaps." + }, + "swapEstimatedNetworkFee": { + "message": "예상 네트워크 요금" + }, + "swapEstimatedNetworkFeeSummary": { + "message": "“$1”은(는) 당사가 예상하는 실제 요금입니다. 정확한 금액은 네트워크 상태에 따라 달라집니다.", + "description": "$1 will be the translation of swapEstimatedNetworkFee, with the font bolded" + }, + "swapEstimatedNetworkFees": { + "message": "예상 네트워크 요금" + }, + "swapEstimatedNetworkFeesInfo": { + "message": "스왑을 완료하는 데 사용할 네트워크 요금 예상치입니다. 실제 금액은 네트워크 조건에 따라 달라질 수 있습니다." + }, + "swapFailedErrorDescription": { + "message": "자금은 안전하며 지갑에서 계속 사용할 수 있습니다." + }, + "swapFailedErrorTitle": { + "message": "스왑 실패" + }, + "swapFetchingQuotesErrorDescription": { + "message": "음.... 문제가 발생했습니다. 다시 시도해 보고 오류가 해결되지 않는다면 고객 지원에 문의하세요." + }, + "swapFetchingQuotesErrorTitle": { + "message": "견적 가져오는 중 오류 발생" + }, + "swapFetchingTokens": { + "message": "토큰 가져오는 중..." + }, + "swapFinalizing": { + "message": "마무리 중..." + }, + "swapGetQuotes": { + "message": "견적 가져오기" + }, + "swapHighSlippageWarning": { + "message": "슬리패지 금액이 아주 큽니다. 현재 어떤 작업을 하고 있는지 확인하세요!" + }, + "swapIntroLearnMoreHeader": { + "message": "자세한 정보를 확인하고 싶으신가요?" + }, + "swapIntroLearnMoreLink": { + "message": "MetaMask Swaps에 대해 자세히 알아보기" + }, + "swapIntroLiquiditySourcesLabel": { + "message": "다음을 포함한 유동성 소스:" + }, + "swapIntroPopupSubTitle": { + "message": "이제 MetaMask 지갑에서 토큰을 바로 스왑할 수 있습니다. MetaMask Swaps는 다양한 분산형 교환 애그리게이터, 투자전문기관, 개별 DEX를 결합하여 MetaMask 사용자가 언제든 최저 네트워크 요금으로 최상의 가격을 얻을 수 있게 합니다." + }, + "swapIntroPopupTitle": { + "message": "토큰 스왑은 여기서 진행됩니다!" + }, + "swapLearnMoreContractsAuditReview": { + "message": "당사의 공식 계약 감사 검토" + }, + "swapLowSlippageError": { + "message": "거래가 실패할 수도 있습니다. 최대 슬리패지가 너무 낮습니다." + }, + "swapMaxNetworkFeeInfo": { + "message": "“$1”이(가) 최대 지출 금액입니다. 네트워크가 불안정한 경우 금액이 증가할 수 있습니다.", + "description": "$1 will be the translation of swapMaxNetworkFees, with the font bolded" + }, + "swapMaxNetworkFees": { + "message": "최대 네트워크 요금" + }, + "swapMaxSlippage": { + "message": "최대 슬리패지" + }, + "swapMetaMaskFee": { + "message": "MetaMask 요금" + }, + "swapMetaMaskFeeDescription": { + "message": "당사는 매번 최상의 유동성 소스에서 최적 가격을 찾습니다. $1% 요금은 각 견적에 자동으로 반영되어, MetaMask를 더욱 개선하는 현재 진행 중인 개발을 지원합니다.", + "description": "Provides information about the fee that metamask takes for swaps. $1 is a decimal number." + }, + "swapNetworkFeeSummary": { + "message": "네트워크 요금에는 스왑을 처리하고 이더리움 네트워크에 보관하는 비용이 적용됩니다. MetaMask는 이 요금을 이용해 이득을 얻지 않습니다." + }, + "swapNewQuoteIn": { + "message": "$1 후에 새 견적", + "description": "Tells the user the amount of time until the currently displayed quotes are update. $1 is a time that is counting down from 1:00 to 0:00" + }, + "swapOnceTransactionHasProcess": { + "message": "$1은(는) 이 거래가 처리되면 귀하의 계정에 추가됩니다.", + "description": "This message communicates the token that is being transferred. It is shown on the awaiting swap screen. The $1 will be a token symbol." + }, + "swapProcessing": { + "message": "처리 중" + }, + "swapQuoteDetails": { + "message": "견적 세부 정보" + }, + "swapQuoteDetailsSlippageInfo": { + "message": "주문 시점과 확인 시점 사이에 가격이 변동되는 현상을 \"슬리패지\"라고 합니다. 슬리패지가 \"최대 슬리패지\" 설정을 초과하면 스왑이 자동으로 취소됩니다." + }, + "swapQuoteIncludesRate": { + "message": "견적에는 $1% MetaMask 요금이 포함됩니다.", + "description": "Provides information about the fee that metamask takes for swaps. $1 is a decimal number." + }, + "swapQuoteNofN": { + "message": "$2의 $1 견적", + "description": "A count of loaded quotes shown to the user while they are waiting for quotes to be fetched. $1 is the number of quotes already loaded, and $2 is the total number of quotes to load." + }, + "swapQuoteSource": { + "message": "견적 소스" + }, + "swapQuotesAreRefreshed": { + "message": "견적은 현재 시장 상황을 반영하도록 자주 갱신됩니다." + }, + "swapQuotesExpiredErrorDescription": { + "message": "지금 견적을 요청해 최신 요율을 확인하세요." + }, + "swapQuotesExpiredErrorTitle": { + "message": "견적 시간 초과" + }, + "swapQuotesNotAvailableErrorDescription": { + "message": "금액 또는 슬리패지 설정을 조정한 후 다시 시도해 보세요." + }, + "swapQuotesNotAvailableErrorTitle": { + "message": "사용 가능한 견적 없음" + }, + "swapRate": { + "message": "요율" + }, + "swapReceiving": { + "message": "수신 중" + }, + "swapReceivingInfoTooltip": { + "message": "이것은 예상치입니다. 정확한 금액은 슬리패지에 따라 달라집니다." + }, + "swapRequestForQuotation": { + "message": "견적 요청" + }, + "swapSearchForAToken": { + "message": "토큰 검색" + }, + "swapSelect": { + "message": "선택" + }, + "swapSelectAQuote": { + "message": "견적 선택" + }, + "swapSelectAToken": { + "message": "토큰 선택" + }, + "swapSelectQuotePopoverDescription": { + "message": "다음은 여러 유동성 소스에서 수집한 전체 견적입니다." + }, + "swapSlippageTooLow": { + "message": "슬리패지는 0보다 커야 합니다." + }, + "swapSource": { + "message": "유동성 소스" + }, + "swapSourceInfo": { + "message": "당사에서는 여러 유동성 소스(교환, 애그리게이터, 투자전문기관)를 검색하여 최상의 요율과 최저 네트워크 요금을 찾습니다." + }, + "swapStartSwapping": { + "message": "스왑 시작" + }, + "swapSwapFrom": { + "message": "다음에서 스왑" + }, + "swapSwapSwitch": { + "message": "토큰에서 또는 토큰으로 전환" + }, + "swapSwapTo": { + "message": "다음으로 스왑" + }, + "swapThisWillAllowApprove": { + "message": "$1이(가) 스왑될 수 있도록 허용합니다." + }, + "swapTokenAvailable": { + "message": "$1이(가) 계정에 추가되었습니다.", + "description": "This message is shown after a swap is successful and communicates the exact amount of tokens the user has received for a swap. The $1 is a decimal number of tokens followed by the token symbol." + }, + "swapTokenToToken": { + "message": "$1에서 $2(으)로 스왑", + "description": "Used in the transaction display list to describe a swap. $1 and $2 are the symbols of tokens in involved in a swap." + }, + "swapTransactionComplete": { + "message": "거래 완료" + }, + "swapUnknown": { + "message": "알 수 없음" + }, + "swapVerifyTokenExplanation": { + "message": "여러 토큰이 같은 이름과 기호를 사용할 수 있습니다. Etherscan을 확인하여 이것이 원하는 토큰인지 확인하세요." + }, + "swapViewToken": { + "message": "$1 보기" + }, + "swapYourTokenBalance": { + "message": "$1 $2 스왑 가능", + "description": "Tells the user how much of a token they have in their balance. $1 is a decimal number amount of tokens, and $2 is a token symbol" + }, + "swapZeroSlippage": { + "message": "0% 슬리패지" + }, + "swapsAdvancedOptions": { + "message": "고급 옵션" + }, + "swapsMaxSlippage": { + "message": "최대 슬리패지" + }, + "swapsNotEnoughForTx": { + "message": "$1이(가) 부족하여 이 거래를 완료할 수 없음", + "description": "Tells the user that they don't have enough of a token for a proposed swap. $1 is a token symbol" + }, + "swapsViewInActivity": { + "message": "활동에서 보기" }, "switchNetworks": { - "message": "네트워크 변경" + "message": "네트워크 전환" + }, + "switchToThisAccount": { + "message": "이 계정으로 전환" }, "symbol": { "message": "기호" }, "symbolBetweenZeroTwelve": { - "message": "심볼은 0에서 12개 사이의 문자여야 합니다." + "message": "기호는 11자 이하여야 합니다." }, "syncWithMobile": { - "message": "모바일로 동기화" + "message": "모바일과 동기화" }, "syncWithMobileBeCareful": { - "message": "이 코드를 스캔할 때 귀하의 화면을 보는 사람이 없는 것을 확인하세요" + "message": "이 코드를 스캔할 때는 다른 사람이 화면을 보지 못하게 하세요." }, "syncWithMobileComplete": { - "message": "데이터가 성공적으로 동기화됐습니다. MetaMask 모바일 앱을 즐겁게 사용하세요!" + "message": "데이터가 동기화되었습니다. MetaMask 모바일 앱을 마음껏 이용하세요!" }, "syncWithMobileDesc": { - "message": "모바일 기기와 계정 및 정보를 동기화할 수 있습니다. MetaMask 모바일 앱을 열고, \"설정\"으로 간 다음 \"브라우저 확장 프로그램에서 동기화\"를 누르세요" + "message": "계정과 정보를 모바일 장치와 동기화할 수 있습니다. MetaMask 모바일 앱을 열고 \"설정\"으로 이동하여 \"브라우저 확장에서 동기화\"를 탭합니다." }, "syncWithMobileDescNewUsers": { - "message": "처음으로 MetaMask 모바일 앱을 여시는 경우, 전화에 나온 과정을 따르세요." + "message": "MetaMask 모바일 앱을 처음 열었다면 전화에 표시되는 단계를 따르세요." }, "syncWithMobileScanThisCode": { - "message": "MetaMask 모바일 앱으로 이 코드를 스캔하세요" + "message": "MetaMask 모바일 앱으로 이 코드를 스캔하세요." }, "syncWithMobileTitle": { "message": "모바일과 동기화" }, + "syncWithThreeBox": { + "message": "3Box로 데이터 동기화(실험적 기능)" + }, + "syncWithThreeBoxDescription": { + "message": "이 기능을 켜면 3Box를 이용해 설정을 백업합니다. 이 기능은 현재 실험 중입니다. 책임은 사용자가 져야 합니다." + }, + "syncWithThreeBoxDisabled": { + "message": "초기 동기화 도중 오류가 발생하여 3Box가 비활성화되었습니다." + }, "terms": { - "message": "사용 지침" + "message": "이용 약관" + }, + "termsOfService": { + "message": "서비스 약관" }, "testFaucet": { - "message": "파우셋 테스트" + "message": "포시트 테스트" }, "thisWillCreate": { - "message": "새로운 지갑과 시드 구문을 생성" + "message": "새 지갑과 시드 구문을 만듭니다." }, "tips": { "message": "팁" }, "to": { - "message": "받는이" + "message": "수신" + }, + "toAddress": { + "message": "수신: $1", + "description": "$1 is the address to include in the To label. It is typically shortened first using shortenAddress" + }, + "toWithColon": { + "message": "수신:" }, "token": { "message": "토큰" }, "tokenAlreadyAdded": { - "message": "토큰이 이미 추가되어있습니다." + "message": "토큰이 이미 추가되었습니다." }, "tokenContractAddress": { - "message": "토큰 컨트랙트 주소" + "message": "토큰 계약 주소" + }, + "tokenOptions": { + "message": "토큰 옵션" }, "tokenSymbol": { "message": "토큰 기호" @@ -1109,65 +1924,73 @@ "message": "합계" }, "transaction": { - "message": "트랜잭션" + "message": "거래" }, "transactionCancelAttempted": { - "message": "$1의 가스 요금으로 트랜잭션 취소가 시도됨 $2." + "message": "$2에서 Gas 요금이 $1인 거래 취소 시도됨" }, "transactionCancelSuccess": { - "message": "트랜잭션이 성공적으로 취소됨 $2." + "message": "$2에서 거래 취소 성공" }, "transactionConfirmed": { - "message": "트랜잭션이 승인됨 $2." + "message": "$2에서의 거래가 확인되었습니다." }, "transactionCreated": { - "message": "$1에 대한 트랜잭션이 생성됨 $2." + "message": "$2에서 $1 값으로 거래를 만들었습니다." }, "transactionDropped": { - "message": "트랜잭션이 드롭됨 $2." + "message": "$2에서의 거래가 중단되었습니다." }, "transactionError": { - "message": "트랜잭션 오류. 컨트랙트 코드에서 예외 발생(Exception thrown)." + "message": "거래 오류입니다. 계약 코드에서 예외가 반환되었습니다." }, "transactionErrorNoContract": { - "message": "비계약 주소에서 기능을 호출하려고 합니다." + "message": "비계약 주소에서 함수를 호출하고 있습니다." }, "transactionErrored": { - "message": "트랜잭션 오류 발생." + "message": "거래에서 오류가 발생했습니다." }, "transactionFee": { - "message": "수수료" + "message": "거래 수수료" }, "transactionResubmitted": { - "message": "$1으로 가스 요금을 올려 트랜잭션이 다시 제출됨 $2." + "message": "$2에서 Gas 요금이 $1(으)로 증가한 거래가 다시 제출됨" }, "transactionSubmitted": { - "message": "$1의 가스 요금으로 트랜잭션이 제출됨 $2." + "message": "$2에서 Gas 요금이 $1인 거래가 제출되었습니다." }, "transactionUpdated": { - "message": "트랜잭션이 수정됨 $2." + "message": "$2에서의 거래가 업데이트되었습니다." }, "transfer": { "message": "전송" }, "transferBetweenAccounts": { - "message": "나의 계정 간 이체" + "message": "계정 간 전송" }, "transferFrom": { - "message": "보내는 이" + "message": "전송 위치" + }, + "troubleConnectingToWallet": { + "message": "$1 연결 도중 문제가 발생했습니다. $2을(를) 검도하고 다시 시도해 보세요.", + "description": "$1 is the wallet device name; $2 is a link to wallet connection guide" }, "troubleTokenBalances": { - "message": "토큰 잔액을 가져오는 데에 문제가 생겼습니다. 링크에서 상세내용을 볼 수 있습니다.", + "message": "토큰 잔액을 로드하는 도중 문제가 발생했습니다. 잔액을 확인할 수 있습니다. ", "description": "Followed by a link (here) to view token balances" }, + "trustSiteApprovePermission": { + "message": "이 사이트를 신뢰하시나요? 이 권한을 부여하면 $1에서 귀하의 $2을(를) 인출하고 거래를 자동으로 처리하게 됩니다.", + "description": "$1 is the url requesting permission and $2 is the symbol of the currency that the request is for" + }, "tryAgain": { - "message": "다시 시도하세요" + "message": "다시 시도" }, "typePassword": { - "message": "비밀번호를 입력하세요" + "message": "MetaMask 암호 입력" }, "unapproved": { - "message": "허가 안 됨" + "message": "승인되지 않음" }, "units": { "message": "단위" @@ -1176,34 +1999,50 @@ "message": "알 수 없음" }, "unknownCameraError": { - "message": "카메라에 접근하는 중 오류가 발생했습니다. 다시 시도해 주세요..." + "message": "카메라에 액세스하는 도중 오류가 발생했습니다. 다시 시도하세요..." }, "unknownCameraErrorTitle": { - "message": "이런! 뭔가 잘못되었습니다...." + "message": "이런! 문제가 발생했습니다...." }, "unknownNetwork": { - "message": "알 수 없는 프라이빗 네트워크" + "message": "알 수 없는 비공개 네트워크" }, "unknownQrCode": { - "message": "오류: QR 코드를 확인할 수 없습니다" + "message": "오류: QR 코드를 식별할 수 없습니다." + }, + "unlimited": { + "message": "무제한" }, "unlock": { "message": "잠금 해제" }, "unlockMessage": { - "message": "우리가 기다리던 탈 중앙화 웹입니다" + "message": "분산된 웹이 다음을 대기 중" }, "updatedWithDate": { - "message": "$1에 업데이트 됨" + "message": "$1에 업데이트됨" }, "urlErrorMsg": { - "message": "URI는 HTTP/HTTPS로 시작해야 합니다." + "message": "URI에는 적절한 HTTP/HTTPS 접두사가 필요합니다." + }, + "urlExistsErrorMsg": { + "message": "URL이 기존 네트워크 목록에 이미 존재함" + }, + "usePhishingDetection": { + "message": "피싱 감지 사용" + }, + "usePhishingDetectionDescription": { + "message": "이더리움 사용자를 노리는 피싱 도메인에 대한 경고를 표시합니다." }, "usedByClients": { - "message": "다양한 클라이언트에서 사용되고 있습니다" + "message": "다양한 클라이언트에서 사용합니다." }, "userName": { - "message": "사용자이름" + "message": "사용자 이름" + }, + "verifyThisTokenOn": { + "message": "$1에서 이 토큰 확인", + "description": "Points the user to etherscan as a place they can verify information about a token. $1 is replaced with the translation for \"etherscan\"" }, "viewAccount": { "message": "계정 보기" @@ -1212,42 +2051,52 @@ "message": "연락처 보기" }, "viewOnCustomBlockExplorer": { - "message": "$1에 보기" + "message": "$1에서 보기" }, "viewOnEtherscan": { - "message": "이더스캔에서 보기" + "message": "Etherscan에서 보기" }, "viewinExplorer": { - "message": "익스플로러에서 보기" + "message": "탐색기에서 보기" }, "visitWebSite": { - "message": "웹사이트 방문" + "message": "당사 웹사이트 방문하기" + }, + "walletConnectionGuide": { + "message": "당사의 하드웨어 지갑 연결 가이드" }, "walletSeed": { - "message": "지갑 시드값" + "message": "시드 구문" }, "welcome": { - "message": "메타마스크 Beta에 오신 것을 환영합니다" + "message": "MetaMask 방문을 환영합니다" }, "welcomeBack": { - "message": "환영합니다!" + "message": "재방문을 환영합니다!" + }, + "whatsThis": { + "message": "이것은 무엇인가요?" }, "writePhrase": { - "message": "이 구문을 종이에 써서 안전한 장소에 보관하세요. 만약 당신이 더 높은 수준의 보안을 원한다면, 그것을 여러 장의 종이에 적어서 각각 2-3개의 다른 위치에 보관하세요." + "message": "메모지에 이 구문을 적어 안전한 곳에 보관하세요. 보안을 더욱 강화하고 싶다면 여러 메모지에 적은 다음 2~3곳에 보관하세요." + }, + "xOfY": { + "message": "$2 중 $1", + "description": "$1 and $2 are intended to be two numbers, where $2 is a total, and $1 is a count towards that total" }, "yesLetsTry": { - "message": "네, 시도해보겠습니다." + "message": "예, 시도하겠습니다." }, "youNeedToAllowCameraAccess": { - "message": "이 기능을 사용하려면 카메라 접근을 허용해야 합니다." + "message": "이 기능을 사용하려면 카메라 액세스를 허용해야 합니다." }, "youSign": { - "message": "서명합니다" + "message": "서명 중입니다." }, "yourPrivateSeedPhrase": { - "message": "개인 시드 구문" + "message": "귀하의 비공개 시드 구문입니다." }, "zeroGasPriceOnSpeedUpError": { - "message": "가속 시 가스 비용 없음" + "message": "가속화 시 Gas 가격 0" } } From 12161bb0c6982ee1f3bfd3906f4a47f58e013ed7 Mon Sep 17 00:00:00 2001 From: Brad Decker Date: Tue, 2 Feb 2021 09:21:56 -0600 Subject: [PATCH 21/48] add Callout component (#10309) --- ui/app/components/ui/callout/callout.js | 65 +++++++++++ ui/app/components/ui/callout/callout.scss | 61 ++++++++++ .../components/ui/callout/callout.stories.js | 107 ++++++++++++++++++ ui/app/components/ui/callout/index.js | 1 + ui/app/components/ui/ui-components.scss | 1 + 5 files changed, 235 insertions(+) create mode 100644 ui/app/components/ui/callout/callout.js create mode 100644 ui/app/components/ui/callout/callout.scss create mode 100644 ui/app/components/ui/callout/callout.stories.js create mode 100644 ui/app/components/ui/callout/index.js diff --git a/ui/app/components/ui/callout/callout.js b/ui/app/components/ui/callout/callout.js new file mode 100644 index 000000000..bc9d4ba62 --- /dev/null +++ b/ui/app/components/ui/callout/callout.js @@ -0,0 +1,65 @@ +import React, { useEffect, useState } from 'react' +import PropTypes from 'prop-types' +import classnames from 'classnames' +import InfoIconInverted from '../icon/info-icon-inverted.component' +import { SEVERITIES } from '../../../helpers/constants/design-system' + +export default function Callout({ + severity, + children, + dismiss, + isFirst, + isLast, + isMultiple, +}) { + const [removed, setRemoved] = useState(false) + const calloutClassName = classnames('callout', `callout--${severity}`, { + 'callout--dismissed': removed === true, + 'callout--multiple': isMultiple === true, + 'callout--dismissible': Boolean(dismiss), + 'callout--first': isFirst === true || isMultiple !== true, + 'callout--last': isLast === true || isMultiple !== true, + }) + // Clicking the close button will set removed state, which will trigger this + // effect to refire due to changing dependencies. When that happens, after a + // half of a second we fire the dismiss method from the parent. The + // consuming component is responsible for modifying state and then removing + // the element from the DOM. + useEffect(() => { + if (removed) { + setTimeout(() => { + dismiss() + }, 500) + } + }, [removed, dismiss]) + return ( +
+ +
{children}
+ {dismiss && ( + { + setRemoved(true) + }} + onKeyUp={(event) => { + if (event.key === 'Enter') { + setRemoved(true) + } + }} + role="button" + tabIndex={0} + className="fas fa-times callout__close-button" + /> + )} +
+ ) +} + +Callout.propTypes = { + severity: PropTypes.oneOf(Object.values(SEVERITIES)).isRequired, + children: PropTypes.node.isRequired, + dismiss: PropTypes.func, + isFirst: PropTypes.bool, + isLast: PropTypes.bool, + isMultiple: PropTypes.bool, +} diff --git a/ui/app/components/ui/callout/callout.scss b/ui/app/components/ui/callout/callout.scss new file mode 100644 index 000000000..b91e03181 --- /dev/null +++ b/ui/app/components/ui/callout/callout.scss @@ -0,0 +1,61 @@ +.callout { + $self: &; + + @include H7; + + padding: 16px; + display: grid; + grid-template-columns: minmax(0, auto) 1fr minmax(0, auto); + grid-template-rows: 1fr; + transition: opacity 0.75s 0s; + + &--dismissible { + &#{$self}--first { + box-shadow: 0 -5px 5px -5px rgba(0, 0, 0, 0.18); + } + } + + &--multiple { + padding-top: 8px; + padding-bottom: 8px; + + &#{$self}--first { + padding-top: 16px; + } + + &#{$self}--last { + padding-bottom: 16px; + } + } + + &--dismissed { + opacity: 0; + } + + &--warning { + border-left: 2px solid $alert-1; + } + + &--danger { + border-left: 2px solid $error-1; + } + + &--info { + border-left: 2px solid $primary-1; + } + + &--success { + border-left: 2px solid $success-1; + } + + & .info-icon { + margin: unset; + margin-right: 10px; + } + + &__close-button { + margin-left: 8px; + background: unset; + cursor: pointer; + } +} diff --git a/ui/app/components/ui/callout/callout.stories.js b/ui/app/components/ui/callout/callout.stories.js new file mode 100644 index 000000000..079d7d10e --- /dev/null +++ b/ui/app/components/ui/callout/callout.stories.js @@ -0,0 +1,107 @@ +import { select } from '@storybook/addon-knobs' +import React, { useState } from 'react' +import { + COLORS, + SEVERITIES, + TYPOGRAPHY, +} from '../../../helpers/constants/design-system' +import Box from '../box' +import Typography from '../typography' +import Callout from './callout' + +export default { + title: 'Callout', +} + +export const persistentCallout = () => ( + + + This is your private key: + + some seed words that are super important and probably deserve a callout + + + + Always back up your private key! + + +) + +export const DismissibleCallout = () => { + const [dismissed, setDismissed] = useState(false) + return ( + + + + This is your private key: + + + some seed words that are super important and probably deserve a + callout + + + {!dismissed && ( + setDismissed(true)} + > + Always back up your private key! + + )} + + ) +} + +const MULTIPLE_CALLOUTS = { + WARN: { + severity: SEVERITIES.WARNING, + content: 'Always back up your private key!', + dismissed: false, + }, + DANGER: { + severity: SEVERITIES.DANGER, + content: 'Never give your private key out, it will lead to loss of funds!', + dismissed: false, + }, +} + +export const MultipleDismissibleCallouts = () => { + const [calloutState, setCalloutState] = useState(MULTIPLE_CALLOUTS) + const dismiss = (id) => { + setCalloutState((prevState) => ({ + ...prevState, + [id]: { + ...prevState[id], + dismissed: true, + }, + })) + } + + return ( + + + + This is your private key: + + + some seed words that are super important and probably deserve a + callout + + + {Object.entries(calloutState) + .filter(([_, callout]) => callout.dismissed === false) + .map(([id, callout], idx, filtered) => ( + dismiss(id)} + isFirst={idx === 0} + isLast={idx + 1 === filtered.length} + isMultiple={filtered.length > 1} + > + {callout.content} + + ))} + + ) +} diff --git a/ui/app/components/ui/callout/index.js b/ui/app/components/ui/callout/index.js new file mode 100644 index 000000000..dc48ad1ac --- /dev/null +++ b/ui/app/components/ui/callout/index.js @@ -0,0 +1 @@ +export { default } from './callout' diff --git a/ui/app/components/ui/ui-components.scss b/ui/app/components/ui/ui-components.scss index f2fd4c5b0..cc8effe24 100644 --- a/ui/app/components/ui/ui-components.scss +++ b/ui/app/components/ui/ui-components.scss @@ -6,6 +6,7 @@ @import 'breadcrumbs/index'; @import 'button-group/index'; @import 'button/buttons'; +@import 'callout/callout'; @import 'card/index'; @import 'check-box/index'; @import 'chip/chip'; From 6a89261f2891f3c4abedb9f0ff0617f4067bc21b Mon Sep 17 00:00:00 2001 From: Thomas Huang Date: Tue, 2 Feb 2021 07:25:30 -0800 Subject: [PATCH 22/48] Reject Trezor eth_getEncryptionPublicKey requests (#10330) Further implements request rejection on eth_getEncryptionPublicKey for Trezor as they do not implement this method either. --- app/scripts/metamask-controller.js | 38 +++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 732db7006..b9d6c598f 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -1645,18 +1645,34 @@ export default class MetamaskController extends EventEmitter { async newRequestEncryptionPublicKey(msgParams, req) { const address = msgParams const keyring = await this.keyringController.getKeyringForAccount(address) - if (keyring.type === 'Ledger Hardware') { - return new Promise((_, reject) => { - reject(new Error('Ledger does not support eth_getEncryptionPublicKey.')) - }) + + switch (keyring.type) { + case 'Ledger Hardware': { + return new Promise((_, reject) => { + reject( + new Error('Ledger does not support eth_getEncryptionPublicKey.'), + ) + }) + } + + case 'Trezor Hardware': { + return new Promise((_, reject) => { + reject( + new Error('Trezor does not support eth_getEncryptionPublicKey.'), + ) + }) + } + + default: { + const promise = this.encryptionPublicKeyManager.addUnapprovedMessageAsync( + msgParams, + req, + ) + this.sendUpdate() + this.opts.showUserConfirmation() + return promise + } } - const promise = this.encryptionPublicKeyManager.addUnapprovedMessageAsync( - msgParams, - req, - ) - this.sendUpdate() - this.opts.showUserConfirmation() - return promise } /** From 96933b3faf1327a023a62bc5e3e1d127d98763ef Mon Sep 17 00:00:00 2001 From: Brad Decker Date: Tue, 2 Feb 2021 12:14:04 -0600 Subject: [PATCH 23/48] add MetaMask Template Renderer (#10307) * add MetaMask Template Renderer * add areEqual fn and change acc var name * use key --- .../app/metamask-template-renderer/index.js | 1 + .../metamask-template-renderer.js | 102 +++++++++++++++++ .../metamask-template-renderer.stories.js | 106 ++++++++++++++++++ .../safe-component-list.js | 21 ++++ 4 files changed, 230 insertions(+) create mode 100644 ui/app/components/app/metamask-template-renderer/index.js create mode 100644 ui/app/components/app/metamask-template-renderer/metamask-template-renderer.js create mode 100644 ui/app/components/app/metamask-template-renderer/metamask-template-renderer.stories.js create mode 100644 ui/app/components/app/metamask-template-renderer/safe-component-list.js diff --git a/ui/app/components/app/metamask-template-renderer/index.js b/ui/app/components/app/metamask-template-renderer/index.js new file mode 100644 index 000000000..b8028d2ce --- /dev/null +++ b/ui/app/components/app/metamask-template-renderer/index.js @@ -0,0 +1 @@ +export { default } from './metamask-template-renderer' diff --git a/ui/app/components/app/metamask-template-renderer/metamask-template-renderer.js b/ui/app/components/app/metamask-template-renderer/metamask-template-renderer.js new file mode 100644 index 000000000..a4af96533 --- /dev/null +++ b/ui/app/components/app/metamask-template-renderer/metamask-template-renderer.js @@ -0,0 +1,102 @@ +import React, { memo } from 'react' +import PropTypes from 'prop-types' +import { isEqual } from 'lodash' +import { safeComponentList } from './safe-component-list' + +function getElement(section) { + const { element } = section + const Element = safeComponentList[element] + if (!Element) { + throw new Error( + `${element} is not in the safe component list for MetaMask template renderer`, + ) + } + return Element +} + +const MetaMaskTemplateRenderer = ({ sections }) => { + if (!sections) { + // If sections is null eject early by returning null + return null + } else if (typeof sections === 'string') { + // React can render strings directly, so return the string + return sections + } else if ( + sections && + typeof sections === 'object' && + !Array.isArray(sections) + ) { + // If dealing with a single entry, then render a single object without key + const Element = getElement(sections) + return ( + + {typeof sections.children === 'object' ? ( + + ) : ( + sections?.children + )} + + ) + } + + // The last case is dealing with an array of objects + return ( + <> + {sections.reduce((allChildren, child) => { + if (typeof child === 'string') { + // React can render strings directly, so push them into the accumulator + allChildren.push(child) + } else { + // If the entry in array is not a string, then it must be a Section. + // Sections are handled by the main function, but must + // be provided a key when a part of an array. + if (!child.key) { + throw new Error( + 'When using array syntax in MetaMask Template Language, you must specify a key for each child of the array', + ) + } + if (typeof child?.children === 'object') { + // If this child has its own children, check if children is an + // object, and in that case use recursion to render. + allChildren.push( + , + ) + } else { + // Otherwise render the element. + const Element = getElement(child) + allChildren.push( + + {child?.children} + , + ) + } + } + return allChildren + }, [])} + + ) +} + +const SectionShape = { + props: PropTypes.object, + element: PropTypes.oneOf(Object.keys(safeComponentList)).isRequired, + key: PropTypes.string, +} + +const ValidChildren = PropTypes.oneOfType([ + PropTypes.string, + PropTypes.shape(SectionShape), + PropTypes.arrayOf( + PropTypes.oneOfType([PropTypes.shape(SectionShape), PropTypes.string]), + ), +]) + +SectionShape.children = ValidChildren + +MetaMaskTemplateRenderer.propTypes = { + sections: ValidChildren, +} + +export default memo(MetaMaskTemplateRenderer, (prevProps, nextProps) => { + return isEqual(prevProps.sections, nextProps.sections) +}) diff --git a/ui/app/components/app/metamask-template-renderer/metamask-template-renderer.stories.js b/ui/app/components/app/metamask-template-renderer/metamask-template-renderer.stories.js new file mode 100644 index 000000000..b0c4dc1a5 --- /dev/null +++ b/ui/app/components/app/metamask-template-renderer/metamask-template-renderer.stories.js @@ -0,0 +1,106 @@ +import React from 'react' +import { object } from '@storybook/addon-knobs' +import { COLORS, TYPOGRAPHY } from '../../../helpers/constants/design-system' +import MetaMaskTemplateRenderer from '.' + +export default { + title: 'MetaMask Template Renderer', +} + +const SECTIONS = { + element: 'Box', + props: { + margin: 4, + padding: 8, + borderColor: COLORS.PRIMARY1, + borderWidth: 2, + }, + children: [ + { + element: 'Typography', + key: 'A Test String', + children: 'A Test String', + props: { + color: COLORS.UI3, + variant: TYPOGRAPHY.H2, + }, + }, + { + element: 'Typography', + key: 'Some more text', + children: 'Some more text as a paragraph', + props: { + color: COLORS.UI4, + variant: TYPOGRAPHY.Paragraph, + }, + }, + { + element: 'TruncatedDefinitionList', + key: 'TDL', + props: { + dictionary: { + term: + 'a word or phrase used to describe a thing or to express a concept, especially in a particular kind of language or branch of study.', + definition: + 'a statement of the exact meaning of a word, especially in a dictionary.', + dl: 'HTML tag denoting a definition list', + dt: 'HTML tag denoting a definition list term', + dd: 'HTML tag denoting a definition list definition', + }, + title: 'Full list', + prefaceKeys: ['term', 'definition'], + }, + }, + { + element: 'Box', + key: 'ActionsBox', + children: [ + { + element: 'Button', + children: 'Cancel', + key: 'cancel-button', + props: { + rounded: true, + type: 'outlined', + style: { + width: '45%', + }, + }, + }, + { + element: 'Button', + children: 'OK', + key: 'ok-button', + props: { + rounded: true, + type: 'primary', + style: { + width: '45%', + }, + }, + }, + ], + props: { justifyContent: 'space-between', padding: [0, 4] }, + }, + ], +} +export const metaMaskTemplateRenderer = () => ( + +) + +export const withInvalidElement = () => ( + +) diff --git a/ui/app/components/app/metamask-template-renderer/safe-component-list.js b/ui/app/components/app/metamask-template-renderer/safe-component-list.js new file mode 100644 index 000000000..fea24c256 --- /dev/null +++ b/ui/app/components/app/metamask-template-renderer/safe-component-list.js @@ -0,0 +1,21 @@ +import Button from '../../ui/button' +import Chip from '../../ui/chip' +import DefinitionList from '../../ui/definition-list' +import TruncatedDefinitionList from '../../ui/truncated-definition-list' +import Popover from '../../ui/popover' +import Typography from '../../ui/typography' +import Box from '../../ui/box' + +export const safeComponentList = { + b: 'b', + p: 'p', + div: 'div', + span: 'span', + Typography, + Chip, + DefinitionList, + TruncatedDefinitionList, + Button, + Popover, + Box, +} From df5f7893911713cdfcec3cd15d8124782c06c39f Mon Sep 17 00:00:00 2001 From: Thomas Huang Date: Tue, 2 Feb 2021 13:14:03 -0800 Subject: [PATCH 24/48] Use nock to intercept gas call for gas-duck test (#10334) * Use nock in to intercept gas call for gas-duck test Use nock instead of stubbing out the window fetch. My suspicion is that when the test runs the window sometimes wouldn't be intialized/referenced, which could explain the intermittent test failures in those particular tests that call window.fetch. Using nock allows the call to be intercepted more reliably. --- ui/app/ducks/gas/gas-duck.test.js | 35 ++++++++++++++++++------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/ui/app/ducks/gas/gas-duck.test.js b/ui/app/ducks/gas/gas-duck.test.js index 519741f25..913fb1168 100644 --- a/ui/app/ducks/gas/gas-duck.test.js +++ b/ui/app/ducks/gas/gas-duck.test.js @@ -1,4 +1,5 @@ import assert from 'assert' +import nock from 'nock' import sinon from 'sinon' import proxyquire from 'proxyquire' @@ -20,35 +21,24 @@ const { const GasReducer = GasDuck.default describe('Gas Duck', function () { - let tempFetch let tempDateNow const mockGasPriceApiResponse = { SafeGasPrice: 10, ProposeGasPrice: 20, FastGasPrice: 30, } - const fakeFetch = () => - new Promise((resolve) => { - const dataToResolve = mockGasPriceApiResponse - resolve({ - json: () => Promise.resolve(dataToResolve), - }) - }) beforeEach(function () { - tempFetch = window.fetch tempDateNow = global.Date.now fakeStorage.getStorageItem = sinon.stub() fakeStorage.setStorageItem = sinon.spy() - window.fetch = sinon.stub().callsFake(fakeFetch) global.Date.now = () => 2000000 }) afterEach(function () { sinon.restore() - window.fetch = tempFetch global.Date.now = tempDateNow }) @@ -166,6 +156,12 @@ describe('Gas Duck', function () { it('should call fetch with the expected params', async function () { const mockDistpatch = sinon.spy() + const windowFetchSpy = sinon.spy(window, 'fetch') + + nock('https://api.metaswap.codefi.network') + .get('/gasPrices') + .reply(200, mockGasPriceApiResponse) + await fetchBasicGasEstimates()(mockDistpatch, () => ({ gas: { ...initState, basicPriceAEstimatesLastRetrieved: 1000000 }, })) @@ -173,7 +169,7 @@ describe('Gas Duck', function () { { type: BASIC_GAS_ESTIMATE_LOADING_STARTED }, ]) assert.ok( - window.fetch + windowFetchSpy .getCall(0) .args[0].startsWith('https://api.metaswap.codefi.network/gasPrices'), 'should fetch metaswap /gasPrices', @@ -198,6 +194,9 @@ describe('Gas Duck', function () { it('should fetch recently retrieved estimates from storage', async function () { const mockDistpatch = sinon.spy() + + const windowFetchSpy = sinon.spy(window, 'fetch') + fakeStorage.getStorageItem .withArgs('BASIC_PRICE_ESTIMATES_LAST_RETRIEVED') .returns(2000000 - 1) // one second ago from "now" @@ -213,7 +212,7 @@ describe('Gas Duck', function () { assert.deepStrictEqual(mockDistpatch.getCall(0).args, [ { type: BASIC_GAS_ESTIMATE_LOADING_STARTED }, ]) - assert.ok(window.fetch.notCalled) + assert.ok(windowFetchSpy.notCalled) assert.deepStrictEqual(mockDistpatch.getCall(1).args, [ { type: SET_BASIC_GAS_ESTIMATE_DATA, @@ -231,6 +230,13 @@ describe('Gas Duck', function () { it('should fallback to network if retrieving estimates from storage fails', async function () { const mockDistpatch = sinon.spy() + + const windowFetchSpy = sinon.spy(window, 'fetch') + + nock('https://api.metaswap.codefi.network') + .get('/gasPrices') + .reply(200, mockGasPriceApiResponse) + fakeStorage.getStorageItem .withArgs('BASIC_PRICE_ESTIMATES_LAST_RETRIEVED') .returns(2000000 - 1) // one second ago from "now" @@ -242,11 +248,12 @@ describe('Gas Duck', function () { { type: BASIC_GAS_ESTIMATE_LOADING_STARTED }, ]) assert.ok( - window.fetch + windowFetchSpy .getCall(0) .args[0].startsWith('https://api.metaswap.codefi.network/gasPrices'), 'should fetch metaswap /gasPrices', ) + assert.deepStrictEqual(mockDistpatch.getCall(1).args, [ { type: SET_BASIC_PRICE_ESTIMATES_LAST_RETRIEVED, value: 2000000 }, ]) From b98cef16afe7101cf0484ae69af8f31b3dce687f Mon Sep 17 00:00:00 2001 From: kumavis Date: Wed, 3 Feb 2021 13:45:38 +0800 Subject: [PATCH 25/48] Update to Node v14 (#9514) * manual rebase against develop * Update .nvmrc --- .circleci/config.yml | 19 +- .circleci/scripts/chrome-install.sh | 19 ++ .circleci/scripts/create-sesify-viz | 13 - .circleci/scripts/deps-install.sh | 1 - .nvmrc | 2 +- development/build/scripts.js | 56 ----- development/metamaskbot-build-announce.js | 5 - package.json | 9 +- test/unit-global/frozenPromise.js | 2 +- yarn.lock | 294 ++-------------------- 10 files changed, 56 insertions(+), 364 deletions(-) create mode 100755 .circleci/scripts/chrome-install.sh delete mode 100755 .circleci/scripts/create-sesify-viz diff --git a/.circleci/config.yml b/.circleci/config.yml index e0407f18b..c2c7f8a46 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -3,10 +3,10 @@ version: 2.1 executors: node-browsers: docker: - - image: circleci/node@sha256:e16740707de2ebed45c05d507f33ef204902349c7356d720610b5ec6a35d3d88 + - image: circleci/node:14-browsers node-browsers-medium-plus: docker: - - image: circleci/node@sha256:e16740707de2ebed45c05d507f33ef204902349c7356d720610b5ec6a35d3d88 + - image: circleci/node:14-browsers resource_class: medium+ environment: NODE_OPTIONS: --max_old_space_size=2048 @@ -262,6 +262,9 @@ jobs: executor: node-browsers steps: - checkout + - run: + name: Re-Install Chrome + command: ./.circleci/scripts/chrome-install.sh - attach_workspace: at: . - run: @@ -286,6 +289,9 @@ jobs: executor: node-browsers steps: - checkout + - run: + name: Re-Install Chrome + command: ./.circleci/scripts/chrome-install.sh - attach_workspace: at: . - run: @@ -364,6 +370,9 @@ jobs: executor: node-browsers steps: - checkout + - run: + name: Re-Install Chrome + command: ./.circleci/scripts/chrome-install.sh - attach_workspace: at: . - run: @@ -404,12 +413,6 @@ jobs: - store_artifacts: path: test-artifacts destination: test-artifacts - # important: generate sesify viz AFTER uploading builds as artifacts - # Temporarily disabled until we can update to a version of `sesify` with - # this fix included: https://github.com/LavaMoat/LavaMoat/pull/121 - # - run: - # name: build:sesify-viz - # command: ./.circleci/scripts/create-sesify-viz - store_artifacts: path: build-artifacts destination: build-artifacts diff --git a/.circleci/scripts/chrome-install.sh b/.circleci/scripts/chrome-install.sh new file mode 100755 index 000000000..491e8c3ed --- /dev/null +++ b/.circleci/scripts/chrome-install.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash + +set -e +set -u +set -o pipefail + +CHROME_VERSION='79.0.3945.117-1' +CHROME_BINARY="google-chrome-stable_${CHROME_VERSION}_amd64.deb" +CHROME_BINARY_URL="http://dl.google.com/linux/chrome/deb/pool/main/g/google-chrome-stable/${CHROME_BINARY}" + +wget -O "${CHROME_BINARY}" -t 5 "${CHROME_BINARY_URL}" + +(sudo dpkg -i "${CHROME_BINARY}" || sudo apt-get -fy install) + +rm -rf "${CHROME_BINARY}" + +sudo sed -i 's|HERE/chrome"|HERE/chrome" --disable-setuid-sandbox --no-sandbox|g' "/opt/google/chrome/google-chrome" + +printf '%s\n' "CHROME ${CHROME_VERSION} configured" diff --git a/.circleci/scripts/create-sesify-viz b/.circleci/scripts/create-sesify-viz deleted file mode 100755 index 33dc0bc72..000000000 --- a/.circleci/scripts/create-sesify-viz +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env bash - -set -x -set -e -set -u -set -o pipefail - -# prepare artifacts dir -mkdir -p ./build-artifacts/deps-viz/ - -# generate viz -SESIFY_AUTOGEN=1 yarn build scripts:core:prod:background -npx sesify-viz --deps sesify/deps-background.json --config sesify/background.json --dest ./build-artifacts/deps-viz/background \ No newline at end of file diff --git a/.circleci/scripts/deps-install.sh b/.circleci/scripts/deps-install.sh index 9e1c36c4e..06b4748a9 100755 --- a/.circleci/scripts/deps-install.sh +++ b/.circleci/scripts/deps-install.sh @@ -16,5 +16,4 @@ then fi # use @lavamoat/allow-scripts instead of manually running install scripts so directory change does not persist - yarn allow-scripts diff --git a/.nvmrc b/.nvmrc index 1de6ab5e2..958b5a36e 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -v10.18.1 +v14 diff --git a/development/build/scripts.js b/development/build/scripts.js index ae1a3472c..8a54c9b33 100644 --- a/development/build/scripts.js +++ b/development/build/scripts.js @@ -1,4 +1,3 @@ -const fs = require('fs') const gulp = require('gulp') const watch = require('gulp-watch') const pify = require('pify') @@ -11,9 +10,7 @@ const watchify = require('watchify') const browserify = require('browserify') const envify = require('loose-envify/custom') const sourcemaps = require('gulp-sourcemaps') -const sesify = require('sesify') const terser = require('gulp-terser-js') -const { makeStringTransform } = require('browserify-transform-tools') const conf = require('rc')('metamask', { INFURA_PROJECT_ID: process.env.INFURA_PROJECT_ID, @@ -277,44 +274,6 @@ function createScriptTasks({ browserPlatforms, livereload }) { } } - function configureBundleForSesify({ browserifyOpts, bundleName }) { - // add in sesify args for better globalRef usage detection - Object.assign(browserifyOpts, sesify.args) - - // ensure browserify uses full paths - browserifyOpts.fullPaths = true - - // record dependencies used in bundle - fs.mkdirSync('./sesify', { recursive: true }) - browserifyOpts.plugin.push([ - 'deps-dump', - { - filename: `./sesify/deps-${bundleName}.json`, - }, - ]) - - const sesifyConfigPath = `./sesify/${bundleName}.json` - - // add sesify plugin - browserifyOpts.plugin.push([ - sesify, - { - writeAutoConfig: sesifyConfigPath, - }, - ]) - - // remove html comments that SES is alergic to - const removeHtmlComment = makeStringTransform( - 'remove-html-comment', - { excludeExtension: ['.json'] }, - (content, _, cb) => { - const result = content.split('-->').join('-- >') - cb(null, result) - }, - ) - browserifyOpts.transform.push([removeHtmlComment, { global: true }]) - } - function generateBundler(opts, performBundle) { const browserifyOpts = assign({}, watchify.args, { plugin: [], @@ -323,21 +282,6 @@ function createScriptTasks({ browserPlatforms, livereload }) { fullPaths: opts.devMode, }) - const bundleName = opts.filename.split('.')[0] - - // activate sesify - const activateAutoConfig = Boolean(process.env.SESIFY_AUTOGEN) - // const activateSesify = activateAutoConfig - const activateSesify = - activateAutoConfig && ['background'].includes(bundleName) - if (activateSesify) { - configureBundleForSesify({ browserifyOpts, bundleName }) - } - - if (!activateSesify) { - browserifyOpts.plugin.push('browserify-derequire') - } - if (!opts.buildLib) { if (opts.devMode && opts.filename === 'ui.js') { browserifyOpts.entries = [ diff --git a/development/metamaskbot-build-announce.js b/development/metamaskbot-build-announce.js index 1bea36d73..d029e4fc5 100755 --- a/development/metamaskbot-build-announce.js +++ b/development/metamaskbot-build-announce.js @@ -58,10 +58,6 @@ async function start() { const coverageUrl = `${BUILD_LINK_BASE}/coverage/index.html` const coverageLink = `Report` - // links to bundle browser builds - const depVizUrl = `${BUILD_LINK_BASE}/build-artifacts/deps-viz/background/index.html` - const depVizLink = `background` - // link to artifacts const allArtifactsUrl = `https://circleci.com/gh/MetaMask/metamask-extension/${CIRCLE_BUILD_NUM}#artifacts/containers/0` @@ -69,7 +65,6 @@ async function start() { `builds: ${buildLinks}`, `bundle viz: ${bundleLinks}`, `code coverage: ${coverageLink}`, - `dep viz: ${depVizLink}`, `all artifacts`, ] const hiddenContent = `
    ${contentRows diff --git a/package.json b/package.json index 836898210..c731fbfe4 100644 --- a/package.json +++ b/package.json @@ -119,7 +119,7 @@ "ethereumjs-abi": "^0.6.4", "ethereumjs-tx": "1.3.7", "ethereumjs-util": "5.1.0", - "ethereumjs-wallet": "^0.6.0", + "ethereumjs-wallet": "^0.6.4", "ethers": "^5.0.8", "ethjs": "^0.4.0", "ethjs-contract": "^0.2.3", @@ -168,7 +168,7 @@ "redux": "^4.0.5", "redux-thunk": "^2.3.0", "reselect": "^3.0.1", - "rpc-cap": "^3.2.0", + "rpc-cap": "^3.2.1", "safe-event-emitter": "^1.0.1", "safe-json-stringify": "^1.2.0", "single-call-balance-checker-abi": "^1.0.0", @@ -210,7 +210,6 @@ "brfs": "^2.0.2", "browserify": "^16.5.1", "browserify-derequire": "^1.0.1", - "browserify-transform-tools": "^1.7.0", "chai": "^4.1.0", "chalk": "^3.0.0", "chromedriver": "^79.0.0", @@ -280,8 +279,6 @@ "selenium-webdriver": "4.0.0-alpha.7", "serve-handler": "^6.1.2", "ses": "0.11.0", - "sesify": "^4.2.1", - "sesify-viz": "^3.0.10", "sinon": "^9.0.0", "source-map": "^0.7.2", "source-map-explorer": "^2.4.2", @@ -296,7 +293,7 @@ "webpack": "^4.41.6" }, "engines": { - "node": "^10.18.1", + "node": "^14.15.1", "yarn": "^1.16.0" }, "lavamoat": { diff --git a/test/unit-global/frozenPromise.js b/test/unit-global/frozenPromise.js index 1a1ca18b5..427d7ffb9 100644 --- a/test/unit-global/frozenPromise.js +++ b/test/unit-global/frozenPromise.js @@ -1,6 +1,6 @@ // Should occur before anything else import './globalPatch' -import 'ses/dist/lockdown.cjs' +import 'ses/lockdown' import '../../app/scripts/runLockdown' import assert from 'assert' /* eslint-disable-line import/first,import/order */ diff --git a/yarn.lock b/yarn.lock index ee2ea4787..f937017d1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2036,35 +2036,7 @@ resolved "https://registry.yarnpkg.com/@metamask/contract-metadata/-/contract-metadata-1.22.0.tgz#55cc84756c703c433176b484b1d34f0e03d16d1e" integrity sha512-t4ijbU+4OH9UAlrPkfLPFo6KmkRTRZJHB+Vly4ajF8oZMnota5YjVVl/SmltsoRC9xvJtRn9DUVf3YMHMIdofw== -"@metamask/controllers@^3.1.0": - version "3.2.0" - resolved "https://registry.yarnpkg.com/@metamask/controllers/-/controllers-3.2.0.tgz#8ad2e63f7953d294712d9b5bacaea1c5261ce588" - integrity sha512-Nysutcny5ddsr4eP4XvYuNMAwMqvCO/krughnNUzT69LljslutJyxS2MnT0MnWyKYNa6+CBaV9gxdV+Mm6fAFA== - dependencies: - await-semaphore "^0.1.3" - eth-contract-metadata "^1.11.0" - eth-ens-namehash "^2.0.8" - eth-json-rpc-infura "^5.1.0" - eth-keyring-controller "^5.6.1" - eth-method-registry "1.1.0" - eth-phishing-detect "^1.1.13" - eth-query "^2.1.2" - eth-rpc-errors "^3.0.0" - eth-sig-util "^2.3.0" - ethereumjs-util "^6.1.0" - ethereumjs-wallet "0.6.0" - ethjs-query "^0.3.8" - human-standard-collectible-abi "^1.0.2" - human-standard-token-abi "^2.0.0" - isomorphic-fetch "^3.0.0" - jsonschema "^1.2.4" - percentile "^1.2.1" - single-call-balance-checker-abi "^1.0.0" - uuid "^3.3.2" - web3 "^0.20.7" - web3-provider-engine "^16.0.1" - -"@metamask/controllers@^5.1.0": +"@metamask/controllers@^5.0.0", "@metamask/controllers@^5.1.0": version "5.1.0" resolved "https://registry.yarnpkg.com/@metamask/controllers/-/controllers-5.1.0.tgz#02c1957295bcb6db1655a716d165665d170e7f34" integrity sha512-4piqkIrpphe+9nEy68WH+yBw9wsXZyCMVeBZeRtliVHAJFXUdz+KZDUi/R1Y+568JBzqAvsOtOzbUIU4btD3Fw== @@ -3480,7 +3452,7 @@ optionalDependencies: text-encoding "^0.6.4" -JSONStream@^1.0.3, JSONStream@^1.3.5: +JSONStream@^1.0.3: version "1.3.5" resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.5.tgz#3208c1f08d3a4d99261ab64f92302bc15e111ca0" integrity sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ== @@ -3583,7 +3555,7 @@ acorn-dynamic-import@^4.0.0: resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-4.0.0.tgz#482210140582a36b83c3e342e1cfebcaa9240948" integrity sha512-d3OEjQV4ROpoflsnUA8HozoIR504TFxNivYEUi6uwz0IYhBkTDXGuWlNdMtybRt3nqVx/L6XqMt0FxkXuWKZhw== -acorn-globals@^4.0.0, acorn-globals@^4.3.3: +acorn-globals@^4.0.0: version "4.3.4" resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-4.3.4.tgz#9fa1926addc11c97308c4e66d7add0d40c3272e7" integrity sha512-clfQEh21R+D0leSbUdWf3OcfqyaCSAQ8Ryq00bofSekfr9W8u1jyYZo6ir0xu9Gtcf7BjcHJpnbZH7JOCpP60A== @@ -3613,12 +3585,12 @@ acorn-node@^1.2.0, acorn-node@^1.3.0, acorn-node@^1.5.2: acorn-walk "^6.1.0" xtend "^4.0.1" -acorn-walk@^6.0.1, acorn-walk@^6.1.0, acorn-walk@^6.1.1: +acorn-walk@^6.0.1, acorn-walk@^6.1.0: version "6.2.0" resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-6.2.0.tgz#123cb8f3b84c2171f1f7fb252615b1c78a6b1a8c" integrity sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA== -acorn@5.X, acorn@^5.0.0, acorn@^5.0.3, acorn@^5.1.2, acorn@^5.2.1: +acorn@5.X, acorn@^5.0.3, acorn@^5.1.2, acorn@^5.2.1: version "5.7.4" resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.4.tgz#3e8d8a9947d0599a1796d10225d7432f4a4acf5e" integrity sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg== @@ -3704,11 +3676,6 @@ aes-js@3.0.0: resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" integrity sha1-4h3xCtbCBTKVvLuNq0Cwnb6ofk0= -aes-js@^0.2.3: - version "0.2.4" - resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-0.2.4.tgz#94b881ab717286d015fa219e08fb66709dda5a3d" - integrity sha1-lLiBq3FyhtAV+iGeCPtmcJ3aWj0= - aes-js@^3.1.1: version "3.1.2" resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.1.2.tgz#db9aabde85d5caabbfc0d4f2a4446960f627146a" @@ -5540,11 +5507,6 @@ base-x@3.0.8: dependencies: safe-buffer "^5.0.1" -base-x@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/base-x/-/base-x-1.1.0.tgz#42d3d717474f9ea02207f6d1aa1f426913eeb7ac" - integrity sha1-QtPXF0dPnqAiB/bRqh9CaRPut6w= - base32-encode@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/base32-encode/-/base32-encode-1.1.1.tgz#d022d86aca0002a751bbe1bf20eb4a9b1cef4e95" @@ -6165,14 +6127,6 @@ browserify-sign@^4.0.0: inherits "^2.0.1" parse-asn1 "^5.0.0" -browserify-transform-tools@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/browserify-transform-tools/-/browserify-transform-tools-1.7.0.tgz#83e277221f63259bed2e7eb2a283a970a501f4c4" - integrity sha1-g+J3Ih9jJZvtLn6yooOpcKUB9MQ= - dependencies: - falafel "^2.0.0" - through "^2.3.7" - browserify-unibabel@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/browserify-unibabel/-/browserify-unibabel-3.0.0.tgz#5a6b8f0f704ce388d3927df47337e25830f71dda" @@ -6285,13 +6239,6 @@ bs58@^2.0.1: resolved "https://registry.yarnpkg.com/bs58/-/bs58-2.0.1.tgz#55908d58f1982aba2008fa1bed8f91998a29bf8d" integrity sha1-VZCNWPGYKrogCPob7Y+RmYopv40= -bs58@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/bs58/-/bs58-3.1.0.tgz#d4c26388bf4804cac714141b1945aa47e5eb248e" - integrity sha1-1MJjiL9IBMrHFBQbGUWqR+XrJI4= - dependencies: - base-x "^1.1.0" - bs58check@<3.0.0, bs58check@^2.0.0, bs58check@^2.1.1, bs58check@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/bs58check/-/bs58check-2.1.2.tgz#53b018291228d82a5aa08e7d796fdafda54aebfc" @@ -6301,14 +6248,6 @@ bs58check@<3.0.0, bs58check@^2.0.0, bs58check@^2.1.1, bs58check@^2.1.2: create-hash "^1.1.0" safe-buffer "^5.1.2" -bs58check@^1.0.8: - version "1.3.4" - resolved "https://registry.yarnpkg.com/bs58check/-/bs58check-1.3.4.tgz#c52540073749117714fa042c3047eb8f9151cbf8" - integrity sha1-xSVABzdJEXcU+gQsMEfrj5FRy/g= - dependencies: - bs58 "^3.1.0" - create-hash "^1.1.0" - btoa@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/btoa/-/btoa-1.2.1.tgz#01a9909f8b2c93f6bf680ba26131eb30f7fa3d73" @@ -7152,17 +7091,6 @@ clone-buffer@^1.0.0: resolved "https://registry.yarnpkg.com/clone-buffer/-/clone-buffer-1.0.0.tgz#e3e25b207ac4e701af721e2cb5a16792cac3dc58" integrity sha1-4+JbIHrE5wGvch4staFnksrD3Fg= -clone-deep@^0.2.4: - version "0.2.4" - resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-0.2.4.tgz#4e73dd09e9fb971cc38670c5dced9c1896481cc6" - integrity sha1-TnPdCen7lxzDhnDF3O2cGJZIHMY= - dependencies: - for-own "^0.1.3" - is-plain-object "^2.0.1" - kind-of "^3.0.2" - lazy-cache "^1.0.3" - shallow-clone "^0.1.2" - clone-deep@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-2.0.2.tgz#00db3a1e173656730d1188c3d6aced6d7ea97713" @@ -9958,11 +9886,6 @@ eth-block-tracker@^4.4.2: pify "^3.0.0" safe-event-emitter "^1.0.1" -eth-contract-metadata@^1.11.0: - version "1.17.0" - resolved "https://registry.yarnpkg.com/eth-contract-metadata/-/eth-contract-metadata-1.17.0.tgz#96d4b056ac9a7175eeba091dbabd0713cfd4c703" - integrity sha512-vlw4OiW3+9J3kJfEtPCyiSW9fhdWTqrAhXcvdMY2CevGxbhvOd5Lz59DeWerSTV3IoSXttghDurPA76dAeTV+A== - eth-ens-namehash@2.0.8, eth-ens-namehash@^2.0.8: version "2.0.8" resolved "https://registry.yarnpkg.com/eth-ens-namehash/-/eth-ens-namehash-2.0.8.tgz#229ac46eca86d52e0c991e7cb2aef83ff0f68bcf" @@ -10062,21 +9985,6 @@ eth-json-rpc-middleware@^6.0.0: pify "^3.0.0" safe-event-emitter "^1.0.1" -eth-keyring-controller@^5.6.1: - version "5.6.1" - resolved "https://registry.yarnpkg.com/eth-keyring-controller/-/eth-keyring-controller-5.6.1.tgz#7b7268400704c8f5ce98a055910341177dd207ca" - integrity sha512-sxJ87bJg7PvvPzj1sY1jJYHQL1HVUhh84Q/a4QPrcnzAAng1yibvvUfww0pCez4XJfHuMkJvUxfF8eAusJM8fQ== - dependencies: - bip39 "^2.4.0" - bluebird "^3.5.0" - browser-passworder "^2.0.3" - eth-hd-keyring "^3.5.0" - eth-sig-util "^1.4.0" - eth-simple-keyring "^3.5.0" - ethereumjs-util "^5.1.2" - loglevel "^1.5.0" - obs-store "^4.0.3" - eth-keyring-controller@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/eth-keyring-controller/-/eth-keyring-controller-6.1.0.tgz#dc9313d0b793e085dc1badf84dd4f5e3004e127e" @@ -10172,7 +10080,7 @@ eth-sig-util@^1.4.0, eth-sig-util@^1.4.2: ethereumjs-abi "git+https://github.com/ethereumjs/ethereumjs-abi.git" ethereumjs-util "^5.1.1" -eth-sig-util@^2.0.0, eth-sig-util@^2.3.0, eth-sig-util@^2.4.4, eth-sig-util@^2.5.0: +eth-sig-util@^2.0.0, eth-sig-util@^2.4.4, eth-sig-util@^2.5.0: version "2.5.3" resolved "https://registry.yarnpkg.com/eth-sig-util/-/eth-sig-util-2.5.3.tgz#6938308b38226e0b3085435474900b03036abcbe" integrity sha512-KpXbCKmmBUNUTGh9MRKmNkIPietfhzBqqYqysDavLseIiMUGl95k6UcPEkALAZlj41e9E6yioYXc1PC333RKqw== @@ -10417,7 +10325,7 @@ ethereumjs-util@6.2.1, ethereumjs-util@^6.0.0, ethereumjs-util@^6.1.0, ethereumj ethjs-util "0.1.6" rlp "^2.2.3" -ethereumjs-util@^4.0.1, ethereumjs-util@^4.3.0, ethereumjs-util@^4.4.0: +ethereumjs-util@^4.0.1, ethereumjs-util@^4.3.0: version "4.5.0" resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-4.5.0.tgz#3e9428b317eebda3d7260d854fddda954b1f1bc6" integrity sha1-PpQosxfuvaPXJg2FT93alUsfG8Y= @@ -10492,19 +10400,6 @@ ethereumjs-vm@^2.1.0, ethereumjs-vm@^2.3.4, ethereumjs-vm@^2.6.0: rustbn.js "~0.2.0" safe-buffer "^5.1.1" -ethereumjs-wallet@0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/ethereumjs-wallet/-/ethereumjs-wallet-0.6.0.tgz#82763b1697ee7a796be7155da9dfb49b2f98cfdb" - integrity sha1-gnY7Fpfuenlr5xVdqd+0my+Yz9s= - dependencies: - aes-js "^0.2.3" - bs58check "^1.0.8" - ethereumjs-util "^4.4.0" - hdkey "^0.7.0" - scrypt.js "^0.2.0" - utf8 "^2.1.1" - uuid "^2.0.1" - ethereumjs-wallet@0.6.5, ethereumjs-wallet@^0.6.0, ethereumjs-wallet@^0.6.4: version "0.6.5" resolved "https://registry.yarnpkg.com/ethereumjs-wallet/-/ethereumjs-wallet-0.6.5.tgz#685e9091645cee230ad125c007658833991ed474" @@ -11095,16 +10990,6 @@ fake-merkle-patricia-tree@^1.0.1: dependencies: checkpoint-store "^1.1.0" -falafel@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/falafel/-/falafel-2.1.0.tgz#96bb17761daba94f46d001738b3cedf3a67fe06c" - integrity sha1-lrsXdh2rqU9G0AFzizzt86Z/4Gw= - dependencies: - acorn "^5.0.0" - foreach "^2.0.5" - isarray "0.0.1" - object-keys "^1.0.6" - fancy-log@1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/fancy-log/-/fancy-log-1.3.2.tgz#f41125e3d84f2e7d89a43d06d958c8f78be16be1" @@ -11661,7 +11546,7 @@ for-in@^1.0.1, for-in@^1.0.2: resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= -for-own@^0.1.3, for-own@^0.1.4: +for-own@^0.1.4: version "0.1.5" resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce" integrity sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4= @@ -11675,11 +11560,6 @@ for-own@^1.0.0: dependencies: for-in "^1.0.1" -foreach@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99" - integrity sha1-C+4AUBiusmDQo6865ljdATbsG5k= - foreground-child@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-2.0.0.tgz#71b32800c9f15aa8f2f83f4a6bd9bff35d861a53" @@ -11778,7 +11658,7 @@ from@~0: resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe" integrity sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4= -fromentries@^1.1.0, fromentries@^1.2.0: +fromentries@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/fromentries/-/fromentries-1.2.0.tgz#e6aa06f240d6267f913cea422075ef88b63e7897" integrity sha512-33X7H/wdfO99GdRLLgkjUrD4geAFdq/Uv0kl3HD4da6HDixd2GUg8Mw7dahLCV9r/EARkmtYBB6Tch4EEokFTQ== @@ -13198,14 +13078,6 @@ hdkey@0.8.0: safe-buffer "^5.1.1" secp256k1 "^3.0.1" -hdkey@^0.7.0: - version "0.7.1" - resolved "https://registry.yarnpkg.com/hdkey/-/hdkey-0.7.1.tgz#caee4be81aa77921e909b8d228dd0f29acaee632" - integrity sha1-yu5L6BqneSHpCbjSKN0PKayu5jI= - dependencies: - coinstring "^2.0.0" - secp256k1 "^3.0.1" - he@1.2.0, he@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" @@ -14554,7 +14426,7 @@ is-boolean-object@^1.0.0: resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.0.0.tgz#98f8b28030684219a95f375cfbd88ce3405dff93" integrity sha1-mPiygDBoQhmpXzdc+9iM40Bd/5M= -is-buffer@^1.0.2, is-buffer@^1.1.0, is-buffer@^1.1.5, is-buffer@~1.1.6: +is-buffer@^1.1.0, is-buffer@^1.1.5, is-buffer@~1.1.6: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== @@ -15910,13 +15782,6 @@ kind-of@^1.1.0: resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-1.1.0.tgz#140a3d2d41a36d2efcfa9377b62c24f8495a5c44" integrity sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ= -kind-of@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-2.0.1.tgz#018ec7a4ce7e3a86cb9141be519d24c8faa981b5" - integrity sha1-AY7HpM5+OobLkUG+UZ0kyPqpgbU= - dependencies: - is-buffer "^1.0.2" - kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: version "3.2.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" @@ -16076,16 +15941,6 @@ latest-version@^5.0.0: dependencies: package-json "^6.3.0" -lazy-cache@^0.2.3: - version "0.2.7" - resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-0.2.7.tgz#7feddf2dcb6edb77d11ef1d117ab5ffdf0ab1b65" - integrity sha1-f+3fLctu23fRHvHRF6tf/fCrG2U= - -lazy-cache@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e" - integrity sha1-odePw6UEdMuAhF07O24dpJpEbo4= - lazy-universal-dotenv@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/lazy-universal-dotenv/-/lazy-universal-dotenv-3.0.1.tgz#a6c8938414bca426ab8c9463940da451a911db38" @@ -17572,15 +17427,6 @@ meow@^7.0.1: type-fest "^0.13.1" yargs-parser "^18.1.3" -merge-deep@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/merge-deep/-/merge-deep-3.0.2.tgz#f39fa100a4f1bd34ff29f7d2bf4508fbb8d83ad2" - integrity sha512-T7qC8kg4Zoti1cFd8Cr0M+qaZfOwjlPDEdZIIPPB2JZctjaPM4fX+i7HOId69tAti2fvO6X5ldfYUONDODsrkA== - dependencies: - arr-union "^3.1.0" - clone-deep "^0.2.4" - kind-of "^3.0.2" - merge-descriptors@1.0.1, merge-descriptors@~1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" @@ -17987,10 +17833,6 @@ module-deps@^6.0.0: through2 "^2.0.0" xtend "^4.0.0" -"module-name-from-path@git+https://git@github.com/kumavis/module-name-from-path.git": - version "1.0.4" - resolved "git+https://git@github.com/kumavis/module-name-from-path.git#fd9c592663a1af6cc48b1be7b8045ea547fca79a" - module-not-found-error@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/module-not-found-error/-/module-not-found-error-1.0.1.tgz#cf8b4ff4f29640674d6cdd02b0e3bc523c2bbdc0" @@ -18247,7 +18089,7 @@ nan@2.13.2: resolved "https://registry.yarnpkg.com/nan/-/nan-2.13.2.tgz#f51dc7ae66ba7d5d55e1e6d4d8092e802c9aefe7" integrity sha512-TghvYc72wlMGMVMluVo9WRJc0mB8KxxF/gZ4YYFy7V2ZQX9l7rgbPg7vjS9mt6U5HXODVFVI2bOduCzwOMv/lw== -nan@^2.0.5, nan@^2.0.8, nan@^2.11.1, nan@^2.12.1, nan@^2.13.2, nan@^2.14.0, nan@^2.2.1: +nan@^2.0.5, nan@^2.11.1, nan@^2.12.1, nan@^2.13.2, nan@^2.14.0, nan@^2.2.1: version "2.14.0" resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c" integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg== @@ -18319,11 +18161,6 @@ ncom@^1.0.2: dependencies: sc-formatter "~3.0.1" -ncp@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ncp/-/ncp-2.0.0.tgz#195a21d6c46e361d2fb1281ba38b91e9df7bdbb3" - integrity sha1-GVoh1sRuNh0vsSgbo4uR6d9727M= - "ndjson@github:hugomrdias/ndjson#feat/readable-stream3": version "1.5.0" resolved "https://codeload.github.com/hugomrdias/ndjson/tar.gz/4db16da6b42e5b39bf300c3a7cde62abb3fa3a11" @@ -18920,7 +18757,7 @@ object-is@^1.0.1: resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.0.1.tgz#0aa60ec9989a0b3ed795cf4d06f62cf1ad6539b6" integrity sha1-CqYOyZiaCz7Xlc9NBvYs8a1lObY= -object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.0.6, object-keys@^1.1.1: +object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== @@ -19062,13 +18899,6 @@ observable-webworkers@^1.0.0: resolved "https://registry.yarnpkg.com/observable-webworkers/-/observable-webworkers-1.0.0.tgz#dcbd484a9644d512accc351962c6e710313fbb68" integrity sha512-+cECwCR8IEh8UY5nefQVLO9Cydqpk1izO+o7BABmKjXfJZyEOzBWY3ss5jbOPM6KmEa9aQExvAtTW6tVTOsNAQ== -offset-sourcemap-lines@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/offset-sourcemap-lines/-/offset-sourcemap-lines-1.0.1.tgz#5854dff74b73fc06efcb61d7b721a8113d99be92" - integrity sha1-WFTf90tz/Abvy2HXtyGoET2ZvpI= - dependencies: - source-map "^0.5.0" - on-finished@^2.3.0, on-finished@~2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" @@ -20096,11 +19926,6 @@ pend@~1.2.0: resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" integrity sha1-elfrVQpng/kRUzH89GY9XI4AelA= -percentile@^1.2.1: - version "1.2.2" - resolved "https://registry.yarnpkg.com/percentile/-/percentile-1.2.2.tgz#8966abc4bb36aaacaee91405f17095d9c881d1cb" - integrity sha512-yb/W/Y3WNxEZ6/P75qkAvE3lu81AO1qDk95j7jPJg4Vj+wDWSDs0CMLVGoAUCOZbXOUOz3b3rWWR6Bf1hyzNJg== - performance-now@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-0.2.0.tgz#33ef30c5c77d4ea21c5a53869d91b56d8f2555e5" @@ -22543,14 +22368,6 @@ resolve-options@^1.1.0: dependencies: value-or-function "^3.0.0" -resolve-package-path@^1.2.7: - version "1.2.7" - resolved "https://registry.yarnpkg.com/resolve-package-path/-/resolve-package-path-1.2.7.tgz#2a7bc37ad96865e239330e3102c31322847e652e" - integrity sha512-fVEKHGeK85bGbVFuwO9o1aU0n3vqQGrezPc51JGu9UTXpFQfWq5qCeKxyaRUSvephs+06c5j5rPq/dzHGEo8+Q== - dependencies: - path-root "^0.1.1" - resolve "^1.10.0" - resolve-pathname@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/resolve-pathname/-/resolve-pathname-3.0.0.tgz#99d02224d3cf263689becbb393bc560313025dcd" @@ -22779,12 +22596,12 @@ roarr@^2.15.3: semver-compare "^1.0.0" sprintf-js "^1.1.2" -rpc-cap@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/rpc-cap/-/rpc-cap-3.2.0.tgz#304b31c4c7ae65e88b8d847045d7514563045d0c" - integrity sha512-RX9ECQfstggmHEN1hzCp9NdSKl4Ct3EAn+HworDU4bfpCl20EEDZAipVXUpqxKqFrNEU6mzH0BRqHmPCUix9qA== +rpc-cap@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/rpc-cap/-/rpc-cap-3.2.1.tgz#95aba886c60562626261667d3637f9b4fe05b078" + integrity sha512-aNevLIJ/jIGR3by0b3pd7MWBUSJOkbOkjOCZ13Kk2ddToGZV1TaxclBsasLIdomFbxl0lyUQ8EeoMwYrS7yuBA== dependencies: - "@metamask/controllers" "^3.1.0" + "@metamask/controllers" "^5.0.0" eth-rpc-errors "^3.0.0" is-subset "^0.1.1" json-rpc-engine "^5.3.0" @@ -23099,21 +22916,6 @@ scrypt-js@3.0.1, scrypt-js@^3.0.0, scrypt-js@^3.0.1: resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-3.0.1.tgz#d314a57c2aef69d1ad98a138a21fe9eafa9ee312" integrity sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA== -scrypt.js@^0.2.0: - version "0.2.1" - resolved "https://registry.yarnpkg.com/scrypt.js/-/scrypt.js-0.2.1.tgz#cc3f751933d6bac7a4bedf5301d7596e8146cdcd" - integrity sha512-XMoqxwABdotuW+l+qACmJ/h0kVSCgMPZXpbncA/zyBO90z/NnDISzVw+xJ4tUY+X/Hh0EFT269OYHm26VCPgmA== - dependencies: - scrypt "^6.0.2" - scryptsy "^1.2.1" - -scrypt@^6.0.2: - version "6.0.3" - resolved "https://registry.yarnpkg.com/scrypt/-/scrypt-6.0.3.tgz#04e014a5682b53fa50c2d5cce167d719c06d870d" - integrity sha1-BOAUpWgrU/pQwtXM4WfXGcBthw0= - dependencies: - nan "^2.0.8" - scryptsy@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/scryptsy/-/scryptsy-1.2.1.tgz#a3225fa4b2524f802700761e2855bdf3b2d92163" @@ -23353,45 +23155,6 @@ ses@0.11.0: "@agoric/make-hardener" "^0.1.0" "@agoric/transform-module" "^0.4.1" -sesify-tofu@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/sesify-tofu/-/sesify-tofu-2.0.4.tgz#b31d4c8d67ea2d61e9c5be4948f085a849f3e632" - integrity sha512-8mWENwqoWauYrtUVww4/QE5mFjj+2JjvVdMWqjcfOZkt3SjOACy+S0ZnxOn06NYpW6epRaPYIqoIF8SdhvXjdA== - dependencies: - acorn-globals "^4.3.3" - -sesify-viz@^3.0.10: - version "3.0.10" - resolved "https://registry.yarnpkg.com/sesify-viz/-/sesify-viz-3.0.10.tgz#1936e9a62bf8155c57dfc42e5eeceaa28b1cb875" - integrity sha512-Gamqr/8qbZDJ7Yq/NGUk3Iq2woTK67x1mZ59Qrt5ssLZZPzeCBYFeqnNWu8SUO42GlP1D3eyiGLHA31xceySHg== - dependencies: - ncp "^2.0.0" - pify "^4.0.1" - yargs "^14.0.0" - -sesify@^4.2.1: - version "4.2.1" - resolved "https://registry.yarnpkg.com/sesify/-/sesify-4.2.1.tgz#ac98d190b6403abbf90016ec6f3a6d16eef8747e" - integrity sha512-fbgkQCs6KhVK6IhWx+e9MW2cNIzpMSKigIbF6KdAPWGrA6U0D6lDgLErfTB7Sllhv8sYFOwTppIOec+AHdU00g== - dependencies: - JSONStream "^1.3.5" - acorn-globals "^4.3.3" - acorn-walk "^6.1.1" - combine-source-map "^0.8.0" - defined "^1.0.0" - fromentries "^1.1.0" - json-stable-stringify "^1.0.1" - merge-deep "^3.0.2" - module-name-from-path "git+https://git@github.com/kumavis/module-name-from-path.git" - offset-sourcemap-lines "^1.0.1" - pify "^4.0.1" - resolve-package-path "^1.2.7" - safe-buffer "^5.1.2" - sesify-tofu "^2.0.4" - tape "^4.9.1" - through2 "^3.0.0" - umd "^3.0.3" - set-blocking@^2.0.0, set-blocking@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" @@ -23442,16 +23205,6 @@ sha3@^1.2.2: dependencies: nan "2.13.2" -shallow-clone@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-0.1.2.tgz#5909e874ba77106d73ac414cfec1ffca87d97060" - integrity sha1-WQnodLp3EG1zrEFM/sH/yofZcGA= - dependencies: - is-extendable "^0.1.1" - kind-of "^2.0.1" - lazy-cache "^0.2.3" - mixin-object "^2.0.1" - shallow-clone@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-1.0.0.tgz#4480cd06e882ef68b2ad88a3ea54832e2c48b571" @@ -24792,7 +24545,7 @@ tapable@^1.0.0, tapable@^1.1.3: resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2" integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA== -tape@^4.6.3, tape@^4.8.0, tape@^4.9.1: +tape@^4.6.3, tape@^4.8.0: version "4.11.0" resolved "https://registry.yarnpkg.com/tape/-/tape-4.11.0.tgz#63d41accd95e45a23a874473051c57fdbc58edc1" integrity sha512-yixvDMX7q7JIs/omJSzSZrqulOV51EC9dK8dM0TzImTIkHWfe2/kFyL5v+d9C+SrCMaICk59ujsqFAVidDqDaA== @@ -25038,7 +24791,7 @@ through2@3.0.1, through2@^3.0.0, through2@^3.0.1: dependencies: readable-stream "2 || 3" -through@2, "through@>=2.2.7 <3", through@^2.3.6, through@^2.3.7, through@^2.3.8, through@~2.3, through@~2.3.1, through@~2.3.4, through@~2.3.8: +through@2, "through@>=2.2.7 <3", through@^2.3.6, through@^2.3.8, through@~2.3, through@~2.3.1, through@~2.3.4, through@~2.3.8: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= @@ -25609,7 +25362,7 @@ ultron@~1.1.0: resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c" integrity sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og== -umd@^3.0.0, umd@^3.0.3: +umd@^3.0.0: version "3.0.3" resolved "https://registry.yarnpkg.com/umd/-/umd-3.0.3.tgz#aa9fe653c42b9097678489c01000acb69f0b26cf" integrity sha512-4IcGSufhFshvLNcMCV80UnQVlZ5pMOC8mvNPForqwA4+lzYQuetTESLDQkeLmihq8bRcnpbQa48Wb8Lh16/xow== @@ -26102,11 +25855,6 @@ uuid@3.3.2: resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA== -uuid@^2.0.1: - version "2.0.3" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-2.0.3.tgz#67e2e863797215530dff318e5bf9dcebfd47b21a" - integrity sha1-Z+LoY3lyFVMN/zGOW/nc6/1Hsho= - uuid@^3.0.1, uuid@^3.1.0, uuid@^3.2.1, uuid@^3.2.2, uuid@^3.3.2, uuid@^3.3.3: version "3.3.3" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.3.tgz#4568f0216e78760ee1dbf3a4d2cf53e224112866" @@ -27252,7 +27000,7 @@ yargs@13.3.2, yargs@^13.2.2, yargs@^13.2.4, yargs@^13.3.0, yargs@^13.3.2: y18n "^4.0.0" yargs-parser "^13.1.2" -yargs@14.0.0, yargs@^14.0.0, yargs@~14.0.0: +yargs@14.0.0, yargs@~14.0.0: version "14.0.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-14.0.0.tgz#ba4cacc802b3c0b3e36a9e791723763d57a85066" integrity sha512-ssa5JuRjMeZEUjg7bEL99AwpitxU/zWGAGpdj0di41pOEmJti8NR6kyUIJBkR78DTYNPZOU08luUo0GTHuB+ow== From 181bd7bc16482655165dd10c1e8734aa470171b6 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Wed, 3 Feb 2021 03:49:41 -0330 Subject: [PATCH 26/48] Require English descriptions in locale files (#10260) The `verify-locale-strings.js` script now validates that the descriptions from the `en` locale are also present in all other locales. These descriptions are intended to help with translation, and are not meant to be translated. This check will ensure that translators don't accidentally translate these. It also ensures they're present alongside each translated message, which might be helpful for understanding context. --- development/lib/locales.js | 10 ++++++++++ development/verify-locale-strings.js | 26 ++++++++++++++++++++++++-- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/development/lib/locales.js b/development/lib/locales.js index 69840fc67..86f1e6ec9 100644 --- a/development/lib/locales.js +++ b/development/lib/locales.js @@ -37,7 +37,17 @@ function compareLocalesForMissingItems({ base, subject }) { return Object.keys(base).filter((key) => !subject[key]) } +function compareLocalesForMissingDescriptions({ englishLocale, targetLocale }) { + return Object.keys(englishLocale).filter( + (key) => + targetLocale[key] !== undefined && + englishLocale[key].description !== undefined && + englishLocale[key].description !== targetLocale[key].description, + ) +} + module.exports = { + compareLocalesForMissingDescriptions, compareLocalesForMissingItems, getLocale, getLocalePath, diff --git a/development/verify-locale-strings.js b/development/verify-locale-strings.js index 8356c3c3c..7a0aa6281 100644 --- a/development/verify-locale-strings.js +++ b/development/verify-locale-strings.js @@ -8,7 +8,8 @@ // // This script will validate that locales have no unused messages. It will check // the English locale against string literals found under `ui/`, and it will check -// other locales by comparing them to the English locale. +// other locales by comparing them to the English locale. It will also validate +// that non-English locales have all descriptions present in the English locale. // // A report will be printed to the console detailing any unused messages. // @@ -27,6 +28,7 @@ const log = require('loglevel') const matchAll = require('string.prototype.matchall').getPolyfill() const localeIndex = require('../app/_locales/index.json') const { + compareLocalesForMissingDescriptions, compareLocalesForMissingItems, getLocale, getLocalePath, @@ -129,12 +131,32 @@ async function verifyLocale(code) { }) } - if (extraItems.length > 0) { + const missingDescriptions = compareLocalesForMissingDescriptions({ + englishLocale, + targetLocale, + }) + + if (missingDescriptions.length) { + console.log( + `**${code}**: ${missingDescriptions.length} missing descriptions`, + ) + log.info('Messages with missing descriptions:') + missingDescriptions.forEach(function (key) { + log.info(` - [ ] ${key}`) + }) + } + + if (extraItems.length > 0 || missingDescriptions.length > 0) { if (fix) { const newLocale = { ...targetLocale } for (const item of extraItems) { delete newLocale[item] } + for (const message of Object.keys(englishLocale)) { + if (englishLocale[message].description && targetLocale[message]) { + targetLocale[message].description = englishLocale[message].description + } + } await writeLocale(code, newLocale) } return true From 20d536d18910799c4353c412ebb2aee00c108bd1 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Wed, 3 Feb 2021 09:42:35 -0330 Subject: [PATCH 27/48] Update `id` localized messages (#10263) These translations were provided by Lionbridge. --- app/_locales/id/messages.json | 1381 +++++++++++++++++++++++++++------ 1 file changed, 1123 insertions(+), 258 deletions(-) diff --git a/app/_locales/id/messages.json b/app/_locales/id/messages.json index 98bdb19ba..9cfa08702 100644 --- a/app/_locales/id/messages.json +++ b/app/_locales/id/messages.json @@ -6,7 +6,15 @@ "message": "Versi, pusat dukungan, dan informasi kontak" }, "acceleratingATransaction": { - "message": "* Mempercepat transaksi dengan menggunakan harga gas yang lebih tinggi meningkatkan peluangnya untuk lebih cepat diproses oleh jaringan, tetapi tak selalu terjamin pasti cepat." + "message": "* Mempercepat transaksi dengan menggunakan biaya jaringan yang lebih tinggi akan meningkatkan peluang untuk diproses oleh jaringan lebih cepat, namun tidak selalu terjamin." + }, + "acceptTermsOfUse": { + "message": "Saya telah membaca dan menyetujui $1", + "description": "$1 is the `terms` message" + }, + "accessAndSpendNotice": { + "message": "$1 dapat diakses dan digunakan hingga jumlah maksimum ini", + "description": "$1 is the url of the site requesting ability to spend" }, "accessingYourCamera": { "message": "Mengakses kamera Anda..." @@ -15,7 +23,7 @@ "message": "Akun" }, "accountDetails": { - "message": "Rincian Akun" + "message": "Detail akun" }, "accountName": { "message": "Nama Akun" @@ -24,60 +32,121 @@ "message": "Opsi Akun" }, "accountSelectionRequired": { - "message": "Anda perlu memilih akun!" + "message": "Anda harus memilih satu akun!" + }, + "active": { + "message": "Aktif" + }, + "activity": { + "message": "Aktivitas" }, "activityLog": { "message": "log aktivitas" }, + "addAccount": { + "message": "Tambahkan akun" + }, "addAcquiredTokens": { - "message": "Tambahkan token yang sudah Anda peroleh menggunakan MetaMask" + "message": "Tambahkan token yang Anda peroleh menggunakan MetaMask" }, "addAlias": { - "message": "Tambah alias" + "message": "Tambahkan alias" }, "addNetwork": { - "message": "Tambah Jaringan" + "message": "Tambahkan Jaringan" }, "addRecipient": { - "message": "Tambah Penerima" + "message": "Tambahkan Penerima" }, "addSuggestedTokens": { - "message": "Tambah Token yang Disarankan" + "message": "Tambahkan Token yang Disarankan" }, "addToAddressBook": { - "message": "Tambahkan ke buku alamat " + "message": "Tambahkan ke buku alamat" }, "addToAddressBookModalPlaceholder": { - "message": "cth: John D." + "message": "contoh: John D." }, "addToken": { - "message": "Tambah Token" + "message": "Tambahkan Token" }, "addTokens": { - "message": "Tambah Token" + "message": "Tambahkan Token" }, "advanced": { - "message": "Lanjutan" + "message": "Tingkat Lanjut" }, "advancedOptions": { - "message": "Opsi Lanjutan" + "message": "Opsi Tingkat Lanjut" }, "advancedSettingsDescription": { - "message": "Akses fitur pengembang, unduh Log Status, Atur Ulang Akun, tata testnets dan RPC kustom" + "message": "Akses fitur pengembang, unduh Log Status, Atur Ulang Akun, siapkan testnet, dan sesuaikan RPC" + }, + "affirmAgree": { + "message": "Saya Setuju" + }, + "aggregatorFeeCost": { + "message": "Biaya jaringan agregator" + }, + "alertDisableTooltip": { + "message": "Ini dapat diubah dalam \"Pengaturan > Peringatan\"" + }, + "alertSettingsUnconnectedAccount": { + "message": "Menjelajahi situs web dengan akun yang tidak terhubung dipilih" + }, + "alertSettingsUnconnectedAccountDescription": { + "message": "Peringatan ini ditampilkan dalam popup saat Anda menelusuri situs Web3 yang terhubung, namun akun yang baru saja dipilih tidak terhubung." + }, + "alerts": { + "message": "Peringatan" + }, + "alertsSettingsDescription": { + "message": "Aktifkan atau nonaktifkan setiap peringatan" + }, + "allowExternalExtensionTo": { + "message": "Izinkan ekstensi eksternal ini untuk:" + }, + "allowOriginSpendToken": { + "message": "Izinkan $1 untuk menggunakan $2 Anda?", + "description": "$1 is the url of the site and $2 is the symbol of the token they are requesting to spend" + }, + "allowThisSiteTo": { + "message": "Izinkan situs ini untuk:" + }, + "allowWithdrawAndSpend": { + "message": "Izinkan $1 untuk ditarik dan digunakan hingga jumlah berikut:", + "description": "The url of the site that requested permission to 'withdraw and spend'" }, "amount": { "message": "Jumlah" }, + "amountInEth": { + "message": "$1 ETH", + "description": "Displays an eth amount to the user. $1 is a decimal number" + }, + "amountWithColon": { + "message": "Jumlah:" + }, "appDescription": { - "message": "Sebuah Dompet Ethereum di Peramban Anda", + "message": "Dompet Ethereum di Browser Anda", "description": "The description of the application" }, "appName": { "message": "MetaMask", "description": "The name of the application" }, + "approvalAndAggregatorTxFeeCost": { + "message": "Biaya jaringan agregator dan persetujuan" + }, + "approvalTxGasCost": { + "message": "Persetujuan Ongkos Jaringan Tx" + }, "approve": { - "message": "Setujui" + "message": "Setujui batas penggunaan" + }, + "approveSpendLimit": { + "message": "Setujui batas penggunaan $1", + "description": "The token symbol that is being approved" }, "approved": { "message": "Disetujui" @@ -85,38 +154,44 @@ "asset": { "message": "Aset" }, + "assets": { + "message": "Aset" + }, "attemptToCancel": { - "message": "Coba Batalkan?" + "message": "Coba Membatalkan?" }, "attemptToCancelDescription": { - "message": "Mengirimkan upaya ini tidak menjamin transaksi asli Anda akan dibatalkan. Jika upaya pembatalan berhasil, Anda akan dikenakan biaya transaksi di atas." + "message": "Mengirim upaya ini tidak menjamin transaksi asli Anda akan dibatalkan. Jika upaya pembatalan berhasil, Anda akan dikenakan biaya transaksi di atas." }, "attemptingConnect": { - "message": "Mencoba menghubungkan ke blockchain." + "message": "Mencoba terhubung ke blockchain." }, "attributions": { "message": "Atribusi" }, + "authorizedPermissions": { + "message": "Anda telah mengotorisasi izin berikut" + }, "autoLockTimeLimit": { - "message": "Jangka Waktu Keluar-Otomatis (menit)" + "message": "Timer Mengunci Otomatis (menit)" }, "autoLockTimeLimitDescription": { - "message": "Atur waktu diam dalam menit sebelum MetaMask mengeluarkan Anda secara otomatis" + "message": "Atur waktu siaga dalam menit sebelum MetaMask menjadi terkunci." }, "average": { "message": "Rata-rata" }, "back": { - "message": "Mundur" + "message": "Kembali" }, "backToAll": { "message": "Kembali ke Semua" }, "backupApprovalInfo": { - "message": "Kode rahasia Anda diperlukan untuk memulihkan dompet jika perangkat hilang, lupa sandi, harus menginstal ulang MetaMask, atau ingin mengakses dompet Anda di perangkat lain." + "message": "Kode rahasia ini diperlukan untuk memulihkan dompet seandainya Anda kehilangan perangkat, lupa kata sandi, harus menginstal kembali MetaMask, atau ingin mengakses dompet Anda di perangkat lain." }, "backupApprovalNotice": { - "message": "Cadangkan kode Pemulihan Rahasia guna mengamankan dompet dan dana Anda." + "message": "Cadangkan kode Pemulihan Rahasia Anda untuk menjaga keamanan dompet dan dana Anda." }, "backupNow": { "message": "Cadangkan sekarang" @@ -125,32 +200,35 @@ "message": "Saldo" }, "balanceOutdated": { - "message": "Saldo mungkin kedaluwarsa" + "message": "Saldo mungkin sudah usang" }, "basic": { "message": "Dasar" }, "blockExplorerUrl": { - "message": "Blokir Penjelajah" + "message": "Block Explorer" }, "blockExplorerView": { "message": "Lihat akun di $1", "description": "$1 replaced by URL for custom block explorer" }, "blockiesIdenticon": { - "message": "Gunakan Blockies Identicon" + "message": "Menggunakan Blockies Identicon" }, "browserNotSupported": { - "message": "Peramban Anda tidak didukung..." + "message": "Browser Anda tidak didukung..." }, "builtInCalifornia": { - "message": "MetaMask dirancang dan dibangun di California." + "message": "MetaMask didesain dan didirikan di California." + }, + "buy": { + "message": "Beli" }, "buyWithWyre": { - "message": "Membeli ETH dengan Wyre" + "message": "Beli ETH dengan Wyre" }, "buyWithWyreDescription": { - "message": "Wyre mengizinkan Anda menggunakan kartu kredit untuk mendepositkan ETH langsung ke akun MetaMask." + "message": "Wyre memungkinkan Anda menggunakan kartu debit untuk menyetorkan ETH langsung di akun MetaMask Anda." }, "bytes": { "message": "Byte" @@ -159,7 +237,7 @@ "message": "Batal" }, "cancellationGasFee": { - "message": "Pembatalan Biaya Gas" + "message": "Biaya Pembatalan Jaringan" }, "cancelled": { "message": "Dibatalkan" @@ -168,52 +246,114 @@ "message": "ID Rantai" }, "chromeRequiredForHardwareWallets": { - "message": "Anda harus menggunakan MetaMask di Google Chrome untuk menyambung ke dompet Perangkat Keras Anda." + "message": "Anda perlu menggunakan MetaMask di Google Chrome untuk terhubung ke Dompet Perangkat Keras Anda." }, "clickToRevealSeed": { - "message": "Klik di sini untuk mengungkapkan kata-kata rahasia" + "message": "Klik di sini untuk membuka kata rahasia" }, "close": { "message": "Tutup" }, "confirm": { - "message": "Konfirmasi" + "message": "Konfirmasikan" }, "confirmPassword": { - "message": "Konfirmasi Sandi" + "message": "Konfirmasikan kata sandi" }, "confirmSecretBackupPhrase": { - "message": "Konfirmasikan Frasa Cadangan Rahasia Anda" + "message": "Konfirmasikan Frasa Cadangan Rahasia" }, "confirmed": { - "message": "Dikonfirmasi" + "message": "Dikonfirmasikan" }, "congratulations": { "message": "Selamat" }, "connect": { - "message": "Sambungkan" + "message": "Hubungkan" + }, + "connectAccountOrCreate": { + "message": "Hubungkan akun atau buat baru" }, "connectHardwareWallet": { - "message": "Hubungkan Dompet Peranti Keras" + "message": "Hubungkan Dompet Perangkat Keras" + }, + "connectManually": { + "message": "Hubungkan ke situs saat ini secara manual" + }, + "connectTo": { + "message": "Hubungkan ke $1", + "description": "$1 is the name/origin of a web3 site/application that the user can connect to metamask" + }, + "connectToAll": { + "message": "Hubungkan ke semua $1 Anda", + "description": "$1 will be replaced by the translation of connectToAllAccounts" + }, + "connectToAllAccounts": { + "message": "akun", + "description": "will replace $1 in connectToAll, completing the sentence 'connect to all of your accounts', will be text that shows list of accounts on hover" + }, + "connectToMultiple": { + "message": "Hubungkan ke $1", + "description": "$1 will be replaced by the translation of connectToMultipleNumberOfAccounts" + }, + "connectToMultipleNumberOfAccounts": { + "message": "$1 akun", + "description": "$1 is the number of accounts to which the web3 site/application is asking to connect; this will substitute $1 in connectToMultiple" + }, + "connectWithMetaMask": { + "message": "Hubungkan Dengan MetaMask" + }, + "connectedAccountsDescriptionPlural": { + "message": "Anda memiliki $1 akun yang terhubung ke situs ini.", + "description": "$1 is the number of accounts" + }, + "connectedAccountsDescriptionSingular": { + "message": "Anda memiliki 1 akun yang terhubung ke situs ini." + }, + "connectedAccountsEmptyDescription": { + "message": "MetaMask tidak terhubung ke situs ini. Untuk terhubung ke situs web3, temukan tombol hubungkan di situs mereka." + }, + "connectedSites": { + "message": "Situs yang terhubung" + }, + "connectedSitesDescription": { + "message": "$1 terhubung ke situs ini. Mereka dapat melihat alamat akun Anda.", + "description": "$1 is the account name" + }, + "connectedSitesEmptyDescription": { + "message": "$1 tidak terhubung ke situs apa pun.", + "description": "$1 is the account name" + }, + "connecting": { + "message": "Menghubungkan..." }, "connectingTo": { "message": "Menghubungkan ke $1" }, "connectingToGoerli": { - "message": "Menghubungkan ke Jaringan Uji Coba Goerli" + "message": "Menghubungkan ke Jaringan Uji Goerli" }, "connectingToKovan": { - "message": "Menyambung ke Jaringan Tes Kovan" + "message": "Menghubungkan ke Jaringan Uji Kovan" }, "connectingToMainnet": { - "message": "Menghubungkan ke Jaringan Ethereum Utama" + "message": "Menghubungkan ke Ethereum Mainnet" }, "connectingToRinkeby": { - "message": "Menghubungkan ke Jaringan Uji Coba Rinkeby " + "message": "Menghubungkan ke Jaringan Uji Rinkeby" }, "connectingToRopsten": { - "message": "Menghubungkan ke Jaringan Uji Coba Ropsten " + "message": "Menghubungkan ke Jaringan Uji Ropsten" + }, + "contactUs": { + "message": "Hubungi kami" + }, + "contacts": { + "message": "Kontak" + }, + "contactsSettingsDescription": { + "message": "Tambah, edit, hapus, dan kelola kontak Anda" }, "continueToWyre": { "message": "Lanjutkan ke Wyre" @@ -228,16 +368,16 @@ "message": "Disalin!" }, "copiedTransactionId": { - "message": "ID Transaksi Tersalin" + "message": "ID Transaksi yang Disalin" }, "copyAddress": { "message": "Salin alamat ke clipboard" }, "copyPrivateKey": { - "message": "Ini adalah kunci pribadi Anda (klik untuk menyalin)" + "message": "Ini adalah kunci privat Anda (klik untuk menyalin)" }, "copyToClipboard": { - "message": "Salin ke papan klip" + "message": "Salin ke clipboard" }, "copyTransactionId": { "message": "Salin ID Transaksi" @@ -252,34 +392,66 @@ "message": "Buat Akun" }, "createPassword": { - "message": "Buat Sandi" + "message": "Buat Kata Sandi" }, "currencyConversion": { "message": "Konversi Mata Uang" }, + "currentAccountNotConnected": { + "message": "Akun Anda saat ini tidak terhubung" + }, + "currentExtension": { + "message": "Halaman ekstensi saat ini" + }, "currentLanguage": { "message": "Bahasa Saat Ini" }, "customGas": { - "message": "Kustomisasi Bensin" + "message": "Sesuaikan Biaya Jaringan" }, "customGasSubTitle": { - "message": "Meningkatkan harga dapat mengurangi waktu pemrosesan, tetapi ini tidak dijamin." + "message": "Menaikkan biaya dapat mengurangi waktu pemrosesan, namun tidak dijamin." }, "customRPC": { "message": "RPC Kustom" }, + "customSpendLimit": { + "message": "Batas Penggunaan Kustom" + }, "customToken": { "message": "Token Kustom" }, + "dataBackupFoundInfo": { + "message": "Beberapa data akun Anda telah dicadangkan selama penginstalan MetaMask yang lalu. Ini bisa mencakup pengaturan, kontak, dan token Anda. Apakah Anda ingin memulihkan data ini sekarang?" + }, "decimal": { - "message": "Ketelitian Desimal" + "message": "Desimal Presisi" }, "decimalsMustZerotoTen": { - "message": "Desimal harus sekurang-kurangnya 0, dan tidak lebih dari 36." + "message": "Desimal harus sekurangnya 0, dan tidak lebih dari 36." + }, + "decrypt": { + "message": "Dekrip" + }, + "decryptCopy": { + "message": "Salin pesan yang dienkripsi" + }, + "decryptInlineError": { + "message": "Pesan ini tidak dapat didekripsi karena kesalahan: $1", + "description": "$1 is error message" + }, + "decryptMessageNotice": { + "message": "$1 ingin membaca pesan ini untuk menyelesaikan tindakan Anda", + "description": "$1 is the web3 site name" + }, + "decryptMetamask": { + "message": "Dekrip pesan" + }, + "decryptRequest": { + "message": "Dekrip permintaan" }, "defaultNetwork": { - "message": "Jaringan default untuk transaksi Ether adalah Main Net." + "message": "Jaringan default untuk transaksi Ether adalah Jaringan Utama." }, "delete": { "message": "Hapus" @@ -291,16 +463,37 @@ "message": "Hapus Jaringan?" }, "deleteNetworkDescription": { - "message": "Apakah Anda yakin ingin menghapus jaringan ini?" + "message": "Anda yakin ingin menghapus jaringan ini?" + }, + "depositEther": { + "message": "Deposit Ether" }, "details": { "message": "Detail" }, "directDepositEther": { - "message": "Deposit Ether Langsung" + "message": "Deposit Ether Secara Langsung" }, "directDepositEtherExplainer": { - "message": "Jika Anda sudah memiliki Ether, cara tercepat mendapatkan Ether di dompet baru lewat deposit langsung." + "message": "Jika Anda sudah memiliki beberapa Ether, cara tercepat untuk mendapatkan Ether di dompet baru Anda adalah dengan deposit langsung." + }, + "disconnect": { + "message": "Putuskan koneksi" + }, + "disconnectAllAccounts": { + "message": "Putuskan koneksi semua akun" + }, + "disconnectAllAccountsConfirmationDescription": { + "message": "Anda yakin ingin memutus koneksi? Fungsionalitas situs Anda bisa hilang." + }, + "disconnectPrompt": { + "message": "Putuskan koneksi $1" + }, + "disconnectThisAccount": { + "message": "Putuskan koneksi akun ini" + }, + "dismiss": { + "message": "Lewatkan" }, "done": { "message": "Selesai" @@ -308,120 +501,227 @@ "dontHaveAHardwareWallet": { "message": "Tidak punya dompet perangkat keras?" }, + "dontShowThisAgain": { + "message": "Jangan tampilkan ini lagi" + }, "downloadGoogleChrome": { "message": "Unduh Google Chrome" }, "downloadSecretBackup": { - "message": "Unduh Frasa Cadangan Rahasia ini dan simpanlah dengan aman di hard drive eksternal atau media penyimpanan terenkripsi." + "message": "Unduh Frasa Cadangan Rahasia dan biarkan tersimpan secara aman di media penyimpanan atau hard drive eksternal terenkripsi." }, "downloadStateLogs": { - "message": "Unduh Log Kondisi" + "message": "Unduh Log Status" }, "dropped": { - "message": "Jatuh" + "message": "Terputus" + }, + "edit": { + "message": "Edit" }, "editContact": { - "message": "Sunting Kontak" + "message": "Edit Kontak" + }, + "editPermission": { + "message": "Edit Izin" + }, + "encryptionPublicKeyNotice": { + "message": "$1 menginginkan kunci enkripsi publik Anda. Dengan menyetujui, situs ini akan dapat membuat pesan terenkripsi untuk Anda.", + "description": "$1 is the web3 site name" + }, + "encryptionPublicKeyRequest": { + "message": "Minta kunci publik enkripsi" }, "endOfFlowMessage1": { - "message": "Anda lulus tes - jagalah agar frasa benih Anda aman, itu tanggung jawab Anda!" + "message": "Anda lulus ujian - jaga frasa pemulihan Anda tetap aman, ini tanggung jawab Anda!" }, "endOfFlowMessage10": { - "message": "Selesai" + "message": "Semua Selesai" }, "endOfFlowMessage2": { - "message": "Tips menyimpan secara aman" + "message": "Kiat menyimpannya secara aman" }, "endOfFlowMessage3": { - "message": "Simpanlah cadangan di beberapa tempat." + "message": "Simpan cadangan di berbagai tempat." }, "endOfFlowMessage4": { - "message": "Jangan pernah bagikan frasa dengan siapa pun." + "message": "Jangan bagikan frasa kepada siapa pun." }, "endOfFlowMessage5": { - "message": "Hati-hati terhadap phishing! MetaMask tidak akan pernah meminta frasa benih Anda secara spontan." + "message": "Berhati-hatilah dengan phishing! MetaMask tidak pernah secara spontan meminta frasa pemulihan Anda." }, "endOfFlowMessage6": { - "message": "Jika Anda perlu mencadangkan frase seed lagi, Anda dapat menemukannya dalam Pengaturan -> Keamanan." + "message": "Jika Anda perlu mencadangkan frasa pemulihan lagi, Anda dapat menemukannya di Pengaturan -> Keamanan." }, "endOfFlowMessage7": { - "message": "Jika Anda punya pertanyaan atau melihat sesuatu yang ganjil, kirimkan email ke support@metamask.io." + "message": "Jika Anda memiliki pertanyaan atau melihat sesuatu yang mencurigakan hubungi lewat email ke support@metamask.io." }, "endOfFlowMessage8": { - "message": "MetaMask tidak dapat memulihkan frasa seed Anda. Pelajari lebih lanjut." + "message": "MetaMask tidak dapat memulihkan frasa pemulihan Anda." }, "endOfFlowMessage9": { - "message": "Pelajari lebih lanjut." + "message": "Pelajari selengkapnya." + }, + "endpointReturnedDifferentChainId": { + "message": "Titik akhir memberikan hasil ID rantai yang berbeda: $1", + "description": "$1 is the return value of eth_chainId from an RPC endpoint" }, "ensNotFoundOnCurrentNetwork": { - "message": "Nama ENS tidak ditemukan pada jaringan saat ini. Cobalah beralih ke jaringan Ethereum utama." + "message": "Nama ENS tidak ditemukan pada jaringan saat ini. Coba untuk beralih ke Ethereum Mainnet." }, "ensRegistrationError": { - "message": "Terjadi kesalahan dalam pendaftaran nama ENS" + "message": "Kesalahan pada pendaftaran nama ENS" }, "enterAnAlias": { "message": "Masukkan alias" }, + "enterMaxSpendLimit": { + "message": "Masukkan Batas Penggunaan Maksimum" + }, "enterPassword": { - "message": "Masukkan sandi" + "message": "Masukkan kata sandi" }, "enterPasswordContinue": { - "message": "Masukkan sandi untuk melanjutkan" + "message": "Masukkan kata sandi untuk melanjutkan" + }, + "errorCode": { + "message": "Kode: $1", + "description": "Displayed error code for debugging purposes. $1 is the error code" + }, + "errorDetails": { + "message": "Detail Kesalahan", + "description": "Title for collapsible section that displays error details for debugging purposes" + }, + "errorMessage": { + "message": "Pesan: $1", + "description": "Displayed error message for debugging purposes. $1 is the error message" + }, + "errorName": { + "message": "Kode: $1", + "description": "Displayed error name for debugging purposes. $1 is the error name" + }, + "errorPageMessage": { + "message": "Coba lagi dengan memuat kembali halaman, atau hubungi dukungan di support@metamask.io", + "description": "Message displayed on generic error page in the fullscreen or notification UI" + }, + "errorPagePopupMessage": { + "message": "Coba lagi dengan menutup dan membuka kembali popup, atau hubungi dukungan di support@metamask.io", + "description": "Message displayed on generic error page in the popup UI" + }, + "errorPageTitle": { + "message": "MetaMask menemukan kesalahan", + "description": "Title of generic error page" + }, + "errorStack": { + "message": "Tumpukan:", + "description": "Title for error stack, which is displayed for debugging purposes" }, "estimatedProcessingTimes": { - "message": "Estimasi Waktu Pemrosesan" + "message": "Waktu Pemrosesan yang Diperkirakan" + }, + "eth_accounts": { + "message": "Lihat alamat akun Anda yang diizinkan (wajib)", + "description": "The description for the `eth_accounts` permission" }, "ethereumPublicAddress": { - "message": "Alamat Publik Ethereum " + "message": "Alamat Publik Ethereum" + }, + "etherscan": { + "message": "Etherscan" }, "etherscanView": { "message": "Lihat akun di Etherscan" }, "expandView": { - "message": "Bentangkan Tampilan" + "message": "Perluas tampilan" }, "exportPrivateKey": { "message": "Ekspor Kunci Privat" }, + "externalExtension": { + "message": "Ekstensi Eksternal" + }, + "extraApprovalGas": { + "message": "+$1 biaya jaringan persetujuan", + "description": "Expresses an additional gas amount the user will have to pay, on top of some other displayed amount. $1 is a decimal amount of gas" + }, "failed": { "message": "Gagal" }, + "failedToFetchChainId": { + "message": "Tidak dapat mengambil ID rantai. Apakah URL RPC Anda benar?" + }, + "failureMessage": { + "message": "Ada yang salah, dan kami tidak dapat menyelesaikan tindakan" + }, "fast": { "message": "Cepat" }, + "fastest": { + "message": "Tercepat" + }, + "feeAssociatedRequest": { + "message": "Biaya dikaitkan dengan permintaan ini." + }, + "fiat": { + "message": "Fiat", + "description": "Exchange type" + }, "fileImportFail": { - "message": "Impor berkas tidak tersedia? Klik di sini!", + "message": "Impor file tidak bekerja? Klik di sini!", "description": "Helps user import their account from a JSON file" }, + "forbiddenIpfsGateway": { + "message": "Gateway IPFS Terlarang: Tentukan gateway CID" + }, "forgetDevice": { "message": "Lupakan perangkat ini" }, "from": { "message": "Dari" }, + "fromAddress": { + "message": "Dari: $1", + "description": "$1 is the address to include in the From label. It is typically shortened first using shortenAddress" + }, + "functionApprove": { + "message": "Fungsi: Setujui" + }, "functionType": { "message": "Jenis Fungsi" }, "gasLimit": { - "message": "Batas Gas" + "message": "Batas Biaya Jaringan" }, "gasLimitInfoTooltipContent": { - "message": "Limit Bensin adalah jumlah maksimal satuan bensin yang Anda bersedia gunakan." + "message": "Batas biaya jaringan adalah jumlah unit biaya jaringan maksimum yang ingin Anda gunakan." }, "gasLimitTooLow": { - "message": "Batas Gas harus paling tidak 21000" + "message": "Batas biaya jaringan harus sekurangnya 21000" + }, + "gasLimitTooLowWithDynamicFee": { + "message": "Batas biaya jaringan harus sekurangnya $1", + "description": "$1 is the custom gas limit, in decimal." }, "gasPrice": { - "message": "Harga Bensin (GWEI)" + "message": "Biaya Jaringan (GWEI)" }, "gasPriceExtremelyLow": { - "message": "Harga Bensin Amat Rendah" + "message": "Biaya Jaringan Sangat Rendah" }, "gasPriceInfoTooltipContent": { - "message": "Harga gas menentukan jumlah Ether yang bersedia Anda bayarkan untuk setiap unit gas." + "message": "Biaya jaringan menentukan jumlah Ether yang ingin Anda bayar untuk masing-masing unit biaya jaringan." }, "gasUsed": { - "message": "Gas yang Digunakan" + "message": "Biaya Jaringan yang Digunakan" + }, + "gdprMessage": { + "message": "Data ini dikumpulkan dan oleh karenanya bersifat anonim untuk tujuan Peraturan Perlindungan Data Umum (General Data Protection Regulation/GDPR) (UE) 2016/679. Untuk informasi selengkapnya sehubungan dengan praktik privasi kami, lihat $1 kami.", + "description": "$1 refers to the gdprMessagePrivacyPolicy message, the translation of which is meant to be used exclusively in the context of gdprMessage" + }, + "gdprMessagePrivacyPolicy": { + "message": "Kebijakan Privasi di sini", + "description": "this translation is intended to be exclusively used as the replacement for the $1 in the gdprMessage translation" }, "general": { "message": "Umum" @@ -440,28 +740,28 @@ "message": "Dapatkan Bantuan." }, "getStarted": { - "message": "Mulai" + "message": "Persiapan." }, "goerli": { "message": "Jaringan Uji Goerli" }, "happyToSeeYou": { - "message": "Kami senang bertemu dengan Anda." + "message": "Kami senang melihat Anda." }, "hardware": { - "message": "perangkat keras" + "message": "Perangkat keras" }, "hardwareWalletConnected": { - "message": "Dompet peranti keras terhubung" + "message": "Dompet perangkat keras terhubung" }, "hardwareWallets": { - "message": "Hubungkan dompet peranti keras" + "message": "Hubungkan dompet perangkat keras" }, "hardwareWalletsMsg": { - "message": "Pilih dompet hardware yang ingin Anda pakai dengan MetaMask" + "message": "Pilih dompet perangkat keras yang ingin Anda gunakan dengan MetaMask" }, "havingTroubleConnecting": { - "message": "Kesulitan menghubungkan?" + "message": "Ada masalah saat menghubungkan?" }, "here": { "message": "di sini", @@ -476,8 +776,12 @@ "hideTokenPrompt": { "message": "Sembunyikan Token?" }, + "hideTokenSymbol": { + "message": "Sembunyikan $1", + "description": "$1 is the symbol for a token (e.g. 'DAI')" + }, "history": { - "message": "Histori" + "message": "Riwayat" }, "import": { "message": "Impor", @@ -487,84 +791,125 @@ "message": "Impor Akun" }, "importAccountMsg": { - "message": "Akun impor tidak akan dihubungkan dengan frasa benih akun MetaMask yang diciptakan pertama kali. Pelajari lebih lanjut tentang akun impor" + "message": " Akun yang diimpor tidak akan dikaitkan dengan frasa pemulihan akun MetaMask yang asli dibuat. Pelajari selengkapnya tentang akun yang diimpor " }, "importAccountSeedPhrase": { - "message": "Impor Akun dengan Frasa Benih" + "message": "Impor akun dengan frasa pemulihan" }, "importUsingSeed": { - "message": "Impor menggunakan frasa benih akun" + "message": "Impor menggunakan frasa pemulihan akun" }, "importWallet": { - "message": "Impor Dompet" + "message": "Impor dompet" }, "importYourExisting": { - "message": "Impor dompet Anda yang ada menggunakan frasa 12 benih kata" + "message": "Impor dompet Anda yang ada menggunakan frasa pemulihan 12 kata" }, "imported": { "message": "Diimpor", "description": "status showing that an account has been fully loaded into the keyring" }, "infoHelp": { - "message": "Info & Bantuan" + "message": "Informasi & Bantuan" }, "initialTransactionConfirmed": { - "message": "Transaksi awal Anda telah dikonfirmasi oleh jaringan. Klik OK untuk kembali." + "message": "Transaksi awal Anda dikonfirmasikan oleh jaringan. Klik Oke untuk kembali." }, "insufficientBalance": { - "message": "Saldo tidak mencukupi." + "message": "Saldo tidak cukup." }, "insufficientFunds": { "message": "Dana tidak cukup." }, "insufficientTokens": { - "message": "Token tak mencukupi." + "message": "Token tidak memadai." }, "invalidAddress": { - "message": "Alamat tidak sah" + "message": "Alamat tidak valid" }, "invalidAddressRecipient": { "message": "Alamat penerima tidak valid" }, "invalidAddressRecipientNotEthNetwork": { - "message": "Bukan jaringan ETH, tetapkan ke huruf kecil" + "message": "Bukan jaringan ETH, atur ke huruf kecil" }, "invalidBlockExplorerURL": { - "message": "URL Block Explorer Tidak Sah" + "message": "URL Block Explorer Tidak Valid" + }, + "invalidCustomNetworkAlertContent1": { + "message": "ID rantai untuk jaringan kustom '$1' harus dimasukkan kembali.", + "description": "$1 is the name/identifier of the network." + }, + "invalidCustomNetworkAlertContent2": { + "message": "Untuk melindungi Anda dari penyedia jaringan yang jahat atau salah, ID rantai kini diperlukan untuk semua jaringan kustom." + }, + "invalidCustomNetworkAlertContent3": { + "message": "Buka Pengaturan > Jaringan dan masukkan ID rantai. Anda dapat menemukan ID rantai dari jaringan paling populer di $1.", + "description": "$1 is a link to https://chainid.network" + }, + "invalidCustomNetworkAlertTitle": { + "message": "Jaringan Kustom Tidak Valid" + }, + "invalidHexNumber": { + "message": "Bilangan heksadesimal tidak valid." + }, + "invalidHexNumberLeadingZeros": { + "message": "Bilangan heksadesimal tidak valid. Hapus semua nol di depan." + }, + "invalidIpfsGateway": { + "message": "Gateway IPFS tidak valid: Nilai harus berupa URL yang valid" + }, + "invalidNumber": { + "message": "Angka tidak valid. Masukkan bilangan heksadesimal berawalan '0x' atau desimal." + }, + "invalidNumberLeadingZeros": { + "message": "Angka tidak valid. Hapus semua nol di depan." }, "invalidRPC": { - "message": "URL RPC Tidak Sah" + "message": "URL RPC Tidak Valid" }, "invalidSeedPhrase": { - "message": "Frasa benih tidak valid" + "message": "Frasa pemulihan tidak valid" + }, + "ipfsGateway": { + "message": "Gateway IPFS" + }, + "ipfsGatewayDescription": { + "message": "Masukkan URL gateway CID IPFS untuk digunakan untuk resolusi konten ENS." }, "jsonFile": { - "message": "Berkas JSON", + "message": "File JSON", "description": "format for importing an account" }, "knownAddressRecipient": { - "message": "Alamat kontrak dikenal." + "message": "Alamat kontrak yang diketahui." + }, + "knownTokenWarning": { + "message": "Tindakan ini akan mengedit token yang telah terdaftar dalam dompet Anda, yang dapat digunakan untuk menipu Anda. Setujui hanya jika Anda yakin bahwa Anda ingin mengubah apa yang diwakili token ini." }, "kovan": { - "message": "Jaringan Uji Coba Kovan" + "message": "Jaringan Uji Kovan" + }, + "lastConnected": { + "message": "Terakhir Terhubung" }, "learnMore": { - "message": "Pelajari lebih lanjut" + "message": "Pelajari selengkapnya" }, "ledgerAccountRestriction": { - "message": "Anda perlu menggunakan akun terakhir sebelum dapat menambahkan akun baru." + "message": "Anda perlu memanfaatkan akun terakhir Anda sebelum menambahkan yang baru." }, "letsGoSetUp": { - "message": "Ya, ayo tata!" + "message": "Ya, mari siap-siap!" }, "likeToAddTokens": { - "message": "Apakah Anda ingin menambahkan token-token ini?" + "message": "Apakah Anda ingin menambahkan token ini?" }, "links": { "message": "Tautan" }, "loadMore": { - "message": "Muat Lainnya" + "message": "Muat Lebih Banyak" }, "loading": { "message": "Memuat..." @@ -572,32 +917,84 @@ "loadingTokens": { "message": "Memuat Token..." }, + "localhost": { + "message": "Localhost 8545" + }, "lock": { - "message": "Keluar" + "message": "Kunci" + }, + "lockTimeTooGreat": { + "message": "Lock time terlalu besar" }, "mainnet": { - "message": "Jaringan Ethereum Utama" + "message": "Ethereum Mainnet" }, "max": { - "message": "Maks" + "message": "Maks." + }, + "memo": { + "message": "memo" }, "memorizePhrase": { - "message": "Ingatlah frasa ini." + "message": "Ingat frasa ini." }, "message": { "message": "Pesan" }, + "metaMaskConnectStatusParagraphOne": { + "message": "Kini, Anda memiliki kontrol lebih banyak atas koneksi akun Anda di MetaMask." + }, + "metaMaskConnectStatusParagraphThree": { + "message": "Klik untuk mengelola akun Anda yang terhubung." + }, + "metaMaskConnectStatusParagraphTwo": { + "message": "Tombol status koneksi menunjukkan apakah situs web yang Anda kunjungi terhubung ke akun Anda yang dipilih saat ini." + }, "metamaskDescription": { "message": "Menghubungkan Anda ke Ethereum dan Web Terdesentralisasi." }, + "metamaskSwapsOfflineDescription": { + "message": "MetaMask Swap sedang dalam pemeliharaan. Silakan periksa kembali nanti." + }, "metamaskVersion": { "message": "Versi MetaMask" }, + "metametricsCommitmentsAllowOptOut": { + "message": "Selalu izinkan Anda untuk menyisih melalui Pengaturan" + }, + "metametricsCommitmentsBoldNever": { + "message": "Jangan", + "description": "This string is localized separately from some of the commitments so that we can bold it" + }, + "metametricsCommitmentsIntro": { + "message": "MetaMask akan.." + }, + "metametricsCommitmentsNeverCollectIP": { + "message": "$1 mengumpulkan alamat IP lengkap Anda", + "description": "The $1 is the bolded word 'Never', from 'metametricsCommitmentsBoldNever'" + }, + "metametricsCommitmentsNeverCollectKeysEtc": { + "message": "$1 mengumpulkan kunci, alamat, transaksi, saldo, hash, atau informasi pribadi lainnya", + "description": "The $1 is the bolded word 'Never', from 'metametricsCommitmentsBoldNever'" + }, + "metametricsCommitmentsNeverSellDataForProfit": { + "message": "$1 menjual data untuk mendapatkan keuntungan. Selamanya!", + "description": "The $1 is the bolded word 'Never', from 'metametricsCommitmentsBoldNever'" + }, + "metametricsCommitmentsSendAnonymizedEvents": { + "message": "Kirim kejadian pageview & klik anonim" + }, + "metametricsHelpImproveMetaMask": { + "message": "Bantu Kami Menyempurnakan MetaMask" + }, + "metametricsOptInDescription": { + "message": "MetaMask ingin mengumpulkan data penggunaan untuk lebih memahami cara pengguna berinteraksi dengan ekstensi. Data ini akan digunakan untuk secara kontinu memperbaiki kegunaan dan pengalaman pengguna atas produk kami dan ekosistem Ethereum." + }, "mobileSyncText": { - "message": "Harap masukkan sandi untuk mengonfirmasi ini memang Anda!" + "message": "Masukkan kata sandi Anda untuk memastikan ini adalah Anda!" }, "mustSelectOne": { - "message": "Harus memilih setidaknya 1 token." + "message": "Harus memilih sekurangnya 1 token." }, "myAccounts": { "message": "Akun Saya" @@ -606,35 +1003,38 @@ "message": "Akun Dompet Saya" }, "myWalletAccountsDescription": { - "message": "Semua akun Anda yang dibuat oleh MetaMask otomatis akan ditambahkan ke bagian ini." + "message": "Semua akun Anda yang dibuat MetaMask akan secara otomatis ditambahkan ke bagian ini." }, "needEtherInWallet": { - "message": "Untuk berinteraksi dengan aplikasi terdesentralisasi menggunakan MetaMask, Anda memerlukan adanya Ether di dompet Anda." + "message": "Untuk berinteraksi dengan aplikasi yang terdesentralisasi menggunakan MetaMask, Anda memerlukan Ether di dompet Anda." }, "needImportFile": { - "message": "Anda harus memilih berkas untuk diimpor.", + "message": "Anda harus memilih file untuk diimpor.", "description": "User is important an account and needs to add a file to continue" }, "negativeETH": { - "message": "Tidak dapat mengirim nominal negatif ETH." + "message": "Tidak dapat mengirim jumlah negatif ETH." }, "networkName": { "message": "Nama Jaringan" }, + "networkSettingsChainIdDescription": { + "message": "ID rantai digunakan untuk menandatangani transaksi. Harus cocok dengan ID rantai yang dikembalikan oleh jaringan. Anda dapat memasukkan bilangan heksadesimal berawalan '0x' atau desimal, namun kami akan menampilkan bilangan tersebut dalam desimal." + }, "networkSettingsDescription": { - "message": "Tambah dan edit jaringan RPC kustom" + "message": "Tambahkan dan edit jaringan RPC kustom" }, "networks": { "message": "Jaringan" }, "nevermind": { - "message": "Abaikan" + "message": "Tidak mengapa" }, "newAccount": { "message": "Akun Baru" }, "newAccountDetectedDialogMessage": { - "message": "Alamat baru terdeteksi! Klik di sini untuk menambahkannya ke buku alamat." + "message": "Alamat baru terdeteksi! Klik di sini untuk menambahkan ke buku alamat Anda." }, "newAccountNumberName": { "message": "Akun $1", @@ -650,10 +1050,10 @@ "message": "Jaringan Baru" }, "newPassword": { - "message": "Kata Sandi Baru (min 8 karakter)" + "message": "Kata sandi baru (min. 8 karakter)" }, "newToMetaMask": { - "message": "Baru di MetaMask?" + "message": "Baru menggunakan MetaMask?" }, "newTotal": { "message": "Total Baru" @@ -664,47 +1064,85 @@ "next": { "message": "Berikutnya" }, + "nextNonceWarning": { + "message": "Nonce lebih tinggi dari nonce yang disarankan $1", + "description": "The next nonce according to MetaMask's internal logic" + }, + "noAccountsFound": { + "message": "Tidak ditemukan akun untuk kueri pencarian yang diberikan" + }, "noAddressForName": { - "message": "Belum ada alamat yang dipasang untuk nama ini." + "message": "Tidak ada alamat yang ditetapkan untuk nama ini." }, "noAlreadyHaveSeed": { - "message": "Tidak, saya sudah memiliki frasa seed" + "message": "Tidak, saya sudah memiliki frasa pemulihan" }, "noConversionRateAvailable": { - "message": "Kurs Konversi Tidak Tersedia" + "message": "Tidak Ada Nilai Konversi yang Tersedia" + }, + "noThanks": { + "message": "Tidak, Terima Kasih" }, "noTransactions": { "message": "Anda tidak memiliki transaksi" }, "noWebcamFound": { - "message": "Webcam komputer Anda tidak ditemukan. Harap coba kembali." + "message": "Webcam komputer Anda tidak ditemukan. Silakan coba lagi." }, "noWebcamFoundTitle": { "message": "Webcam tidak ditemukan" }, + "nonceField": { + "message": "Sesuaikan nonce transaksi" + }, + "nonceFieldDescription": { + "message": "Aktifkan ini untuk mengubah nonce (nomor transaksi) di layar konfirmasi. Ini adalah fitur lanjutan, gunakan dengan hati-hati." + }, + "nonceFieldHeading": { + "message": "Sesuaikan Nonce" + }, + "notCurrentAccount": { + "message": "Apa ini akun yang benar? Ini berbeda dari akun yang saat ini dipilih di dompet Anda" + }, "notEnoughGas": { - "message": "Bensin Tidak Cukup" + "message": "Biaya Jaringan Tidak Cukup" }, "ofTextNofM": { "message": "dari" }, "off": { - "message": "Mati" + "message": "Off" + }, + "offlineForMaintenance": { + "message": "Offline untuk pemeliharaan" }, "ok": { "message": "Oke" }, "on": { - "message": "Aktif" + "message": "On" + }, + "onboardingReturnNotice": { + "message": "\"$1\" akan menutup tab ini dan mengarahkan kembali ke $2", + "description": "Return the user to the site that initiated onboarding" + }, + "onlyAddTrustedNetworks": { + "message": "Penyedia jaringan Ethereum jahat dapat berbohong tentang status blockchain dan merekam aktivitas jaringan Anda. Hanya tambahkan jaringan kustom yang Anda percayai." + }, + "onlyAvailableOnMainnet": { + "message": "Hanya tersedia di mainnet" + }, + "onlyConnectTrust": { + "message": "Hanya hubungkan ke situs yang Anda percayai." }, "optionalBlockExplorerUrl": { - "message": "Blokir URL Penjelajah (opsional)" + "message": "URL Block Explorer (opsional)" }, "optionalCurrencySymbol": { - "message": "Simbol (opsional)" + "message": "Simbol Mata Uang (opsional)" }, "orderOneHere": { - "message": "Pesanlah Trezor atau Ledger dan simpan dana Anda di penyimpanan dingin" + "message": "Pesan Trezor atau Ledger dan simpan dana Anda di penyimpanan dingin" }, "origin": { "message": "Asal" @@ -713,69 +1151,94 @@ "message": "Parameter" }, "participateInMetaMetrics": { - "message": "Berpartisipasilah di MetaMetrics" + "message": "Ikut serta dalam MetaMetric" }, "participateInMetaMetricsDescription": { - "message": "Berpartisipasilah dalam MetaMetrics guna membantu kami menjadikan MetaMask lebih baik" + "message": "Ikut serta dalam MetaMetric untuk membantu kami membuat MetaMask lebih baik" }, "password": { - "message": "Sandi" + "message": "Kata sandi" }, "passwordNotLongEnough": { - "message": "Sandi kurang panjang" + "message": "Kata sandi kurang panjang" }, "passwordsDontMatch": { - "message": "Sandi Tidak Sama" + "message": "Kata Sandi Tidak Cocok" }, "pastePrivateKey": { - "message": "Tempelkan string kunci privat di sini:", + "message": "Tempel string kunci privat Anda di sini:", "description": "For importing an account from a private key" }, "pending": { - "message": "tertunda" + "message": "Tunda" + }, + "permissionCheckedIconDescription": { + "message": "Anda telah menyetujui izin ini" + }, + "permissionUncheckedIconDescription": { + "message": "Anda belum menyetujui izin ini" + }, + "permissions": { + "message": "Izin" }, "personalAddressDetected": { - "message": "Alamat personal terdeteksi. Masukkan alamat kontrak token." + "message": "Alamat pribadi terdeteksi. Masukkan alamat kontrak token." + }, + "plusXMore": { + "message": "+ $1 lagi", + "description": "$1 is a number of additional but unshown items in a list- this message will be shown in place of those items" }, "prev": { "message": "Sebelumnya" }, "primaryCurrencySetting": { - "message": "Mata Uang Utama" + "message": "Mata Uang Primer" }, "primaryCurrencySettingDescription": { - "message": "Pilih asli untuk memprioritaskan menampilkan nilai dalam mata uang asli dari rantai (cth: ETH). Pilih Fiat untuk memprioritaskan menampilkan nilai dalam mata uang fiat pilihan Anda." + "message": "Pilih asal untuk memprioritaskan nilai yang ditampilkan dalam mata uang asal rantai (contoh, ETH). Pilih Fiat untuk memprioritaskan nilai yang ditampilkan dalam mata uang fiat yang Anda pilih." }, "privacyMsg": { "message": "Kebijakan Privasi" }, "privateKey": { - "message": "Kunci Pribadi", + "message": "Kunci Privat", "description": "select this type of file to use to import an account" }, "privateKeyWarning": { - "message": "PERINGATAN: Jangan pernah mengungkap kunci ini. Siapa saja dapat mencuri aset yang tersimpan di akun Anda dengan kunci pribadi Anda." + "message": "Peringatan: Jangan ungkapkan kunci ini. Siapa pun dengan kunci privat Anda dapat mencuri aset yang disimpan di akun Anda." }, "privateNetwork": { "message": "Jaringan Privat" }, + "proposedApprovalLimit": { + "message": "Batas Persetujuan yang Diajukan" + }, "protectYourKeys": { "message": "Lindungi Kunci Anda!" }, "protectYourKeysMessage1": { - "message": "Berhati-hatilah dengan frasa seed Anda — terdapat laporan tentang website yang coba mengimitasi MetaMask. MetaMask tidak akan pernah meminta frasa seed Anda!" + "message": "Berhati-hatilah dengan frasa pemulihan Anda — ada laporan dari beberapa situs web yang mencoba membuat MetaMask imitasi. MetaMask tidak pernah meminta frasa pemulihan Anda!" }, "protectYourKeysMessage2": { - "message": "Jaga keamanan frasa Anda. Jika Anda menemukan sesuatu yang mencurigakan, atau ragu dengan sebuah situs web, kirim surel ke support@metamask.io" + "message": "Jaga frasa Anda tetap aman. Jika Anda melihat sesuatu yang mencurigakan, atau tidak yakin dengan satu situs web, hubungi lewat email di support@metamask.io" + }, + "provide": { + "message": "Berikan" }, "queue": { "message": "Antrean" }, + "queued": { + "message": "Antrean" + }, "readdToken": { - "message": "Anda dapat menambahkan token ini kembali di masa mendatang dengan memilih opsi \"Tambah Token\" di menu opsi akun Anda." + "message": "Anda dapat menambahkan token ini kembali di masa mendatang dengan membuka “Tambahkan token” di menu opsi akun Anda." }, "readyToConnect": { - "message": "Siap untuk Menyambung?" + "message": "Siap untuk Terhubung?" + }, + "receive": { + "message": "Terima" }, "recents": { "message": "Terkini" @@ -784,7 +1247,7 @@ "message": "Alamat Penerima" }, "recipientAddressPlaceholder": { - "message": "Pencarian, alamat publik (0x), atau ENS" + "message": "Cari, alamat publik (0x), atau ENS" }, "reject": { "message": "Tolak" @@ -793,7 +1256,7 @@ "message": "Tolak Semua" }, "rejectTxsDescription": { - "message": "Anda akan menolak tumpak $1 transaksi." + "message": "Anda akan menolak bertahap transaksi $1." }, "rejectTxsN": { "message": "Tolak transaksi $1" @@ -802,7 +1265,7 @@ "message": "Ditolak" }, "remindMeLater": { - "message": "Ingatkan saya nanti." + "message": "Ingatkan saya nanti" }, "remove": { "message": "Hapus" @@ -811,52 +1274,62 @@ "message": "Hapus akun" }, "removeAccountDescription": { - "message": "Akun ini akan dihapus dari dompet. Pastikan Anda memiliki frasa seed asli atau kunci privat untuk akun impor ini sebelum melanjutkan. Anda dapat mengimpor atau membuat akun lagi dari menu drop-down akun." + "message": "Akun ini akan dihapus dari dompet Anda. Pastikan Anda memiliki frasa pemulihan asli atau kunci privat untuk akun impor ini sebelum melanjutkan. Anda dapat mengimpor atau membuat akun lagi dari akun drop down. " }, "requestsAwaitingAcknowledgement": { - "message": "permintaan menunggu untuk dibenarkan" + "message": "permintaan menunggu untuk diakui" }, "required": { - "message": "Dibutuhkan" + "message": "Wajib" }, "reset": { - "message": "Setel ulang" + "message": "Atur ulang" }, "resetAccount": { - "message": "Reset Akun" + "message": "Atur Ulang Akun" }, "resetAccountDescription": { - "message": "Mengatur ulang akun akan membersihkan riwayat transaksi Anda." + "message": "Mengatur ulang akun akan mengosongkan riwayat transaksi Anda. Ini tidak akan mengubah saldo di akun atau mengharuskan Anda untuk memasukkan kembali frasa pemulihan Anda." }, "restore": { "message": "Pulihkan" }, "restoreAccountWithSeed": { - "message": "Pulihkan Akun Anda dengan Frasa Benih" + "message": "Memulihkan Akun dengan Frasa Pemulihan" }, "restoreFromSeed": { - "message": "Pulihkan Akun?" + "message": "Pulihkan akun?" + }, + "restoreWalletPreferences": { + "message": "Cadangan data Anda dari $1 telah ditemukan. Apakah Anda ingin memulihkan preferensi dompet Anda?", + "description": "$1 is the date at which the data was backed up" + }, + "retryTransaction": { + "message": "Coba Lagi Transaksi" + }, + "reusedTokenNameWarning": { + "message": "Token di sini menggunakan kembali simbol dari token lain yang Anda lihat, ini bisa jadi membingungkan atau menipu." }, "revealSeedWords": { - "message": "Singkap Kata-Kata Benih" + "message": "Mengungkapkan Frasa Pemulihan" }, "revealSeedWordsDescription": { - "message": "Jika mengganti peramban atau memindahkan komputer, Anda akan memerlukan frasa seed ini untuk mengakses akun. Simpanlah di tempat aman dan rahasia." + "message": "Jika Anda pernah mengubah browser atau mengganti komputer, Anda akan memerlukan frasa pemulihan ini untuk mengakses akun Anda. Simpan di tempat yang aman dan rahasia." }, "revealSeedWordsTitle": { - "message": "Frasa Seed" + "message": "Frasa Pemulihan" }, "revealSeedWordsWarning": { "message": "Kata-kata ini dapat digunakan untuk mencuri semua akun Anda." }, "revealSeedWordsWarningTitle": { - "message": "JANGAN sebarkan frasa ini ke siapa pun!" + "message": "JANGAN bagikan frasa ini kepada siapa pun!" }, "rinkeby": { "message": "Jaringan Uji Rinkeby" }, "ropsten": { - "message": "Jaringan Tes Ropsten" + "message": "Jaringan Uji Ropsten" }, "rpcUrl": { "message": "URL RPC Baru" @@ -865,19 +1338,25 @@ "message": "Simpan" }, "saveAsCsvFile": { - "message": "Simpan sebagai Berkas CSV" + "message": "Simpan sebagai File CSV" }, "scanInstructions": { - "message": "Tempatkan kode QR di depan kamera Anda" + "message": "Tempatkan kode QR di bagian depan kamera Anda" }, "scanQrCode": { "message": "Pindai Kode QR" }, + "scrollDown": { + "message": "Gulir ke bawah" + }, "search": { - "message": "Telusuri" + "message": "Cari" + }, + "searchAccounts": { + "message": "Cari Akun" }, "searchResults": { - "message": "Hasil Pencarian" + "message": "Cari Hasil" }, "searchTokens": { "message": "Cari Token" @@ -886,28 +1365,37 @@ "message": "Frasa Cadangan Rahasia" }, "secretBackupPhraseDescription": { - "message": "Frasa cadangan rahasia Anda akan memudahkan untuk membuat cadangan dan memulihkan akun Anda." + "message": "Frasa cadangan rahasia Anda memudahkan untuk mencadangkan dan memulihkan akun Anda." }, "secretBackupPhraseWarning": { - "message": "PERINGATAN: Jangan pernah mengungkap frasa cadangan Anda. Siapa saja dapat mengambil Ether Anda selamanya dengan frasa ini." + "message": "PERINGATAN: Jangan pernah ungkapkan frasa cadangan Anda. Siapa pun yang memiliki frasa ini dapat mengambil Ether Anda selamanya." }, "secretPhrase": { - "message": "Masukkan frasa dua belas kata rahasia Anda di sini untuk memulihkan lemari besi Anda." + "message": "Masukkan frasa kata dua belas rahasia Anda di sini untuk memulihkan vault Anda." }, "securityAndPrivacy": { "message": "Keamanan & Privasi" }, "securitySettingsDescription": { - "message": "Pengaturan privasi dan frasa seed dompet" + "message": "Pengaturan privasi dan frasa pemulihan dompet" }, "seedPhrasePlaceholder": { - "message": "Pisahkan setiap kata dengan spasi tunggal" + "message": "Pisahkan setiap kata dengan satu spasi" + }, + "seedPhrasePlaceholderPaste": { + "message": "Tempel frasa pemulihan dari clipboard" }, "seedPhraseReq": { - "message": "Frasa seed terdiri atas 12 kata" + "message": "Frasa pemulihan berisi 12, 15, 18, 21, atau 24 kata" }, "selectAHigherGasFee": { - "message": "Pilih biaya gas yang lebih tinggi untuk mempercepat proses transaksi Anda.*" + "message": "Pilih biaya jaringan yang lebih tinggi untuk mempercepat pemrosesan transaksi Anda.*" + }, + "selectAccounts": { + "message": "Pilih akun" + }, + "selectAll": { + "message": "Pilih semua" }, "selectAnAccount": { "message": "Pilih Akun" @@ -919,74 +1407,96 @@ "message": "Pilih Mata Uang" }, "selectEachPhrase": { - "message": "Silakan pilih setiap frasa untuk memastikan bahwa ini benar." + "message": "Pilih masing-masing frasa untuk memastikan kebenarannya." }, "selectHdPath": { - "message": "Pilih HD Path" + "message": "Pilih Jalur HD" }, "selectLocale": { "message": "Pilih Lokal" }, "selectPathHelp": { - "message": "Jika tidak melihat akun Buku Besar Anda saat ini di bawah, cobalah beralih jalur ke \"Legacy (MEW / MyCrypto)\"" + "message": "Jika Anda tidak melihat akun Ledger Anda yang ada di bawah, coba untuk beralih jalur ke \"Warisan (MEW / MyCrypto)\"" }, "selectType": { - "message": "Pilih Jenis" + "message": "Pilih Tipe" + }, + "selectingAllWillAllow": { + "message": "Memiih semua akan mengizinkan situs ini untuk melihat semua akun Anda saat ini. Pastikan Anda memercayai situs ini." }, "send": { "message": "Kirim" }, "sendAmount": { - "message": "Nominal Kirim" + "message": "Kirim Jumlah" }, "sendETH": { "message": "Kirim ETH" }, + "sendSpecifiedTokens": { + "message": "Kirim $1", + "description": "Symbol of the specified token" + }, "sendTokens": { "message": "Kirim Token" }, "sentEther": { - "message": "kirim ether" + "message": "ether terkirim" }, "separateEachWord": { - "message": "Pisahkan setiap kata dengan spasi tunggal" + "message": "Pisahkan setiap kata dengan satu spasi" }, "settings": { - "message": "Setelan" + "message": "Pengaturan" }, "showAdvancedGasInline": { - "message": "Kendali gas tingkat lanjut" + "message": "Kontrol biaya jaringan tingkat lanjut" }, "showAdvancedGasInlineDescription": { - "message": "Pilih ini untuk menampilkan harga gas dan batasi kontrol langsung pada layar pengiriman dan konfirmasi." + "message": "Pilih ini untuk menampilkan biaya jaringan dan kontrol batas secara langsung di layar kirim dan konfirmasi." }, "showFiatConversionInTestnets": { - "message": "Tampilkan Konversi di Testnets" + "message": "Menampilkan Konversi di Testnet" }, "showFiatConversionInTestnetsDescription": { - "message": "Pilih ini untuk menampilkan konversi fiat di Testnets" + "message": "Pilih ini untuk menampilkan konversi fiat di Testnet" }, "showHexData": { "message": "Tampilkan Data Hex" }, "showHexDataDescription": { - "message": "Pilih ini untuk menampilkan larik data heksadesimal pada layar pengiriman" + "message": "Pilih ini untuk menampilkan bidang data hex di layar kirim" + }, + "showIncomingTransactions": { + "message": "Menampilkan Transaksi yang Masuk" + }, + "showIncomingTransactionsDescription": { + "message": "Pilih ini untuk menggunakan Etherscan untuk menampilkan transaksi yang masuk di daftar transaksi" + }, + "showPermissions": { + "message": "Tampilkan Izin" }, "showPrivateKeys": { - "message": "Tampilkan Kunci Pribadi" + "message": "Tampilkan Kunci Privat" + }, + "showSeedPhrase": { + "message": "Tampilkan frasa pemulihan" }, "sigRequest": { "message": "Permintaan Tanda Tangan" }, "sign": { - "message": "Tanda tangani" + "message": "Tanda tangan" }, "signNotice": { - "message": "Menandatangani pesan ini dapat memberi efek samping yang berbahaya. Hanya tanda tangani pesan dari situs yang benar-benar Anda percayakan dengan seluruh akun Anda.\nMetode berbahaya ini akan dihapus di versi mendatang." + "message": "Menandatangani pesan ini dapat memiliki \nefek samping berbahaya. Hanya tanda tangani pesan dari \nsitus yang Anda percayai sepenuhnya dengan akun Anda seluruhnya.\n Metode berbahaya ini akan dihapus dalam versi yang akan datang. " }, "signatureRequest": { "message": "Permintaan Tanda Tangan" }, + "signatureRequest1": { + "message": "Pesan" + }, "signed": { "message": "Ditandatangani" }, @@ -994,10 +1504,10 @@ "message": "Lambat" }, "somethingWentWrong": { - "message": "Ups! Terjadi sesuatu." + "message": "Ups! Ada yang salah." }, "speedUp": { - "message": "Percepat" + "message": "Mempercepat" }, "speedUpCancellation": { "message": "Percepat pembatalan ini" @@ -1005,134 +1515,455 @@ "speedUpTransaction": { "message": "Percepat transaksi ini" }, + "spendLimitAmount": { + "message": "Jumlah batas penggunaan" + }, + "spendLimitInsufficient": { + "message": "Batas penggunaan tidak mencukupi" + }, + "spendLimitInvalid": { + "message": "Batas penggunaan tidak valid; harus berupa bilangan positif" + }, + "spendLimitPermission": { + "message": "Izin batas penggunaan" + }, + "spendLimitRequestedBy": { + "message": "Batas penggunaan diminta oleh $1", + "description": "Origin of the site requesting the spend limit" + }, + "spendLimitTooLarge": { + "message": "Batas penggunaan terlalu besar" + }, "stateLogError": { - "message": "Kesalahan dalam mengambil log kondisi." + "message": "Kesalahan dalam log status pengambilan." + }, + "stateLogFileName": { + "message": "Log Status MetaMask" }, "stateLogs": { - "message": "Log Kondisi" + "message": "Log Status" }, "stateLogsDescription": { - "message": "Log status mengandung alamat akun publik dan transaksi terkirim Anda." + "message": "Log status berisi alamat akun publik Anda dan transaksi terkirim." + }, + "statusConnected": { + "message": "Terhubung" + }, + "statusNotConnected": { + "message": "Tidak terhubung" }, "step1HardwareWallet": { - "message": "1. Hubungkan Dompet Peranti Keras" + "message": "1. Hubungkan Dompet Perangkat Keras" }, "step1HardwareWalletMsg": { - "message": "Hubungkan dompet perangkat keras Anda langsung ke komputer Anda." + "message": "Hubungkan dompet perangkat keras Anda langsung ke komputer." }, "step2HardwareWallet": { "message": "2. Pilih Akun" }, "step2HardwareWalletMsg": { - "message": "Pilih akun yang ingin Anda tinjau. Anda hanya dapat memilih satu akun pada satu waktu." + "message": "Pilih akun yang ingin Anda lihat. Anda hanya dapat memilih satu pada satu waktu." }, "step3HardwareWallet": { - "message": "3. Mulai gunakan dApps dan lainnya!" + "message": "3. Mulai menggunakan situs web3 dan lainnya!" }, "step3HardwareWalletMsg": { - "message": "Gunakan akun peranti keras Anda seperti layaknya akun Ethereum. Masuklah ke dApps, kirim Eth, beli dan simpan token ERC20 dan token Non-Fungible seperti CryptoKitties." + "message": "Gunakan akun perangkat keras Anda seperti yang akan Anda lakukan dengan akun Ethereum lainnya. Hubungkan ke situs web3, kirim ETH, beli dan simpan token ERC20 dan token yang tidak dapat dipertukarkan seperti CryptoKitties." }, "storePhrase": { - "message": "Simpan frasa ini dalam manajer sandi seperti 1Password." + "message": "Simpan frasa ini dalam pengelola kata sandi seperti 1Password." + }, + "submit": { + "message": "Kirim" }, "submitted": { "message": "Terkirim" }, "supportCenter": { - "message": "Kunjungi Pusat Bantuan kami" + "message": "Kunjungi Pusat Dukungan kami" + }, + "swap": { + "message": "Tukar" + }, + "swapAdvancedSlippageInfo": { + "message": "Jika harga berubah antara waktu pesanan Anda ditempatkan dan dikonfirmasi, ini disebut “slippage”. Penukaran Anda akan otomatis dibatalkan jika slippage melebihi pengaturan “slippage maks.”" + }, + "swapAggregator": { + "message": "Agregator" + }, + "swapAmountReceived": { + "message": "Jumlah yang dijamin" + }, + "swapAmountReceivedInfo": { + "message": "Ini adalah jumlah minimum yang akan Anda terima. Anda dapat menerima lebih banyak tergantung pada slippage." + }, + "swapApproval": { + "message": "Setujui $1 untuk penukaran", + "description": "Used in the transaction display list to describe a transaction that is an approve call on a token that is to be swapped.. $1 is the symbol of a token that has been approved." + }, + "swapApproveNeedMoreTokens": { + "message": "Anda memerlukan $1 lagi $2 untuk menyelesaikan penukaran ini", + "description": "Tells the user how many more of a given token they need for a specific swap. $1 is an amount of tokens and $2 is the token symbol." + }, + "swapBuildQuotePlaceHolderText": { + "message": "Tidak ada token yang cocok yang tersedia $1", + "description": "Tells the user that a given search string does not match any tokens in our token lists. $1 can be any string of text" + }, + "swapCheckingQuote": { + "message": "Memeriksa $1", + "description": "Shown to the user during quote loading. $1 is the name of an aggregator. The message indicates that metamask is currently checking if that aggregator has a trade/quote for their requested swap." + }, + "swapCustom": { + "message": "kustom" + }, + "swapDecentralizedExchange": { + "message": "Penukaran terdesentralisasi" + }, + "swapEditLimit": { + "message": "Edit batas" + }, + "swapEnableDescription": { + "message": "Ini wajib dan memberikan MetaMask izin untuk menukar $1 Anda.", + "description": "Gives the user info about the required approval transaction for swaps. $1 will be the symbol of a token being approved for swaps." + }, + "swapEstimatedNetworkFee": { + "message": "Biaya jaringan yang diperkirakan" + }, + "swapEstimatedNetworkFeeSummary": { + "message": "“$1” adalah yang kami harapkan untuk biaya yang seharusnya. Jumlah yang tepat tergantung pada kondisi jaringan.", + "description": "$1 will be the translation of swapEstimatedNetworkFee, with the font bolded" + }, + "swapEstimatedNetworkFees": { + "message": "Biaya jaringan yang diperkirakan" + }, + "swapEstimatedNetworkFeesInfo": { + "message": "Ini adalah perkiraan biaya jaringan yang akan digunakan untuk menyelesaikan penukaran Anda. Jumlah aktual dapat berubah sesuai dengan kondisi jaringan." + }, + "swapFailedErrorDescription": { + "message": "Dana Anda aman dan masih tersedia di dompet Anda." + }, + "swapFailedErrorTitle": { + "message": "Penukaran gagal" + }, + "swapFetchingQuotesErrorDescription": { + "message": "Hmmm... ada yang salah. Coba lagi, atau jika masalah masih ada, hubungi dukungan pelanggan." + }, + "swapFetchingQuotesErrorTitle": { + "message": "Kesalahan dalam mengambil kuota" + }, + "swapFetchingTokens": { + "message": "Mengambil token..." + }, + "swapFinalizing": { + "message": "Menyelesaikan..." + }, + "swapGetQuotes": { + "message": "Dapatkan kuota" + }, + "swapHighSlippageWarning": { + "message": "Jumlah slippage sangat tinggi. Pastikan Anda mengetahui yang Anda kerjakan!" + }, + "swapIntroLearnMoreHeader": { + "message": "Ingin mempelajari selengkapnya?" + }, + "swapIntroLearnMoreLink": { + "message": "Pelajari selengkapnya tentang Penukaran MetaMask" + }, + "swapIntroLiquiditySourcesLabel": { + "message": "Sumber likuiditas mencakup:" + }, + "swapIntroPopupSubTitle": { + "message": "Sekarang, Anda bisa menukar token secara langsung di dompet MetaMask Anda. Penukaran MetaMask menggabungkan beberapa agregator penukaran terdesentralisasi, pembuat pasar profesional, dan DEX individu untuk memastikan pengguna MetaMask selalu mendapatkan harga terbaik dengan biaya jaringan terendah." + }, + "swapIntroPopupTitle": { + "message": "Penukaran token ada di sini!" + }, + "swapLearnMoreContractsAuditReview": { + "message": "Tinjau audit kontrak resmi kami" + }, + "swapLowSlippageError": { + "message": "Transaksi bisa gagal, slippage maks. terlalu rendah." + }, + "swapMaxNetworkFeeInfo": { + "message": "“$1” adalah yang paling banyak yang akan Anda gunakan. Bila jaringan tidak stabil ini bisa menjadi jumlah yang besar.", + "description": "$1 will be the translation of swapMaxNetworkFees, with the font bolded" + }, + "swapMaxNetworkFees": { + "message": "Biaya jaringan maks." + }, + "swapMaxSlippage": { + "message": "Maks. slippage" + }, + "swapMetaMaskFee": { + "message": "Biaya MetaMask" + }, + "swapMetaMaskFeeDescription": { + "message": "Kami menemukan harga terbaik dari sumber likuiditas teratas, setiap waktu. Biaya sebesar $1% secara otomatis diperhitungkan ke dalam setiap kuota, yang mendukung pengembangan berkelanjutan untuk membuat MetaMask lebih baik lagi.", + "description": "Provides information about the fee that metamask takes for swaps. $1 is a decimal number." + }, + "swapNetworkFeeSummary": { + "message": "Biaya jaringan mencakup biaya pemrosesan penukaran Anda dan menyimpannya di jaringan Ethereum. MetaMask tidak mendapatkan keuntungan dari biaya ini." + }, + "swapNewQuoteIn": { + "message": "Kuota baru di $1", + "description": "Tells the user the amount of time until the currently displayed quotes are update. $1 is a time that is counting down from 1:00 to 0:00" + }, + "swapOnceTransactionHasProcess": { + "message": "$1 akan ditambahkan ke akun Anda setelah transaksi ini diproses.", + "description": "This message communicates the token that is being transferred. It is shown on the awaiting swap screen. The $1 will be a token symbol." + }, + "swapProcessing": { + "message": "Memproses" + }, + "swapQuoteDetails": { + "message": "Detail kuota" + }, + "swapQuoteDetailsSlippageInfo": { + "message": "Jika harga berubah antara waktu pesanan Anda ditempatkan dan dikonfirmasi, ini disebut \"slippage\". Penukaran Anda akan otomatis dibatalkan jika slippage melebihi pengaturan \"slippage maks.\"." + }, + "swapQuoteIncludesRate": { + "message": "Kuota mencakup biaya MetaMask $1%", + "description": "Provides information about the fee that metamask takes for swaps. $1 is a decimal number." + }, + "swapQuoteNofN": { + "message": "Kuota $1 dari $2", + "description": "A count of loaded quotes shown to the user while they are waiting for quotes to be fetched. $1 is the number of quotes already loaded, and $2 is the total number of quotes to load." + }, + "swapQuoteSource": { + "message": "Sumber kuota" + }, + "swapQuotesAreRefreshed": { + "message": "Kuota disegarkan sering kali untuk menerapkan kondisi pasar terkini." + }, + "swapQuotesExpiredErrorDescription": { + "message": "Silakan minta kuota baru untuk mendapatkan tarif terbaru." + }, + "swapQuotesExpiredErrorTitle": { + "message": "Waktu habis kuota" + }, + "swapQuotesNotAvailableErrorDescription": { + "message": "Cobalah untuk menyesuaikan pengaturan slippage atau jumlah dan coba lagi." + }, + "swapQuotesNotAvailableErrorTitle": { + "message": "Tidak ada kuota yang tersedia" + }, + "swapRate": { + "message": "Tarif" + }, + "swapReceiving": { + "message": "Menerima" + }, + "swapReceivingInfoTooltip": { + "message": "Ini adalah perkiraan. Jumlah yang tepat tergantung pada slippage." + }, + "swapRequestForQuotation": { + "message": "Meminta penawaran" + }, + "swapSearchForAToken": { + "message": "Cari token" + }, + "swapSelect": { + "message": "Pilih" + }, + "swapSelectAQuote": { + "message": "Pilih kuota" + }, + "swapSelectAToken": { + "message": "Pilih token" + }, + "swapSelectQuotePopoverDescription": { + "message": "Di bawah ini adalah semua kuota yang dikumpulkan dari beberapa sumber likuiditas." + }, + "swapSlippageTooLow": { + "message": "Slippage harus lebih besar dari nol" + }, + "swapSource": { + "message": "Sumber likuiditas" + }, + "swapSourceInfo": { + "message": "Kami mencari beberapa sumber likuiditas (penukaran, agregator, dan pembuat pasar profesional) untuk menemukan tarif terbaik dan biaya jaringan terendah." + }, + "swapStartSwapping": { + "message": "Mulai menukar" + }, + "swapSwapFrom": { + "message": "Tukar dari" + }, + "swapSwapSwitch": { + "message": "Tukar dari dan untuk token" + }, + "swapSwapTo": { + "message": "Tukar untuk" + }, + "swapThisWillAllowApprove": { + "message": "Ini akan memungkinkan $1 untuk ditukar." + }, + "swapTokenAvailable": { + "message": "$1 Anda telah ditambahkan ke akun Anda.", + "description": "This message is shown after a swap is successful and communicates the exact amount of tokens the user has received for a swap. The $1 is a decimal number of tokens followed by the token symbol." + }, + "swapTokenToToken": { + "message": "Tukar $1 untuk $2", + "description": "Used in the transaction display list to describe a swap. $1 and $2 are the symbols of tokens in involved in a swap." + }, + "swapTransactionComplete": { + "message": "Transaksi selesai" + }, + "swapUnknown": { + "message": "Tidak diketahui" + }, + "swapVerifyTokenExplanation": { + "message": "Beberapa token dapat menggunakan simbol dan nama yang sama. Periksa Etherscan untuk memverifikasi inilah token yang Anda cari." + }, + "swapViewToken": { + "message": "Lihat $1" + }, + "swapYourTokenBalance": { + "message": "$1 $2 tersedia untuk ditukar", + "description": "Tells the user how much of a token they have in their balance. $1 is a decimal number amount of tokens, and $2 is a token symbol" + }, + "swapZeroSlippage": { + "message": "0% Slippage" + }, + "swapsAdvancedOptions": { + "message": "Opsi Tingkat Lanjut" + }, + "swapsMaxSlippage": { + "message": "Maks. slippage" + }, + "swapsNotEnoughForTx": { + "message": "Tidak cukup $1 untuk menyelesaikan transaksi ini", + "description": "Tells the user that they don't have enough of a token for a proposed swap. $1 is a token symbol" + }, + "swapsViewInActivity": { + "message": "Lihat dalam aktivitas" }, "switchNetworks": { - "message": "Ganti Jaringan" + "message": "Beralih Jaringan" + }, + "switchToThisAccount": { + "message": "Beralih ke akun ini" }, "symbol": { "message": "Simbol" }, "symbolBetweenZeroTwelve": { - "message": "Simbol harus antara 0 sampai 12 karakter." + "message": "Simbol harus terdiri dari 11 karakter atau kurang." }, "syncWithMobile": { - "message": "Sinkronkan dengan ponsel" + "message": "Sinkronisasi dengan seluler" }, "syncWithMobileBeCareful": { - "message": "Pastikan tidak ada yang melihat ke layar ketika kode ini Anda pindai" + "message": "Pastikan tidak ada orang lain yang melihat layar Anda saat memindai kode ini" }, "syncWithMobileComplete": { - "message": "Data Anda telah berhasil disinkronkan. Nikmati aplikasi mobile MetaMask!" + "message": "Data Anda telah berhasil disinkronkan. Nikmati aplikasi seluler MetaMask!" }, "syncWithMobileDesc": { - "message": "Anda dapat menyinkronkan akun dan informasi Anda dengan perangkat seluler. Buka aplikasi seluler MetaMask, pilih \"Pengaturan\" lalu ketuk \"Sinkronkan dari Ekstensi Peramban\"" + "message": "Anda dapat menyinkronkan akun dan informasi dengan perangkat seluler Anda. Buka aplikasi seluler MetaMask, buka \"Pengaturan\" dan ketuk \"Sinkronkan dari Ekstensi Browser\"" }, "syncWithMobileDescNewUsers": { - "message": "Jika Anda baru saja membuka aplikasi MetaMask Mobile untuk pertama kali, ikuti langkah-langkah pada ponsel Anda." + "message": "Jika Anda baru membuka aplikasi seluler MetaMask untuk pertama kali, cukup ikuti langkah-langkah yang ada di ponsel Anda." }, "syncWithMobileScanThisCode": { - "message": "Pindai kode ini dengan aplikasi ponsel MetaMask " + "message": "Pindai kode ini dengan aplikasi seluler MetaMask Anda" }, "syncWithMobileTitle": { - "message": "Sinkronkan dengan seluler" + "message": "Sinkronisasi dengan seluler" + }, + "syncWithThreeBox": { + "message": "Sinkronkan data dengan 3Box (eksperimen)" + }, + "syncWithThreeBoxDescription": { + "message": "Aktifkan agar pengaturan Anda dicadangkan dengan 3Box. Fitur ini sekarang dalam masa percobaan; gunakan dengan risiko Anda sendiri." + }, + "syncWithThreeBoxDisabled": { + "message": "3Box telah dinonaktifkan karena terdapat kesalahan selama sinkronisasi awal" }, "terms": { "message": "Syarat Penggunaan" }, + "termsOfService": { + "message": "Syarat Layanan" + }, "testFaucet": { - "message": "Tes Keran" + "message": "Uji Fungsi" }, "thisWillCreate": { - "message": "Ini akan membuat dompet dan frasa seed baru" + "message": "Ini akan membuat frasa pemulihan dan dompet baru" }, "tips": { - "message": "Tip" + "message": "Kiat" }, "to": { - "message": "Ke" + "message": "Untuk" + }, + "toAddress": { + "message": "Untuk: $1", + "description": "$1 is the address to include in the To label. It is typically shortened first using shortenAddress" + }, + "toWithColon": { + "message": "Untuk:" + }, + "token": { + "message": "Token" }, "tokenAlreadyAdded": { - "message": "Token sudah ditambahkan." + "message": "Token telah ditambahkan." }, "tokenContractAddress": { "message": "Alamat Kontrak Token" }, + "tokenOptions": { + "message": "Opsi token" + }, "tokenSymbol": { "message": "Simbol Token" }, + "total": { + "message": "Total" + }, "transaction": { "message": "transaksi" }, "transactionCancelAttempted": { - "message": "Pembatalan transaksi dicoba dengan biaya gas sebesar $1 di $2" + "message": "Pembatalan transaksi diupayakan dengan biaya jaringan sebesar $1 pada $2" }, "transactionCancelSuccess": { - "message": "Transaksi berhasil dibatalkan di $2." + "message": "Transaksi berhasil dibatalkan pada $2" }, "transactionConfirmed": { - "message": "Transaksi dikonfirmasi di $2." + "message": "Transaksi dikonfirmasi pada $2." }, "transactionCreated": { - "message": "Transaksi dibuat dengan nilai $1 di $2." + "message": "Transaksi dibuat dengan nilai sebesar $1 pada $2." }, "transactionDropped": { - "message": "Transaksi dibatalkan di $2." + "message": "Transaksi jatuh pada $2." }, "transactionError": { - "message": "Eror Transaksi. Pengecualian dimasukkan ke dalam kode kontrak." + "message": "Kesalahan Transaksi. Pengecualian diberikan dalam kode kontrak." }, "transactionErrorNoContract": { "message": "Mencoba memanggil fungsi pada alamat non-kontrak." }, "transactionErrored": { - "message": "Transaksi mengalami eror." + "message": "Transaksi mengalami kesalahan." }, "transactionFee": { "message": "Biaya Transaksi" }, "transactionResubmitted": { - "message": "Transaksi dikirim ulang dengan biaya gas meningkat menjadi $1 di $2" + "message": "Transaksi dikirim kembali dengan biaya jaringan naik $1 pada $2" }, "transactionSubmitted": { - "message": "Transaksi diajukan dengan biaya gas sebesar $1 di $2." + "message": "Transaksi dkirim kembali dengan biaya jaringan sebesar $1 pada $2." }, "transactionUpdated": { - "message": "Transaksi diperbarui di $2." + "message": "Transaksi diperbarui pada $2." + }, + "transfer": { + "message": "Transfer" }, "transferBetweenAccounts": { "message": "Transfer antar akun saya" @@ -1140,54 +1971,78 @@ "transferFrom": { "message": "Transfer Dari" }, + "troubleConnectingToWallet": { + "message": "Kami mengalami masalah untuk terhubung ke $1 Anda, coba lihat kembali $2 dan coba lagi.", + "description": "$1 is the wallet device name; $2 is a link to wallet connection guide" + }, "troubleTokenBalances": { - "message": "Kami menemui masalah dalam memuat saldo token. Anda dapat melihatnya", + "message": "Kami mengalami masalah saat memuat saldo token Anda. Anda dapat melihatnya ", "description": "Followed by a link (here) to view token balances" }, + "trustSiteApprovePermission": { + "message": "Anda percaya situs ini? Dengan memberikan izin ini, Anda mengizinkan $1 untuk menarik $2 Anda dan mengotomatiskan transaksi untuk Anda.", + "description": "$1 is the url requesting permission and $2 is the symbol of the currency that the request is for" + }, "tryAgain": { "message": "Coba lagi" }, "typePassword": { - "message": "Ketik kata sandi MetaMask Anda" + "message": "Ketikkan kata sandi MetaMask Anda" }, "unapproved": { - "message": "Tak disetujui" + "message": "Tidak disetujui" }, "units": { "message": "unit" }, "unknown": { - "message": "Tidak dikenal" + "message": "Tidak diketahui" }, "unknownCameraError": { - "message": "Terjadi eror saat mencoba mengakses kamera. Harap coba ulang..." + "message": "Ada kesalahan sewaktu mencoba mengakses kamera Anda. Silakan coba lagi..." }, "unknownCameraErrorTitle": { - "message": "Ups! Terjadi sesuatu..." + "message": "Ups! Ada yang salah..." }, "unknownNetwork": { - "message": "Jaringan Pribadi Tak Dikenal" + "message": "Jaringan Privat Tidak Dikenal" }, "unknownQrCode": { "message": "Kesalahan: Kami tidak dapat mengidentifikasi kode QR itu" }, + "unlimited": { + "message": "Tidak terbatas" + }, "unlock": { - "message": "Buka kunci" + "message": "Tidak terkunci" }, "unlockMessage": { - "message": "Web terdesentralisasi menanti" + "message": "Web terdesentralisasi menunggu" }, "updatedWithDate": { "message": "Diperbarui $1" }, "urlErrorMsg": { - "message": "URI memerlukan awalan HTTP/HTTPS yang sesuai." + "message": "URL memerlukan awalan HTTP/HTTPS yang sesuai." + }, + "urlExistsErrorMsg": { + "message": "URL sudah ada dalam daftar jaringan yang ada" + }, + "usePhishingDetection": { + "message": "Menggunakan Deteksi Phishing" + }, + "usePhishingDetectionDescription": { + "message": "Menampilkan peringatan untuk domain phishing yang menargetkan pengguna Ethereum" }, "usedByClients": { - "message": "Digunakan oleh berbagai klien" + "message": "Digunakan oleh berbagai klien yang berbeda" }, "userName": { - "message": "Nama Pengguna" + "message": "Nama pengguna" + }, + "verifyThisTokenOn": { + "message": "Verifikasikan token ini di $1", + "description": "Points the user to etherscan as a place they can verify information about a token. $1 is replaced with the translation for \"etherscan\"" }, "viewAccount": { "message": "Lihat Akun" @@ -1205,33 +2060,43 @@ "message": "Lihat di Explorer" }, "visitWebSite": { - "message": "Kunjungi website kami" + "message": "Kunjungi situs web kami" + }, + "walletConnectionGuide": { + "message": "panduan koneksi dompet perangkat keras kami" }, "walletSeed": { - "message": "Benih Dompet" + "message": "Frasa pemulihan" }, "welcome": { - "message": "Selamat Datang di MetaMask" + "message": "Selamat datang di MetaMask" }, "welcomeBack": { "message": "Selamat Datang Kembali!" }, + "whatsThis": { + "message": "Apa ini?" + }, "writePhrase": { - "message": "Tuliskan frasa ini di selembar kertas dan simpan di tempat aman. Jika ingin lebih aman, tulislah di beberapa lembar kertas dan simpan masing-masing kertas di 2 - 3 lokasi berbeda." + "message": "Tulis frasa ini pada selembar kertas dan simpan di tempat yang aman. Jika Anda ingin lebih aman lagi, tuliskan pada beberapa lembar kertas dan simpan masing-masing di 2-3 tempat berbeda." + }, + "xOfY": { + "message": "$1 dari $2", + "description": "$1 and $2 are intended to be two numbers, where $2 is a total, and $1 is a count towards that total" }, "yesLetsTry": { - "message": "Ya, ayo kita coba" + "message": "Ya, mari kita coba" }, "youNeedToAllowCameraAccess": { - "message": "Anda perlu mengizinkan akses kamera untuk menggunakan fitur ini." + "message": "Anda harus mengizinkan akses kamera untuk menggunakan fitur ini." }, "youSign": { - "message": "Anda menandatangani" + "message": "Anda sudah masuk" }, "yourPrivateSeedPhrase": { - "message": "Frase benih pribadi Anda" + "message": "Frasa pemulihan privat Anda" }, "zeroGasPriceOnSpeedUpError": { - "message": "Harga gas nol saat mempercepat" + "message": "Biaya jaringan nol dipercepat" } } From fc409a103b1ac2bf28ac53544dbe10e457fe5014 Mon Sep 17 00:00:00 2001 From: Etienne Dusseault Date: Thu, 4 Feb 2021 09:23:12 +0800 Subject: [PATCH 28/48] Add .yarnrc to disable scripts (#10354) * add yarn rc file to disable scripts * remove ignore scripts in CI * re-add entry * add lavamoat preinstall always fail * allow-scripts - add missing package to denylist Co-authored-by: kumavis --- .circleci/scripts/deps-install.sh | 2 +- .yarnrc | 1 + package.json | 4 +++- yarn.lock | 5 +++++ 4 files changed, 10 insertions(+), 2 deletions(-) create mode 100644 .yarnrc diff --git a/.circleci/scripts/deps-install.sh b/.circleci/scripts/deps-install.sh index 06b4748a9..cba42c416 100755 --- a/.circleci/scripts/deps-install.sh +++ b/.circleci/scripts/deps-install.sh @@ -5,7 +5,7 @@ set -x # Exit immediately if a command exits with a non-zero status. set -e -yarn --frozen-lockfile --ignore-scripts --har +yarn --frozen-lockfile --har # Move HAR file into directory with consistent name so that we can cache it mkdir -p build-artifacts/yarn-install-har diff --git a/.yarnrc b/.yarnrc new file mode 100644 index 000000000..2088d635c --- /dev/null +++ b/.yarnrc @@ -0,0 +1 @@ +ignore-scripts true \ No newline at end of file diff --git a/package.json b/package.json index c731fbfe4..6fd78e3cb 100644 --- a/package.json +++ b/package.json @@ -75,6 +75,7 @@ "@download/blockies": "^1.0.3", "@formatjs/intl-relativetimeformat": "^5.2.6", "@fortawesome/fontawesome-free": "^5.13.0", + "@lavamoat/preinstall-always-fail": "^1.0.0", "@material-ui/core": "^4.11.0", "@metamask/contract-metadata": "^1.22.0", "@metamask/controllers": "^5.1.0", @@ -322,7 +323,8 @@ "ursa-optional": false, "gc-stats": false, "github:assemblyscript/assemblyscript": false, - "tiny-secp256k1": false + "tiny-secp256k1": false, + "@lavamoat/preinstall-always-fail": false } } } diff --git a/yarn.lock b/yarn.lock index f937017d1..89f28bf8b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1962,6 +1962,11 @@ yargs "^16.2.0" yarn-logical-tree "^1.0.2" +"@lavamoat/preinstall-always-fail@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@lavamoat/preinstall-always-fail/-/preinstall-always-fail-1.0.0.tgz#e78a6e3d9e212a4fef869ec37d4f5fb498dea373" + integrity sha512-vD2DcC0ffJj1w2y1Lu0OU39wHmlPEd2tCDW04Bm6Kf4LyRnCHCezTsS8yzeSJ+4so7XP+TITuR5FGJRWxPb+GA== + "@material-ui/core@^4.11.0": version "4.11.0" resolved "https://registry.yarnpkg.com/@material-ui/core/-/core-4.11.0.tgz#b69b26e4553c9e53f2bfaf1053e216a0af9be15a" From b2d40f4e3a95359d2a112ad6e5af2ebe35b95a8e Mon Sep 17 00:00:00 2001 From: kumavis Date: Thu, 4 Feb 2021 21:09:45 +0800 Subject: [PATCH 29/48] deps - bump allow-scripts (#10370) --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 6fd78e3cb..e6c0fa917 100644 --- a/package.json +++ b/package.json @@ -191,7 +191,7 @@ "@babel/preset-env": "^7.5.5", "@babel/preset-react": "^7.0.0", "@babel/register": "^7.5.5", - "@lavamoat/allow-scripts": "^1.0.0", + "@lavamoat/allow-scripts": "^1.0.3", "@metamask/eslint-config": "^4.1.0", "@metamask/forwarder": "^1.1.0", "@metamask/test-dapp": "^4.0.1", diff --git a/yarn.lock b/yarn.lock index 89f28bf8b..4808fa604 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1951,10 +1951,10 @@ "@types/yargs" "^15.0.0" chalk "^3.0.0" -"@lavamoat/allow-scripts@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@lavamoat/allow-scripts/-/allow-scripts-1.0.0.tgz#b24de0b179f1b16aae7bc15d21948bd774fb05e9" - integrity sha512-xY98CJu2BAFirfZ+w4wRQxAMlolfFj7L5sIkUdZPlhFYIZjNis8kGKxvxN4uscbIOILS14nSIbGqrUwEddPGrA== +"@lavamoat/allow-scripts@^1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@lavamoat/allow-scripts/-/allow-scripts-1.0.3.tgz#8fa54a3f250977fdc85484d0870ae65c4e50a0c8" + integrity sha512-bzRYwOqjx5UU2vQYIV/QZYQGDA1Nm4lXipTUCK4UNBwGSwYlK8A1SUrQdX+Rp0ASbr/mb8IH6rPIjz1LgsDbDA== dependencies: "@npmcli/run-script" "^1.8.1" "@yarnpkg/lockfile" "^1.1.0" From da18091d8ee1409f0d823c6d6a0e625ceecd76eb Mon Sep 17 00:00:00 2001 From: Richard Gordon Date: Thu, 4 Feb 2021 08:11:05 -0500 Subject: [PATCH 30/48] fix(typo): unapprived unapproved (#10366) --- ui/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/index.js b/ui/index.js index 3f0e172f8..660209804 100644 --- a/ui/index.js +++ b/ui/index.js @@ -118,8 +118,8 @@ async function startApp(metamaskState, backgroundConnection, opts) { metamaskState.unapprovedTypedMessages, metamaskState.network, ) - const numberOfUnapprivedTx = unapprovedTxsAll.length - if (numberOfUnapprivedTx > 0) { + const numberOfUnapprovedTx = unapprovedTxsAll.length + if (numberOfUnapprovedTx > 0) { store.dispatch( actions.showConfTxPage({ id: unapprovedTxsAll[0].id, From b52d82ac279696d3b7532584e2c33d63e79af25f Mon Sep 17 00:00:00 2001 From: kumavis Date: Thu, 4 Feb 2021 21:13:00 +0800 Subject: [PATCH 31/48] ci/benchmark - increase executor size to medium+ (#10361) --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index c2c7f8a46..d1e8651ad 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -367,7 +367,7 @@ jobs: destination: test-artifacts benchmark: - executor: node-browsers + executor: node-browsers-medium-plus steps: - checkout - run: From efd280172f5f5e1e6d884a71ac789d0782a98742 Mon Sep 17 00:00:00 2001 From: kumavis Date: Thu, 4 Feb 2021 22:30:22 +0800 Subject: [PATCH 32/48] ci - run storybook and add to build-artifacts (#10360) * ci - run storybook and add to build-artifacts * ci/storybook - rename storybook build path and fix artifact upload * ci/storybook - rename link text * clean - remove accidently committed storybook build dir * storybook - fix image path to relative (#10364) --- .circleci/config.yml | 6 +++++- .gitignore | 2 +- development/metamaskbot-build-announce.js | 4 ++++ package.json | 4 ++-- ui/app/components/ui/box/box.stories.js | 2 +- 5 files changed, 13 insertions(+), 5 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index d1e8651ad..9ebde782f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -90,6 +90,7 @@ workflows: requires: - prep-deps - prep-build + - prep-build-storybook - benchmark - all-tests-pass - job-publish-release: @@ -214,7 +215,7 @@ jobs: - persist_to_workspace: root: . paths: - - .out + - storybook-build test-lint: executor: node-browsers @@ -416,6 +417,9 @@ jobs: - store_artifacts: path: build-artifacts destination: build-artifacts + - store_artifacts: + path: storybook-build + destination: storybook - run: name: build:announce command: ./development/metamaskbot-build-announce.js diff --git a/.gitignore b/.gitignore index 46064a64b..5e46dd1e0 100644 --- a/.gitignore +++ b/.gitignore @@ -26,7 +26,7 @@ temp .DS_Store app/.DS_Store -.out/ +storybook-build/ coverage/ dist builds/ diff --git a/development/metamaskbot-build-announce.js b/development/metamaskbot-build-announce.js index d029e4fc5..8ea766ed3 100755 --- a/development/metamaskbot-build-announce.js +++ b/development/metamaskbot-build-announce.js @@ -58,6 +58,9 @@ async function start() { const coverageUrl = `${BUILD_LINK_BASE}/coverage/index.html` const coverageLink = `Report` + const storybookUrl = `${BUILD_LINK_BASE}/storybook/index.html` + const storybookLink = `Storybook` + // link to artifacts const allArtifactsUrl = `https://circleci.com/gh/MetaMask/metamask-extension/${CIRCLE_BUILD_NUM}#artifacts/containers/0` @@ -65,6 +68,7 @@ async function start() { `builds: ${buildLinks}`, `bundle viz: ${bundleLinks}`, `code coverage: ${coverageLink}`, + `storybook: ${storybookLink}`, `all artifacts`, ] const hiddenContent = `
      ${contentRows diff --git a/package.json b/package.json index e6c0fa917..cb6ae4c97 100644 --- a/package.json +++ b/package.json @@ -48,8 +48,8 @@ "start:dev": "concurrently -k -n build,react,redux yarn:start yarn:devtools:react yarn:devtools:redux", "announce": "node development/announcer.js", "storybook": "start-storybook -p 6006 -c .storybook --static-dir ./app ./storybook/images", - "storybook:build": "build-storybook -c .storybook -o .out --static-dir ./app ./storybook/images", - "storybook:deploy": "storybook-to-ghpages --existing-output-dir .out --remote storybook --branch master", + "storybook:build": "build-storybook -c .storybook -o storybook-build --static-dir ./app ./storybook/images", + "storybook:deploy": "storybook-to-ghpages --existing-output-dir storybook-build --remote storybook --branch master", "update-changelog": "./development/auto-changelog.sh", "generate:migration": "./development/generate-migration.sh" }, diff --git a/ui/app/components/ui/box/box.stories.js b/ui/app/components/ui/box/box.stories.js index 324e642b2..bae0f257a 100644 --- a/ui/app/components/ui/box/box.stories.js +++ b/ui/app/components/ui/box/box.stories.js @@ -25,7 +25,7 @@ export const box = () => { 'children', ) for (let $i = 0; $i < number('items', 1, {}, 'children'); $i++) { - items.push() + items.push() } return ( Date: Thu, 4 Feb 2021 09:58:46 -0600 Subject: [PATCH 33/48] Implement price impact acknowledgement button (#10347) --- app/_locales/en/messages.json | 6 ++ ui/app/pages/swaps/view-quote/index.scss | 37 +++++++-- .../tests/view-quote-price-difference.test.js | 2 +- .../view-quote/view-quote-price-difference.js | 77 ++++++++----------- ui/app/pages/swaps/view-quote/view-quote.js | 75 +++++++++++++++--- 5 files changed, 139 insertions(+), 58 deletions(-) diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index affb60904..39e111cb7 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -1735,6 +1735,12 @@ "message": "You are about to swap $1 $2 (~$3) for $4 $5 (~$6).", "description": "This message represents the price slippage for the swap. $1 and $4 are a number (ex: 2.89), $2 and $5 are symbols (ex: ETH), and $3 and $6 are fiat currency amounts." }, + "swapPriceDifferenceAcknowledgement": { + "message": "I'm aware" + }, + "swapPriceDifferenceAcknowledgementNoFiat": { + "message": "Continue" + }, "swapPriceDifferenceTitle": { "message": "Price difference of ~$1%", "description": "$1 is a number (ex: 1.23) that represents the price difference." diff --git a/ui/app/pages/swaps/view-quote/index.scss b/ui/app/pages/swaps/view-quote/index.scss index 397748c2a..20c2ea0b4 100644 --- a/ui/app/pages/swaps/view-quote/index.scss +++ b/ui/app/pages/swaps/view-quote/index.scss @@ -15,6 +15,11 @@ padding-right: 20px; justify-content: space-between; + &_modal > div:not(.view-quote__warning-wrapper) { + opacity: 0.6; + pointer-events: none; + } + @media screen and (max-width: 576px) { overflow-y: auto; max-height: 428px; @@ -98,14 +103,30 @@ .actionable-message__message { color: inherit; } + + button { + background: $Yellow-500; + border-radius: 42px; + } } - &.high .actionable-message { - border-color: $Red-500; - background: $Red-100; + &.high { + .actionable-message { + border-color: $Red-500; + background: $Red-100; - .actionable-message__message { - color: $Red-500; + .actionable-message__message { + color: $Red-500; + } + } + + button { + background: $Red-500; + color: #fff; + border-radius: 42px; + + /* Offsets the width of ActionableMessage icon */ + margin-right: -22px; } } @@ -118,11 +139,17 @@ &-contents { display: flex; + text-align: left; &-title { font-weight: bold; } + &-actions { + text-align: end; + padding-top: 10px; + } + i { margin-inline-start: 10px; } diff --git a/ui/app/pages/swaps/view-quote/tests/view-quote-price-difference.test.js b/ui/app/pages/swaps/view-quote/tests/view-quote-price-difference.test.js index bf37e0061..1fc66284b 100644 --- a/ui/app/pages/swaps/view-quote/tests/view-quote-price-difference.test.js +++ b/ui/app/pages/swaps/view-quote/tests/view-quote-price-difference.test.js @@ -140,7 +140,7 @@ describe('View Price Quote Difference', function () { }) it('displays a fiat error when calculationError is present', function () { - const props = { ...DEFAULT_PROPS } + const props = { ...DEFAULT_PROPS, priceSlippageUnknownFiatValue: true } props.usedQuote.priceSlippage.calculationError = 'Could not determine price.' diff --git a/ui/app/pages/swaps/view-quote/view-quote-price-difference.js b/ui/app/pages/swaps/view-quote/view-quote-price-difference.js index 5a3be3cac..bf229b8da 100644 --- a/ui/app/pages/swaps/view-quote/view-quote-price-difference.js +++ b/ui/app/pages/swaps/view-quote/view-quote-price-difference.js @@ -2,64 +2,37 @@ import React, { useContext } from 'react' import PropTypes from 'prop-types' import classnames from 'classnames' -import BigNumber from 'bignumber.js' -import { useEthFiatAmount } from '../../../hooks/useEthFiatAmount' import { I18nContext } from '../../../contexts/i18n' import ActionableMessage from '../actionable-message' import Tooltip from '../../../components/ui/tooltip' export default function ViewQuotePriceDifference(props) { - const { usedQuote, sourceTokenValue, destinationTokenValue } = props + const { + usedQuote, + sourceTokenValue, + destinationTokenValue, + onAcknowledgementClick, + acknowledged, + priceSlippageFromSource, + priceSlippageFromDestination, + priceDifferencePercentage, + priceSlippageUnknownFiatValue, + } = props const t = useContext(I18nContext) - const priceSlippageFromSource = useEthFiatAmount( - usedQuote?.priceSlippage?.sourceAmountInETH || 0, - ) - const priceSlippageFromDestination = useEthFiatAmount( - usedQuote?.priceSlippage?.destinationAmountInEth || 0, - ) - - if (!usedQuote || !usedQuote.priceSlippage) { - return null - } - - const { priceSlippage } = usedQuote - - // We cannot present fiat value if there is a calculation error or no slippage - // from source or destination - const priceSlippageUnknownFiatValue = - !priceSlippageFromSource || - !priceSlippageFromDestination || - priceSlippage.calculationError - - let priceDifferencePercentage = 0 - if (priceSlippage.ratio) { - priceDifferencePercentage = parseFloat( - new BigNumber(priceSlippage.ratio, 10) - .minus(1, 10) - .times(100, 10) - .toFixed(2), - 10, - ) - } - - const shouldShowPriceDifferenceWarning = - ['high', 'medium'].includes(priceSlippage.bucket) || - priceSlippageUnknownFiatValue - - if (!shouldShowPriceDifferenceWarning) { - return null - } - let priceDifferenceTitle = '' let priceDifferenceMessage = '' let priceDifferenceClass = '' + let priceDifferenceAcknowledgementText = '' if (priceSlippageUnknownFiatValue) { // A calculation error signals we cannot determine dollar value priceDifferenceMessage = t('swapPriceDifferenceUnavailable') priceDifferenceClass = 'fiat-error' + priceDifferenceAcknowledgementText = t( + 'swapPriceDifferenceAcknowledgementNoFiat', + ) } else { priceDifferenceTitle = t('swapPriceDifferenceTitle', [ priceDifferencePercentage, @@ -72,7 +45,8 @@ export default function ViewQuotePriceDifference(props) { usedQuote.destinationTokenInfo.symbol, // Destination token symbol, priceSlippageFromDestination, // Destination tokens total value ]) - priceDifferenceClass = priceSlippage.bucket + priceDifferenceClass = usedQuote.priceSlippage.bucket + priceDifferenceAcknowledgementText = t('swapPriceDifferenceAcknowledgement') } return ( @@ -92,6 +66,17 @@ export default function ViewQuotePriceDifference(props) {
)} {priceDifferenceMessage} + {!acknowledged && ( +
+ +
+ )}
{ @@ -474,20 +480,70 @@ export default function ViewQuote() { : 'ETH', ]) - const viewQuotePriceDifferenceComponent = ( - + // Price difference warning + let viewQuotePriceDifferenceComponent = null + const priceSlippageFromSource = useEthFiatAmount( + usedQuote?.priceSlippage?.sourceAmountInETH || 0, + ) + const priceSlippageFromDestination = useEthFiatAmount( + usedQuote?.priceSlippage?.destinationAmountInEth || 0, ) + // We cannot present fiat value if there is a calculation error or no slippage + // from source or destination + const priceSlippageUnknownFiatValue = + !priceSlippageFromSource || + !priceSlippageFromDestination || + usedQuote?.priceSlippage?.calculationError + + let priceDifferencePercentage = 0 + if (usedQuote?.priceSlippage?.ratio) { + priceDifferencePercentage = parseFloat( + new BigNumber(usedQuote.priceSlippage.ratio, 10) + .minus(1, 10) + .times(100, 10) + .toFixed(2), + 10, + ) + } + + const shouldShowPriceDifferenceWarning = + !showInsufficientWarning && + usedQuote && + (['high', 'medium'].includes(usedQuote.priceSlippage.bucket) || + priceSlippageUnknownFiatValue) + + if (shouldShowPriceDifferenceWarning) { + viewQuotePriceDifferenceComponent = ( + { + setAcknowledgedPriceDifference(true) + }} + acknowledged={acknowledgedPriceDifference} + /> + ) + } + + const disableSubmissionDueToPriceWarning = + shouldShowPriceDifferenceWarning && !acknowledgedPriceDifference + const isShowingWarning = - showInsufficientWarning || viewQuotePriceDifferenceComponent !== null + showInsufficientWarning || shouldShowPriceDifferenceWarning return (
-
+
{selectQuotePopoverShown && ( - {!showInsufficientWarning && viewQuotePriceDifferenceComponent} + {viewQuotePriceDifferenceComponent} {showInsufficientWarning && ( Date: Thu, 4 Feb 2021 14:42:43 -0330 Subject: [PATCH 34/48] Change copy of submit button on swaps screen (#10373) --- app/_locales/en/messages.json | 6 +++--- app/_locales/hi/messages.json | 3 --- app/_locales/id/messages.json | 3 --- app/_locales/ko/messages.json | 3 --- ui/app/pages/swaps/build-quote/build-quote.js | 2 +- 5 files changed, 4 insertions(+), 13 deletions(-) diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index 39e111cb7..b8f44b7bb 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -1672,9 +1672,6 @@ "swapFinalizing": { "message": "Finalizing..." }, - "swapGetQuotes": { - "message": "Get quotes" - }, "swapHighSlippageWarning": { "message": "Slippage amount is very high. Make sure you know what you are doing!" }, @@ -1798,6 +1795,9 @@ "swapRequestForQuotation": { "message": "Request for quotation" }, + "swapReviewSwap": { + "message": "Review Swap" + }, "swapSearchForAToken": { "message": "Search for a token" }, diff --git a/app/_locales/hi/messages.json b/app/_locales/hi/messages.json index e47d4ec18..6e8e48288 100644 --- a/app/_locales/hi/messages.json +++ b/app/_locales/hi/messages.json @@ -1657,9 +1657,6 @@ "swapFinalizing": { "message": "अंतिम रूप दिया जा रहा है..." }, - "swapGetQuotes": { - "message": "उद्धरण प्राप्त करें" - }, "swapHighSlippageWarning": { "message": "स्लिपेज राशि बहुत अधिक है। सुनिश्चित करें कि आप जानते हैं कि आप क्या कर रहे हैं!" }, diff --git a/app/_locales/id/messages.json b/app/_locales/id/messages.json index 9cfa08702..b8119c448 100644 --- a/app/_locales/id/messages.json +++ b/app/_locales/id/messages.json @@ -1657,9 +1657,6 @@ "swapFinalizing": { "message": "Menyelesaikan..." }, - "swapGetQuotes": { - "message": "Dapatkan kuota" - }, "swapHighSlippageWarning": { "message": "Jumlah slippage sangat tinggi. Pastikan Anda mengetahui yang Anda kerjakan!" }, diff --git a/app/_locales/ko/messages.json b/app/_locales/ko/messages.json index 08dc33108..5e0e307ac 100644 --- a/app/_locales/ko/messages.json +++ b/app/_locales/ko/messages.json @@ -1657,9 +1657,6 @@ "swapFinalizing": { "message": "마무리 중..." }, - "swapGetQuotes": { - "message": "견적 가져오기" - }, "swapHighSlippageWarning": { "message": "슬리패지 금액이 아주 큽니다. 현재 어떤 작업을 하고 있는지 확인하세요!" }, diff --git a/ui/app/pages/swaps/build-quote/build-quote.js b/ui/app/pages/swaps/build-quote/build-quote.js index 4714f79ad..c8ce65e88 100644 --- a/ui/app/pages/swaps/build-quote/build-quote.js +++ b/ui/app/pages/swaps/build-quote/build-quote.js @@ -410,7 +410,7 @@ export default function BuildQuote({ ), ) }} - submitText={t('swapGetQuotes')} + submitText={t('swapReviewSwap')} disabled={ !Number(inputValue) || !selectedToToken?.address || From 76a2a9bb8b6ea04025328d36404ac3b59121dfc8 Mon Sep 17 00:00:00 2001 From: Erik Marks <25517051+rekmarks@users.noreply.github.com> Date: Thu, 4 Feb 2021 10:15:23 -0800 Subject: [PATCH 35/48] @metamask/eslint config@5.0.0 (#10358) * @metamask/eslint-config@5.0.0 * Update eslintrc and prettierrc * yarn lint:fix --- .eslintrc.js | 14 +- .prettierrc.yml | 1 - .../account-import-strategies/index.js | 48 +- app/scripts/background.js | 280 +-- app/scripts/constants/contracts.js | 8 +- app/scripts/contentscript.js | 176 +- app/scripts/controllers/alert.js | 56 +- app/scripts/controllers/app-state.js | 68 +- app/scripts/controllers/cached-balances.js | 40 +- app/scripts/controllers/detect-tokens.js | 112 +- app/scripts/controllers/ens/ens.js | 12 +- app/scripts/controllers/ens/index.js | 68 +- .../controllers/incoming-transactions.js | 176 +- app/scripts/controllers/metametrics.js | 128 +- .../controllers/network/createInfuraClient.js | 36 +- .../network/createJsonRpcClient.js | 48 +- .../network/createMetamaskMiddleware.js | 10 +- app/scripts/controllers/network/index.js | 2 +- .../controllers/network/middleware/pending.js | 38 +- app/scripts/controllers/network/network.js | 198 +- app/scripts/controllers/network/util.js | 6 +- app/scripts/controllers/onboarding.js | 36 +- app/scripts/controllers/permissions/enums.js | 24 +- app/scripts/controllers/permissions/index.js | 294 +-- .../controllers/permissions/permissionsLog.js | 130 +- .../permissionsMethodMiddleware.js | 62 +- .../permissions/restrictedMethods.js | 26 +- app/scripts/controllers/preferences.js | 420 ++-- app/scripts/controllers/swaps.js | 475 ++-- app/scripts/controllers/threebox.js | 199 +- app/scripts/controllers/token-rates.js | 70 +- app/scripts/controllers/transactions/index.js | 550 ++--- .../lib/tx-state-history-helpers.js | 28 +- .../controllers/transactions/lib/util.js | 44 +- .../transactions/pending-tx-tracker.js | 132 +- .../controllers/transactions/tx-gas-utils.js | 56 +- .../transactions/tx-state-manager.js | 254 +- app/scripts/disable-console.js | 6 +- app/scripts/first-time-state.js | 4 +- app/scripts/initSentry.js | 4 +- app/scripts/inpage.js | 32 +- app/scripts/lib/ComposableObservableStore.js | 24 +- app/scripts/lib/account-tracker.js | 164 +- app/scripts/lib/buy-eth-url.js | 28 +- app/scripts/lib/cleanErrorStack.js | 16 +- app/scripts/lib/createLoggerMiddleware.js | 14 +- app/scripts/lib/createOnboardingMiddleware.js | 20 +- app/scripts/lib/createOriginMiddleware.js | 6 +- app/scripts/lib/createStreamSink.js | 14 +- app/scripts/lib/createTabIdMiddleware.js | 6 +- app/scripts/lib/decrypt-message-manager.js | 142 +- .../lib/encryption-public-key-manager.js | 122 +- .../lib/ens-ipfs/contracts/registry.js | 4 +- .../lib/ens-ipfs/contracts/resolver.js | 4 +- app/scripts/lib/ens-ipfs/resolver.js | 66 +- app/scripts/lib/ens-ipfs/setup.js | 61 +- app/scripts/lib/extractEthjsErrorMessage.js | 14 +- .../lib/get-first-preferred-lang-code.js | 26 +- app/scripts/lib/getObjStructure.js | 16 +- app/scripts/lib/local-store.js | 46 +- app/scripts/lib/message-manager.js | 110 +- app/scripts/lib/migrator/index.js | 36 +- app/scripts/lib/network-store.js | 36 +- app/scripts/lib/nodeify.js | 28 +- app/scripts/lib/notification-manager.js | 42 +- app/scripts/lib/personal-message-manager.js | 132 +- app/scripts/lib/random-id.js | 8 +- .../createMethodMiddleware.js | 14 +- .../handlers/get-provider-state.js | 10 +- .../rpc-method-middleware/handlers/index.js | 10 +- .../handlers/log-web3-shim-usage.js | 16 +- .../handlers/watch-asset.js | 12 +- .../lib/rpc-method-middleware/index.js | 2 +- app/scripts/lib/seed-phrase-verifier.js | 28 +- app/scripts/lib/segment.js | 36 +- app/scripts/lib/setupFetchDebugging.js | 22 +- app/scripts/lib/setupSentry.js | 76 +- app/scripts/lib/stream-utils.js | 12 +- app/scripts/lib/typed-message-manager.js | 180 +- app/scripts/lib/util.js | 86 +- app/scripts/metamask-controller.js | 1196 ++++----- app/scripts/migrations/002.js | 16 +- app/scripts/migrations/003.js | 18 +- app/scripts/migrations/004.js | 22 +- app/scripts/migrations/005.js | 32 +- app/scripts/migrations/006.js | 28 +- app/scripts/migrations/007.js | 28 +- app/scripts/migrations/008.js | 26 +- app/scripts/migrations/009.js | 32 +- app/scripts/migrations/010.js | 26 +- app/scripts/migrations/011.js | 28 +- app/scripts/migrations/012.js | 28 +- app/scripts/migrations/013.js | 28 +- app/scripts/migrations/014.js | 30 +- app/scripts/migrations/015.js | 38 +- app/scripts/migrations/016.js | 40 +- app/scripts/migrations/017.js | 40 +- app/scripts/migrations/018.js | 46 +- app/scripts/migrations/019.js | 75 +- app/scripts/migrations/020.js | 26 +- app/scripts/migrations/021.js | 28 +- app/scripts/migrations/022.js | 38 +- app/scripts/migrations/023.js | 46 +- app/scripts/migrations/024.js | 34 +- app/scripts/migrations/025.js | 46 +- app/scripts/migrations/026.js | 34 +- app/scripts/migrations/027.js | 28 +- app/scripts/migrations/028.js | 32 +- app/scripts/migrations/029.js | 24 +- app/scripts/migrations/030.js | 34 +- app/scripts/migrations/031.js | 26 +- app/scripts/migrations/032.js | 24 +- app/scripts/migrations/033.js | 24 +- app/scripts/migrations/034.js | 26 +- app/scripts/migrations/035.js | 18 +- app/scripts/migrations/036.js | 24 +- app/scripts/migrations/037.js | 40 +- app/scripts/migrations/038.js | 24 +- app/scripts/migrations/039.js | 42 +- app/scripts/migrations/040.js | 20 +- app/scripts/migrations/041.js | 22 +- app/scripts/migrations/042.js | 22 +- app/scripts/migrations/043.js | 20 +- app/scripts/migrations/044.js | 20 +- app/scripts/migrations/045.js | 22 +- app/scripts/migrations/046.js | 20 +- app/scripts/migrations/047.js | 24 +- app/scripts/migrations/048.js | 122 +- app/scripts/migrations/049.js | 34 +- app/scripts/migrations/050.js | 16 +- app/scripts/migrations/051.js | 26 +- app/scripts/migrations/fail-tx.js | 38 +- app/scripts/migrations/index.js | 4 +- app/scripts/migrations/template.js | 22 +- app/scripts/phishing-detect.js | 54 +- app/scripts/platforms/extension.js | 168 +- app/scripts/runLockdown.js | 6 +- app/scripts/ui.js | 128 +- babel.config.js | 6 +- development/announcer.js | 14 +- development/build/display.js | 138 +- development/build/etc.js | 38 +- development/build/index.js | 40 +- development/build/manifest.js | 83 +- development/build/scripts.js | 166 +- development/build/static.js | 66 +- development/build/styles.js | 50 +- development/build/task.js | 94 +- development/create-static-server.js | 18 +- development/lib/create-segment-server.js | 64 +- development/lib/locales.js | 30 +- development/lib/parse-port.js | 10 +- development/metamaskbot-build-announce.js | 176 +- development/missing-locale-strings.js | 50 +- development/mock-3box.js | 46 +- development/mock-segment.js | 48 +- development/require-react-devtools.js | 2 +- development/sentry-publish.js | 62 +- development/show-deps-install-scripts.js | 36 +- development/sourcemap-validator.js | 138 +- development/static-server.js | 76 +- development/verify-locale-strings.js | 175 +- nyc.config.js | 2 +- package.json | 2 +- shared/constants/alerts.js | 6 +- shared/constants/app.js | 20 +- shared/constants/metametrics.js | 4 +- shared/constants/network.js | 62 +- shared/constants/permissions.js | 2 +- shared/constants/tokens.js | 4 +- shared/constants/transaction.js | 10 +- shared/modules/fetch-with-timeout.js | 28 +- shared/modules/utils.js | 8 +- stylelint.config.js | 2 +- test/e2e/address-book.spec.js | 302 +-- test/e2e/benchmark.js | 160 +- test/e2e/ethereum-on.spec.js | 204 +- test/e2e/fixture-server.js | 64 +- test/e2e/from-import-ui.spec.js | 418 ++-- test/e2e/ganache.js | 26 +- test/e2e/helpers.js | 104 +- test/e2e/incremental-security.spec.js | 228 +- test/e2e/metamask-responsive-ui.spec.js | 276 +-- test/e2e/metamask-ui.spec.js | 1782 +++++++------- test/e2e/metrics.spec.js | 50 +- test/e2e/mock-3box/server.js | 40 +- test/e2e/permissions.spec.js | 180 +- test/e2e/send-edit.spec.js | 262 +- test/e2e/signature-request.spec.js | 184 +- test/e2e/tests/localization.spec.js | 34 +- test/e2e/tests/personal-sign.spec.js | 42 +- test/e2e/tests/simple-send.spec.js | 38 +- test/e2e/threebox.spec.js | 278 +-- test/e2e/webdriver/chrome.js | 34 +- test/e2e/webdriver/driver.js | 158 +- test/e2e/webdriver/firefox.js | 46 +- test/e2e/webdriver/index.js | 54 +- test/env.js | 2 +- test/helper.js | 90 +- test/lib/createTxMeta.js | 14 +- test/lib/mock-encryptor.js | 26 +- test/lib/render-helpers.js | 26 +- test/lib/wait-until-called.js | 32 +- test/setup.js | 8 +- test/stub/provider.js | 28 +- test/unit-global/frozenPromise.js | 50 +- test/unit-global/globalPatch.js | 2 +- test/unit/actions/config_test.js | 28 +- test/unit/actions/set_account_label_test.js | 24 +- .../unit/actions/set_selected_account_test.js | 24 +- test/unit/actions/tx_test.js | 44 +- test/unit/actions/warning_test.js | 24 +- test/unit/app/ComposableObservableStore.js | 46 +- .../app/account-import-strategies.spec.js | 60 +- test/unit/app/buy-eth-url.spec.js | 38 +- test/unit/app/cleanErrorStack.spec.js | 38 +- .../app/controllers/cached-balances-test.js | 64 +- .../app/controllers/detect-tokens-test.js | 286 +-- .../app/controllers/ens-controller-test.js | 108 +- .../controllers/incoming-transactions-test.js | 510 ++-- .../controllers/metamask-controller-test.js | 1065 ++++---- test/unit/app/controllers/metametrics-test.js | 335 +-- .../network/network-controller-test.js | 88 +- .../network/pending-middleware-test.js | 90 +- test/unit/app/controllers/network/stubs.js | 4 +- .../app/controllers/permissions/helpers.js | 56 +- .../unit/app/controllers/permissions/mocks.js | 156 +- .../permissions-controller-test.js | 908 +++---- .../permissions-log-controller-test.js | 456 ++-- .../permissions-middleware-test.js | 564 ++--- .../permissions/restricted-methods-test.js | 138 +- .../preferences-controller-test.js | 651 ++--- test/unit/app/controllers/swaps-test.js | 781 +++--- .../app/controllers/token-rates-controller.js | 38 +- .../transactions/pending-tx-tracker-test.js | 389 +-- .../transactions/tx-controller-test.js | 578 ++--- .../transactions/tx-gas-util-test.js | 76 +- .../transactions/tx-helper-test.js | 18 +- .../tx-state-history-helpers-test.js | 120 +- .../transactions/tx-state-manager-test.js | 488 ++-- .../controllers/transactions/tx-utils-test.js | 113 +- test/unit/app/fetch-with-timeout.test.js | 56 +- test/unit/app/message-manager-test.js | 118 +- test/unit/app/nodeify-test.js | 72 +- .../unit/app/personal-message-manager-test.js | 144 +- test/unit/app/seed-phrase-verifier-test.js | 146 +- test/unit/app/typed-message-manager.spec.js | 85 +- test/unit/app/util-test.js | 128 +- test/unit/balance-formatter-test.js | 30 +- test/unit/lib/account-link.test.js | 16 +- test/unit/localhostState.js | 6 +- test/unit/migrations/021-test.js | 20 +- test/unit/migrations/022-test.js | 28 +- test/unit/migrations/023-test.js | 89 +- test/unit/migrations/024-test.js | 44 +- test/unit/migrations/025-test.js | 44 +- test/unit/migrations/026-test.js | 30 +- test/unit/migrations/027-test.js | 44 +- test/unit/migrations/028-test.js | 42 +- test/unit/migrations/029-test.js | 34 +- test/unit/migrations/030-test.js | 24 +- test/unit/migrations/031-test.js | 26 +- test/unit/migrations/033-test.js | 14 +- test/unit/migrations/034-test.js | 66 +- test/unit/migrations/035-test.js | 46 +- test/unit/migrations/036-test.js | 66 +- test/unit/migrations/037-test.js | 36 +- test/unit/migrations/038-test.js | 36 +- test/unit/migrations/039-test.js | 146 +- test/unit/migrations/040-test.js | 36 +- test/unit/migrations/041-test.js | 46 +- test/unit/migrations/042-test.js | 36 +- test/unit/migrations/043-test.js | 30 +- test/unit/migrations/044-test.js | 38 +- test/unit/migrations/045-test.js | 46 +- test/unit/migrations/046-test.js | 30 +- test/unit/migrations/047-test.js | 54 +- test/unit/migrations/048-test.js | 148 +- test/unit/migrations/049-test.js | 54 +- test/unit/migrations/050-test.js | 54 +- test/unit/migrations/051-test.js | 52 +- test/unit/migrations/migrations-test.js | 152 +- test/unit/migrations/migrator-test.js | 106 +- test/unit/migrations/template-test.js | 16 +- .../responsive/components/dropdown-test.js | 34 +- test/unit/ui/app/actions.spec.js | 1362 +++++------ test/unit/ui/app/reducers/app.spec.js | 288 +-- test/unit/ui/app/reducers/metamask.spec.js | 210 +- .../ui/etherscan-prefix-for-network.spec.js | 30 +- .../account-list-item/account-list-item.js | 16 +- .../components/app/account-list-item/index.js | 2 +- .../tests/account-list-item-component.test.js | 128 +- .../account-menu/account-menu.component.js | 194 +- .../account-menu/account-menu.container.js | 42 +- ui/app/components/app/account-menu/index.js | 2 +- .../account-menu/tests/account-menu.test.js | 172 +- .../add-token-button.component.js | 24 +- .../components/app/add-token-button/index.js | 2 +- ui/app/components/app/alerts/alerts.js | 30 +- ui/app/components/app/alerts/index.js | 2 +- .../invalid-custom-network-alert/index.js | 2 +- .../invalid-custom-network-alert.js | 44 +- .../alerts/unconnected-account-alert/index.js | 2 +- .../tests/unconnected-account-alert.test.js | 92 +- .../unconnected-account-alert.js | 56 +- .../app/app-header/app-header.component.js | 48 +- .../app/app-header/app-header.container.js | 26 +- ui/app/components/app/app-header/index.js | 2 +- .../app/app-header/tests/app-header.test.js | 88 +- .../app/asset-list-item/asset-list-item.js | 66 +- .../components/app/asset-list-item/index.js | 2 +- .../components/app/asset-list/asset-list.js | 62 +- ui/app/components/app/asset-list/index.js | 2 +- .../confirm-detail-row.component.js | 20 +- .../confirm-detail-row/index.js | 2 +- .../confirm-detail-row.component.test.js | 56 +- ...onfirm-page-container-content.component.js | 30 +- ...onfirm-page-container-summary.component.js | 18 +- .../confirm-page-container-summary/index.js | 2 +- ...onfirm-page-container-warning.component.js | 12 +- .../confirm-page-container-warning/index.js | 2 +- .../confirm-page-container-content/index.js | 6 +- ...confirm-page-container-header.component.js | 30 +- .../confirm-page-container-header/index.js | 2 +- ...irm-page-container-navigation.component.js | 14 +- .../index.js | 2 +- .../confirm-page-container.component.js | 20 +- .../app/confirm-page-container/index.js | 10 +- .../connected-accounts-list-item.component.js | 18 +- .../connected-accounts-list-item/index.js | 2 +- ...nnected-accounts-list-options.component.js | 16 +- .../connected-accounts-list-options/index.js | 2 +- .../connected-accounts-list.component.js | 72 +- .../app/connected-accounts-list/index.js | 2 +- ...onnected-accounts-permissions.component.js | 30 +- .../connected-accounts-permissions/index.js | 2 +- .../connected-sites-list.component.js | 22 +- .../app/connected-sites-list/index.js | 2 +- .../connected-status-indicator.js | 58 +- .../app/connected-status-indicator/index.js | 2 +- .../contact-list/contact-list.component.js | 54 +- ui/app/components/app/contact-list/index.js | 2 +- .../app/contact-list/recipient-group/index.js | 2 +- .../recipient-group.component.js | 18 +- .../app/dropdowns/components/dropdown.js | 30 +- .../app/dropdowns/network-dropdown.js | 130 +- .../app/dropdowns/simple-dropdown.js | 44 +- .../app/dropdowns/tests/dropdown.test.js | 38 +- .../dropdowns/tests/network-dropdown.test.js | 108 +- .../advanced-gas-inputs.component.js | 92 +- .../advanced-gas-inputs.container.js | 18 +- .../advanced-gas-inputs/index.js | 2 +- .../advanced-gas-input-component.test.js | 107 +- .../advanced-tab-content.component.js | 16 +- .../advanced-tab-content/index.js | 2 +- .../advanced-tab-content-component.test.js | 74 +- .../basic-tab-content.component.js | 18 +- .../basic-tab-content/index.js | 2 +- .../tests/basic-tab-content-component.test.js | 60 +- .../gas-modal-page-container.component.js | 42 +- .../gas-modal-page-container.container.js | 164 +- .../gas-modal-page-container/index.js | 2 +- ...gas-modal-page-container-component.test.js | 192 +- ...gas-modal-page-container-container.test.js | 304 +-- .../gas-price-button-group.component.js | 34 +- .../gas-price-button-group/index.js | 2 +- .../gas-price-button-group-component.test.js | 180 +- .../gas-slider/gas-slider.component.js | 10 +- .../app/gas-customization/gas-slider/index.js | 2 +- .../home-notification.component.js | 24 +- .../components/app/home-notification/index.js | 2 +- ui/app/components/app/info-box/index.js | 4 +- .../app/info-box/info-box.component.js | 20 +- .../app/info-box/tests/info-box.test.js | 40 +- .../app/loading-network-screen/index.js | 2 +- .../loading-network-screen.component.js | 90 +- .../loading-network-screen.container.js | 30 +- .../app/menu-bar/account-options-menu.js | 86 +- ui/app/components/app/menu-bar/index.js | 2 +- ui/app/components/app/menu-bar/menu-bar.js | 46 +- .../app/menu-bar/tests/menu-bar.test.js | 56 +- ui/app/components/app/menu-droppo.js | 54 +- .../app/metamask-template-renderer/index.js | 2 +- .../metamask-template-renderer.js | 52 +- .../metamask-template-renderer.stories.js | 16 +- .../safe-component-list.js | 16 +- ui/app/components/app/modal/index.js | 4 +- .../app/modal/modal-content/index.js | 2 +- .../modal-content/modal-content.component.js | 10 +- .../tests/modal-content.component.test.js | 42 +- .../components/app/modal/modal.component.js | 16 +- .../app/modal/tests/modal.component.test.js | 132 +- .../account-details-modal.component.js | 34 +- .../account-details-modal.container.js | 21 +- .../app/modals/account-details-modal/index.js | 2 +- .../account-modal-container.component.js | 18 +- .../account-modal-container.container.js | 16 +- .../modals/account-modal-container/index.js | 2 +- .../add-to-addressbook-modal.component.js | 32 +- .../add-to-addressbook-modal.container.js | 12 +- .../modals/add-to-addressbook-modal/index.js | 2 +- .../cancel-transaction-gas-fee.component.js | 14 +- .../cancel-transaction-gas-fee/index.js | 2 +- ...ncel-transaction-gas-fee.component.test.js | 32 +- .../cancel-transaction.component.js | 42 +- .../cancel-transaction.container.js | 50 +- .../app/modals/cancel-transaction/index.js | 2 +- .../cancel-transaction.component.test.js | 66 +- .../confirm-delete-network.component.js | 22 +- .../confirm-delete-network.container.js | 16 +- .../modals/confirm-delete-network/index.js | 2 +- .../tests/confirm-delete-network.test.js | 56 +- .../confirm-remove-account.component.js | 32 +- .../confirm-remove-account.container.js | 20 +- .../modals/confirm-remove-account/index.js | 2 +- .../tests/confirm-remove-account.test.js | 68 +- .../confirm-reset-account.component.js | 18 +- .../confirm-reset-account.container.js | 16 +- .../app/modals/confirm-reset-account/index.js | 2 +- .../tests/confirm-reset-account.test.js | 46 +- .../deposit-ether-modal.component.js | 44 +- .../deposit-ether-modal.container.js | 20 +- .../app/modals/deposit-ether-modal/index.js | 2 +- .../edit-approval-permission.component.js | 82 +- .../edit-approval-permission.container.js | 18 +- .../modals/edit-approval-permission/index.js | 2 +- .../export-private-key-modal.component.js | 54 +- .../export-private-key-modal.container.js | 26 +- .../modals/export-private-key-modal/index.js | 2 +- ui/app/components/app/modals/fade-modal.js | 160 +- .../hide-token-confirmation-modal.js | 36 +- .../hide-token-confirmation-modal/index.js | 2 +- ui/app/components/app/modals/index.js | 4 +- .../app/modals/loading-network-error/index.js | 2 +- .../loading-network-error.component.js | 20 +- .../loading-network-error.container.js | 6 +- .../modals/metametrics-opt-in-modal/index.js | 2 +- .../metametrics-opt-in-modal.component.js | 30 +- .../metametrics-opt-in-modal.container.js | 22 +- .../tests/metametrics-opt-in-modal.test.js | 60 +- ui/app/components/app/modals/modal.js | 102 +- .../app/modals/new-account-modal/index.js | 2 +- .../new-account-modal.component.js | 28 +- .../new-account-modal.container.js | 26 +- .../components/app/modals/qr-scanner/index.js | 4 +- .../modals/qr-scanner/qr-scanner.component.js | 184 +- .../modals/qr-scanner/qr-scanner.container.js | 12 +- .../app/modals/reject-transactions/index.js | 2 +- .../reject-transactions.component.js | 24 +- .../reject-transactions.container.js | 16 +- .../tests/reject-transactions.test.js | 46 +- .../tests/account-details-modal.test.js | 64 +- .../app/modals/transaction-confirmed/index.js | 2 +- .../tests/transaction-confirmed.test.js | 28 +- .../transaction-confirmed.component.js | 22 +- .../transaction-confirmed.container.js | 6 +- .../app/multiple-notifications/index.js | 2 +- .../multiple-notifications.component.js | 22 +- .../components/app/network-display/index.js | 2 +- .../app/network-display/network-display.js | 30 +- .../app/permission-page-container/index.js | 4 +- .../index.js | 2 +- ...ission-page-container-content.component.js | 66 +- .../permission-page-container.component.js | 62 +- .../permission-page-container.container.js | 18 +- .../app/permissions-connect-footer/index.js | 2 +- .../permissions-connect-footer.component.js | 12 +- .../app/permissions-connect-header/index.js | 2 +- .../permissions-connect-header.component.js | 18 +- .../components/app/selected-account/index.js | 4 +- .../selected-account.component.js | 38 +- .../selected-account.container.js | 12 +- .../tests/selected-account-component.test.js | 18 +- ui/app/components/app/sidebars/index.js | 2 +- .../app/sidebars/sidebar.component.js | 32 +- .../sidebars/tests/sidebars-component.test.js | 104 +- .../app/signature-request-original/index.js | 2 +- .../signature-request-original.component.js | 166 +- .../signature-request-original.container.js | 52 +- .../components/app/signature-request/index.js | 2 +- .../signature-request-footer/index.js | 2 +- .../signature-request-footer.component.js | 14 +- .../signature-request-header/index.js | 2 +- .../signature-request-header.component.js | 14 +- .../signature-request-message/index.js | 2 +- .../signature-request-message.component.js | 16 +- .../signature-request.component.js | 42 +- .../signature-request.constants.js | 4 +- .../signature-request.container.js | 44 +- .../tests/signature-request.test.js | 24 +- ui/app/components/app/tab-bar/index.js | 2 +- ui/app/components/app/tab-bar/tab-bar.js | 16 +- .../app/tests/signature-request.test.js | 48 +- ui/app/components/app/token-cell/index.js | 2 +- .../components/app/token-cell/token-cell.js | 30 +- .../app/token-cell/token-cell.test.js | 70 +- ui/app/components/app/token-list/index.js | 2 +- .../components/app/token-list/token-list.js | 36 +- .../app/transaction-activity-log/index.js | 2 +- ...transaction-activity-log.component.test.js | 44 +- ...transaction-activity-log.container.test.js | 22 +- .../transaction-activity-log.util.test.js | 38 +- .../transaction-activity-log-icon/index.js | 2 +- ...transaction-activity-log-icon.component.js | 20 +- .../transaction-activity-log.component.js | 68 +- .../transaction-activity-log.constants.js | 24 +- .../transaction-activity-log.container.js | 32 +- .../transaction-activity-log.util.js | 106 +- .../app/transaction-breakdown/index.js | 2 +- .../transaction-breakdown.component.test.js | 22 +- .../transaction-breakdown-row/index.js | 2 +- ...ransaction-breakdown-row.component.test.js | 32 +- .../transaction-breakdown-row.component.js | 12 +- .../transaction-breakdown.component.js | 28 +- .../transaction-breakdown.container.js | 34 +- .../components/app/transaction-icon/index.js | 2 +- .../app/transaction-icon/transaction-icon.js | 36 +- .../transaction-list-item-details/index.js | 2 +- ...action-list-item-details.component.test.js | 90 +- ...transaction-list-item-details.component.js | 102 +- ...transaction-list-item-details.container.js | 46 +- .../app/transaction-list-item/index.js | 2 +- .../transaction-list-item.component.js | 88 +- .../components/app/transaction-list/index.js | 2 +- .../transaction-list.component.js | 66 +- .../app/transaction-status/index.js | 2 +- .../transaction-status.component.test.js | 70 +- .../transaction-status.component.js | 32 +- .../index.js | 2 +- ...erenced-currency-display.component.test.js | 52 +- ...-preferenced-currency-display.component.js | 20 +- .../user-preferenced-currency-input/index.js | 2 +- ...eferenced-currency-input.component.test.js | 36 +- ...eferenced-currency-input.container.test.js | 22 +- ...er-preferenced-currency-input.component.js | 12 +- ...er-preferenced-currency-input.container.js | 14 +- .../app/user-preferenced-token-input/index.js | 2 +- ...-preferenced-token-input.component.test.js | 36 +- ...-preferenced-token-input.container.test.js | 22 +- .../user-preferenced-token-input.component.js | 12 +- .../user-preferenced-token-input.container.js | 20 +- .../app/wallet-overview/eth-overview.js | 100 +- .../components/app/wallet-overview/index.js | 4 +- .../app/wallet-overview/token-overview.js | 92 +- .../app/wallet-overview/wallet-overview.js | 16 +- .../account-mismatch-warning.component.js | 26 +- ...cccount-mismatch-warning.component.test.js | 44 +- .../alert-circle-icon.component.js | 12 +- .../alert-circle-icon.stories.js | 10 +- .../components/ui/alert-circle-icon/index.js | 2 +- ui/app/components/ui/alert/index.js | 28 +- .../components/ui/alert/tests/alert.test.js | 52 +- ui/app/components/ui/box/box.js | 40 +- ui/app/components/ui/box/box.stories.js | 22 +- ui/app/components/ui/box/index.js | 2 +- .../ui/breadcrumbs/breadcrumbs.component.js | 12 +- ui/app/components/ui/breadcrumbs/index.js | 2 +- .../tests/breadcrumbs.component.test.js | 26 +- .../ui/button-group/button-group.component.js | 30 +- .../ui/button-group/button-group.stories.js | 20 +- ui/app/components/ui/button-group/index.js | 2 +- .../tests/button-group-component.test.js | 138 +- .../components/ui/button/button.component.js | 40 +- ui/app/components/ui/button/button.stories.js | 22 +- ui/app/components/ui/button/index.js | 4 +- ui/app/components/ui/callout/callout.js | 28 +- .../components/ui/callout/callout.stories.js | 34 +- ui/app/components/ui/callout/index.js | 2 +- ui/app/components/ui/card/card.component.js | 12 +- ui/app/components/ui/card/index.js | 2 +- .../ui/card/tests/card.component.test.js | 28 +- .../ui/check-box/check-box.component.js | 32 +- .../ui/check-box/check-box.stories.js | 14 +- ui/app/components/ui/check-box/index.js | 2 +- ui/app/components/ui/chip/chip.js | 20 +- ui/app/components/ui/chip/chip.stories.js | 22 +- ui/app/components/ui/chip/index.js | 2 +- .../ui/circle-icon/circle-icon.component.js | 12 +- .../ui/circle-icon/circle-icon.stories.js | 8 +- ui/app/components/ui/circle-icon/index.js | 2 +- .../ui/color-indicator/color-indicator.js | 16 +- .../color-indicator.stories.js | 14 +- ui/app/components/ui/color-indicator/index.js | 2 +- .../currency-display.component.js | 16 +- .../components/ui/currency-display/index.js | 2 +- .../tests/currency-display.component.test.js | 40 +- .../currency-input.component.js | 92 +- .../currency-input.container.js | 26 +- ui/app/components/ui/currency-input/index.js | 2 +- .../tests/currency-input.component.test.js | 304 +-- .../tests/currency-input.container.test.js | 36 +- .../ui/definition-list/definition-list.js | 18 +- .../definition-list.stories.js | 22 +- ui/app/components/ui/definition-list/index.js | 2 +- ui/app/components/ui/dialog/index.js | 12 +- ui/app/components/ui/dropdown/dropdown.js | 26 +- .../ui/dropdown/dropdown.stories.js | 30 +- ui/app/components/ui/dropdown/index.js | 2 +- .../ui/editable-label/editable-label.js | 32 +- ui/app/components/ui/editable-label/index.js | 2 +- .../error-message/error-message.component.js | 18 +- ui/app/components/ui/error-message/index.js | 2 +- .../tests/error-message.component.test.js | 36 +- .../export-text-container.component.js | 24 +- .../ui/export-text-container/index.js | 4 +- .../hex-to-decimal.component.js | 14 +- ui/app/components/ui/hex-to-decimal/index.js | 2 +- .../tests/hex-to-decimal.component.test.js | 26 +- .../components/ui/icon-border/icon-border.js | 10 +- ui/app/components/ui/icon-border/index.js | 2 +- .../components/ui/icon-button/icon-button.js | 14 +- ui/app/components/ui/icon-button/index.js | 2 +- .../icon-with-fallback.component.js | 18 +- .../components/ui/icon-with-fallback/index.js | 2 +- .../ui/icon-with-label/icon-with-label.js | 10 +- ui/app/components/ui/icon-with-label/index.js | 2 +- .../ui/icon/approve-icon.component.js | 12 +- .../components/ui/icon/copy-icon.component.js | 12 +- ui/app/components/ui/icon/icon.stories.js | 42 +- .../ui/icon/info-icon-inverted.component.js | 14 +- .../components/ui/icon/info-icon.component.js | 14 +- .../ui/icon/interaction-icon.component.js | 12 +- .../ui/icon/overview-buy-icon.component.js | 8 +- .../ui/icon/overview-send-icon.component.js | 8 +- .../components/ui/icon/paper-airplane-icon.js | 10 +- ui/app/components/ui/icon/preloader/index.js | 4 +- .../preloader/preloader-icon.component.js | 14 +- .../ui/icon/receive-icon.component.js | 12 +- .../components/ui/icon/send-icon.component.js | 12 +- .../components/ui/icon/sign-icon.component.js | 8 +- .../ui/icon/sun-check-icon.component.js | 12 +- .../ui/icon/swap-icon-for-list.component.js | 12 +- .../components/ui/icon/swap-icon.component.js | 8 +- .../blockieIdenticon.component.js | 28 +- .../ui/identicon/blockieIdenticon/index.js | 2 +- .../ui/identicon/identicon.component.js | 44 +- .../ui/identicon/identicon.container.js | 12 +- .../ui/identicon/identicon.stories.js | 20 +- ui/app/components/ui/identicon/index.js | 2 +- .../tests/identicon.component.test.js | 45 +- ui/app/components/ui/info-tooltip/index.js | 2 +- .../ui/info-tooltip/info-tooltip.js | 14 +- .../ui/info-tooltip/info-tooltip.stories.js | 16 +- ui/app/components/ui/jazzicon/index.js | 2 +- .../ui/jazzicon/jazzicon.component.js | 40 +- ui/app/components/ui/list-item/index.js | 2 +- .../ui/list-item/list-item.component.js | 12 +- .../ui/list-item/list-item.stories.js | 38 +- .../ui/list-item/tests/list-item.test.js | 84 +- .../components/ui/loading-indicator/index.js | 2 +- .../ui/loading-indicator/loading-indicator.js | 8 +- ui/app/components/ui/loading-screen/index.js | 4 +- .../loading-screen.component.js | 20 +- ui/app/components/ui/lock-icon/index.js | 2 +- .../ui/lock-icon/lock-icon.component.js | 4 +- ui/app/components/ui/mascot/index.js | 2 +- .../components/ui/mascot/mascot.component.js | 80 +- ui/app/components/ui/mascot/mascot.stories.js | 50 +- ui/app/components/ui/menu/index.js | 4 +- ui/app/components/ui/menu/menu-item.js | 14 +- ui/app/components/ui/menu/menu.js | 26 +- ui/app/components/ui/menu/menu.stories.js | 18 +- ui/app/components/ui/metafox-logo/index.js | 2 +- .../ui/metafox-logo/metafox-logo.component.js | 16 +- .../tests/metafox-logo.component.test.js | 26 +- ui/app/components/ui/page-container/index.js | 8 +- .../page-container-content.component.js | 8 +- .../page-container-footer/index.js | 2 +- .../page-container-footer.component.js | 16 +- .../page-container-footer.component.test.js | 74 +- .../page-container-header/index.js | 2 +- .../page-container-header.component.js | 22 +- .../page-container-header.component.test.js | 95 +- .../page-container.component.js | 46 +- ui/app/components/ui/popover/index.js | 4 +- .../ui/popover/popover.component.js | 36 +- .../components/ui/popover/popover.stories.js | 16 +- ui/app/components/ui/pulse-loader/index.js | 2 +- .../ui/pulse-loader/pulse-loader.js | 4 +- .../ui/pulse-loader/pulse-loader.stories.js | 8 +- ui/app/components/ui/qr-code/index.js | 2 +- ui/app/components/ui/qr-code/qr-code.js | 36 +- ui/app/components/ui/readonly-input/index.js | 2 +- .../ui/readonly-input/readonly-input.js | 14 +- ui/app/components/ui/search-icon/index.js | 2 +- .../ui/search-icon/search-icon.component.js | 4 +- .../ui/sender-to-recipient/index.js | 2 +- .../sender-to-recipient.component.js | 76 +- .../sender-to-recipient.constants.js | 6 +- ui/app/components/ui/site-icon/index.js | 2 +- ui/app/components/ui/site-icon/site-icon.js | 16 +- ui/app/components/ui/snackbar/index.js | 2 +- .../ui/snackbar/snackbar.component.js | 14 +- ui/app/components/ui/spinner/index.js | 4 +- .../ui/spinner/spinner.component.js | 12 +- ui/app/components/ui/tabs/index.js | 6 +- ui/app/components/ui/tabs/tab/index.js | 4 +- .../components/ui/tabs/tab/tab.component.js | 22 +- ui/app/components/ui/tabs/tabs.component.js | 42 +- ui/app/components/ui/tabs/tabs.stories.js | 24 +- ui/app/components/ui/text-field/index.js | 4 +- .../ui/text-field/text-field.component.js | 32 +- .../ui/text-field/text-field.stories.js | 20 +- ui/app/components/ui/toggle-button/index.js | 4 +- .../toggle-button/toggle-button.component.js | 26 +- ui/app/components/ui/token-balance/index.js | 2 +- .../ui/token-balance/token-balance.js | 18 +- .../ui/token-currency-display/index.js | 2 +- .../token-currency-display.component.js | 14 +- ui/app/components/ui/token-input/index.js | 2 +- .../tests/token-input.component.test.js | 248 +- .../ui/token-input/token-input.component.js | 88 +- .../ui/token-input/token-input.container.js | 24 +- ui/app/components/ui/tooltip/index.js | 2 +- ui/app/components/ui/tooltip/tooltip.js | 16 +- .../ui/truncated-definition-list/index.js | 2 +- .../truncated-definition-list.js | 26 +- .../truncated-definition-list.stories.js | 18 +- ui/app/components/ui/typography/index.js | 2 +- ui/app/components/ui/typography/typography.js | 24 +- .../ui/typography/typography.stories.js | 14 +- ui/app/components/ui/unit-input/index.js | 2 +- .../tests/unit-input.component.test.js | 130 +- .../ui/unit-input/unit-input.component.js | 60 +- ui/app/components/ui/url-icon/index.js | 2 +- ui/app/components/ui/url-icon/url-icon.js | 12 +- ui/app/contexts/i18n.js | 46 +- ui/app/contexts/metametrics.js | 76 +- ui/app/contexts/metametrics.new.js | 80 +- ui/app/ducks/alerts/enums.js | 2 +- ui/app/ducks/alerts/index.js | 6 +- ui/app/ducks/alerts/invalid-custom-network.js | 34 +- ui/app/ducks/alerts/unconnected-account.js | 110 +- ui/app/ducks/app/app.js | 96 +- .../confirm-transaction.duck.js | 204 +- .../confirm-transaction.duck.test.js | 295 +-- ui/app/ducks/gas/gas-duck.test.js | 191 +- ui/app/ducks/gas/gas.duck.js | 117 +- ui/app/ducks/history/history.js | 22 +- ui/app/ducks/index.js | 24 +- ui/app/ducks/locale/locale.js | 10 +- ui/app/ducks/metamask/metamask.js | 126 +- ui/app/ducks/send/send-duck.test.js | 78 +- ui/app/ducks/send/send.duck.js | 40 +- ui/app/ducks/swaps/swaps.js | 480 ++-- ui/app/helpers/constants/common.js | 12 +- ui/app/helpers/constants/connected-sites.js | 6 +- ui/app/helpers/constants/design-system.js | 32 +- ui/app/helpers/constants/error-keys.js | 8 +- ui/app/helpers/constants/routes.js | 128 +- ui/app/helpers/constants/swaps.js | 20 +- ui/app/helpers/constants/transactions.js | 8 +- .../authenticated/authenticated.component.js | 18 +- .../authenticated/authenticated.container.js | 12 +- .../authenticated/index.js | 2 +- .../feature-toggled-route.js | 12 +- .../initialized/index.js | 2 +- .../initialized/initialized.component.js | 12 +- .../initialized/initialized.container.js | 12 +- .../with-modal-props/index.js | 2 +- .../tests/with-modal-props.test.js | 42 +- .../with-modal-props/with-modal-props.js | 18 +- ui/app/helpers/utils/common.util.js | 2 +- ui/app/helpers/utils/common.util.test.js | 16 +- ui/app/helpers/utils/confirm-tx.util.js | 46 +- ui/app/helpers/utils/confirm-tx.util.test.js | 104 +- ui/app/helpers/utils/conversion-util.js | 132 +- ui/app/helpers/utils/conversion-util.test.js | 82 +- ui/app/helpers/utils/conversions.util.js | 58 +- ui/app/helpers/utils/conversions.util.test.js | 48 +- ui/app/helpers/utils/fetch-with-cache.js | 38 +- ui/app/helpers/utils/fetch-with-cache.test.js | 104 +- ui/app/helpers/utils/formatters.js | 2 +- ui/app/helpers/utils/i18n-helper.js | 90 +- ui/app/helpers/utils/i18n-helper.test.js | 118 +- ui/app/helpers/utils/switch-direction.js | 26 +- ui/app/helpers/utils/token-util.js | 128 +- ui/app/helpers/utils/transactions.util.js | 102 +- .../helpers/utils/transactions.util.test.js | 52 +- ui/app/helpers/utils/util.js | 286 +-- ui/app/helpers/utils/util.test.js | 418 ++-- .../hooks/tests/useCancelTransaction.test.js | 120 +- ui/app/hooks/tests/useCurrencyDisplay.test.js | 50 +- .../hooks/tests/useRetryTransaction.test.js | 68 +- ui/app/hooks/tests/useTokenData.test.js | 30 +- .../hooks/tests/useTokenDisplayValue.test.js | 36 +- .../tests/useTransactionDisplayData.test.js | 145 +- .../tests/useUserPreferencedCurrency.test.js | 44 +- ui/app/hooks/useCancelTransaction.js | 34 +- ui/app/hooks/useCopyToClipboard.js | 22 +- ui/app/hooks/useCurrencyDisplay.js | 28 +- ui/app/hooks/useCurrentAsset.js | 20 +- ui/app/hooks/useEqualityCheck.js | 12 +- ui/app/hooks/useEthFiatAmount.js | 24 +- ui/app/hooks/useI18nContext.js | 6 +- ui/app/hooks/useMethodData.js | 20 +- ui/app/hooks/useMetricEvent.js | 22 +- ui/app/hooks/usePrevious.js | 10 +- ui/app/hooks/useRetryTransaction.js | 40 +- ui/app/hooks/useShouldShowSpeedUp.js | 30 +- ui/app/hooks/useSwappedTokenValue.js | 28 +- ui/app/hooks/useSwapsEthToken.js | 14 +- ui/app/hooks/useTimeout.js | 34 +- ui/app/hooks/useTokenData.js | 10 +- ui/app/hooks/useTokenDisplayValue.js | 20 +- ui/app/hooks/useTokenFiatAmount.js | 26 +- ui/app/hooks/useTokenTracker.js | 78 +- ui/app/hooks/useTokensToSearch.js | 90 +- ui/app/hooks/useTransactionDisplayData.js | 180 +- ui/app/hooks/useUserPreferencedCurrency.js | 22 +- ui/app/pages/add-token/add-token.component.js | 164 +- ui/app/pages/add-token/add-token.container.js | 20 +- ui/app/pages/add-token/index.js | 4 +- .../pages/add-token/tests/add-token.test.js | 100 +- ui/app/pages/add-token/token-list/index.js | 4 +- .../token-list-placeholder/index.js | 4 +- .../token-list-placeholder.component.js | 10 +- .../token-list/token-list.component.js | 26 +- .../token-list/token-list.container.js | 12 +- ui/app/pages/add-token/token-search/index.js | 4 +- .../token-search/token-search.component.js | 44 +- ui/app/pages/asset/asset.js | 36 +- .../asset/components/asset-breadcrumb.js | 12 +- .../asset/components/asset-navigation.js | 16 +- ui/app/pages/asset/components/native-asset.js | 26 +- ui/app/pages/asset/components/token-asset.js | 44 +- .../pages/asset/components/token-options.js | 30 +- ui/app/pages/asset/index.js | 2 +- .../confirm-add-suggested-token.component.js | 72 +- .../confirm-add-suggested-token.container.js | 26 +- .../confirm-add-suggested-token/index.js | 4 +- .../confirm-add-token.component.js | 46 +- .../confirm-add-token.container.js | 20 +- ui/app/pages/confirm-add-token/index.js | 4 +- .../confirm-approve-content.component.js | 46 +- .../confirm-approve-content/index.js | 2 +- .../pages/confirm-approve/confirm-approve.js | 90 +- .../confirm-approve/confirm-approve.util.js | 37 +- ui/app/pages/confirm-approve/index.js | 2 +- .../confirm-decrypt-message.component.js | 156 +- .../confirm-decrypt-message.container.js | 50 +- ui/app/pages/confirm-decrypt-message/index.js | 2 +- .../confirm-deploy-contract.component.js | 20 +- .../confirm-deploy-contract.container.js | 12 +- ui/app/pages/confirm-deploy-contract/index.js | 2 +- ...confirm-encryption-public-key.component.js | 126 +- ...confirm-encryption-public-key.container.js | 40 +- .../confirm-encryption-public-key/index.js | 2 +- .../confirm-send-ether.component.js | 26 +- .../confirm-send-ether.container.js | 32 +- ui/app/pages/confirm-send-ether/index.js | 2 +- .../confirm-send-token.component.js | 20 +- .../confirm-send-token.container.js | 44 +- ui/app/pages/confirm-send-token/index.js | 2 +- ...onfirm-token-transaction-base.component.js | 46 +- ...onfirm-token-transaction-base.container.js | 50 +- .../confirm-token-transaction-base/index.js | 4 +- .../confirm-transaction-base.component.js | 234 +- .../confirm-transaction-base.container.js | 154 +- .../pages/confirm-transaction-base/index.js | 2 +- ...confirm-transaction-base.component.test.js | 20 +- .../confirm-transaction-switch.component.js | 62 +- .../confirm-transaction-switch.container.js | 28 +- .../pages/confirm-transaction-switch/index.js | 4 +- ui/app/pages/confirm-transaction/conf-tx.js | 149 +- .../confirm-transaction.component.js | 66 +- .../confirm-transaction.container.js | 46 +- ui/app/pages/confirm-transaction/index.js | 4 +- .../connected-accounts.component.js | 24 +- .../connected-accounts.container.js | 40 +- ui/app/pages/connected-accounts/index.js | 2 +- .../connected-sites.component.js | 72 +- .../connected-sites.container.js | 70 +- ui/app/pages/connected-sites/index.js | 2 +- .../connect-hardware/account-list.js | 58 +- .../create-account/connect-hardware/index.js | 179 +- .../connect-hardware/select-hardware.js | 60 +- .../create-account.component.js | 28 +- .../create-account/import-account/index.js | 40 +- .../create-account/import-account/json.js | 86 +- .../import-account/private-key.js | 76 +- ui/app/pages/create-account/index.js | 2 +- .../create-account/new-account.component.js | 30 +- .../create-account/new-account.container.js | 28 +- .../tests/create-account.test.js | 48 +- ui/app/pages/error/error.component.js | 26 +- ui/app/pages/error/index.js | 2 +- .../create-password.component.js | 24 +- .../create-password.container.js | 12 +- .../import-with-seed-phrase.component.js | 124 +- .../import-with-seed-phrase.container.js | 12 +- .../import-with-seed-phrase/index.js | 2 +- .../import-with-seed-phrase.component.test.js | 82 +- .../first-time-flow/create-password/index.js | 2 +- .../create-password/new-account/index.js | 2 +- .../new-account/new-account.component.js | 92 +- .../create-password/unique-image/index.js | 2 +- .../unique-image/unique-image.component.js | 22 +- .../unique-image/unique-image.container.js | 12 +- .../end-of-flow/end-of-flow.component.js | 52 +- .../end-of-flow/end-of-flow.container.js | 22 +- .../first-time-flow/end-of-flow/index.js | 2 +- .../end-of-flow/tests/end-of-flow.test.js | 40 +- .../first-time-flow-switch.component.js | 22 +- .../first-time-flow-switch.container.js | 12 +- .../first-time-flow-switch/index.js | 2 +- .../tests/first-time-flow-switch.test.js | 68 +- .../first-time-flow.component.js | 74 +- .../first-time-flow.container.js | 26 +- ui/app/pages/first-time-flow/index.js | 2 +- .../metametrics-opt-in/index.js | 2 +- .../metametrics-opt-in.component.js | 36 +- .../metametrics-opt-in.container.js | 22 +- .../tests/metametrics-opt-in.test.js | 30 +- .../onboarding-initiator-util.js | 38 +- .../confirm-seed-phrase.component.js | 136 +- .../confirm-seed-phrase.container.js | 12 +- .../draggable-seed.component.js | 56 +- .../seed-phrase/confirm-seed-phrase/index.js | 2 +- .../first-time-flow/seed-phrase/index.js | 2 +- .../seed-phrase/reveal-seed-phrase/index.js | 2 +- .../reveal-seed-phrase.component.js | 72 +- .../reveal-seed-phrase.container.js | 18 +- .../tests/reveal-seed-phrase.test.js | 46 +- .../seed-phrase/seed-phrase.component.js | 36 +- .../confirm-seed-phrase-component.test.js | 143 +- .../first-time-flow/select-action/index.js | 2 +- .../select-action/select-action.component.js | 34 +- .../select-action/select-action.container.js | 22 +- .../select-action/tests/select-action.test.js | 50 +- ui/app/pages/first-time-flow/welcome/index.js | 2 +- .../welcome/tests/welcome.test.js | 46 +- .../welcome/welcome.component.js | 34 +- .../welcome/welcome.container.js | 22 +- ui/app/pages/home/home.component.js | 114 +- ui/app/pages/home/home.container.js | 66 +- ui/app/pages/home/index.js | 2 +- ui/app/pages/index.js | 38 +- ui/app/pages/keychains/restore-vault.js | 94 +- ui/app/pages/keychains/reveal-seed.js | 66 +- .../pages/keychains/tests/reveal-seed.test.js | 22 +- ui/app/pages/lock/index.js | 2 +- ui/app/pages/lock/lock.component.js | 18 +- ui/app/pages/lock/lock.container.js | 22 +- ui/app/pages/lock/tests/lock.test.js | 36 +- ui/app/pages/mobile-sync/index.js | 2 +- .../mobile-sync/mobile-sync.component.js | 227 +- .../mobile-sync/mobile-sync.container.js | 22 +- .../choose-account.component.js | 90 +- .../choose-account/index.js | 2 +- ui/app/pages/permissions-connect/index.js | 2 +- .../permissions-connect.component.js | 122 +- .../permissions-connect.container.js | 76 +- .../permissions-connect/redirect/index.js | 2 +- .../permissions-redirect.component.js | 16 +- ui/app/pages/routes/index.js | 2 +- ui/app/pages/routes/routes.component.js | 184 +- ui/app/pages/routes/routes.container.js | 28 +- ui/app/pages/send/index.js | 2 +- .../add-recipient/add-recipient.component.js | 122 +- .../add-recipient/add-recipient.container.js | 26 +- .../add-recipient/add-recipient.js | 22 +- .../add-recipient/ens-input.component.js | 178 +- .../add-recipient/ens-input.container.js | 12 +- .../send-content/add-recipient/ens-input.js | 2 +- .../send/send-content/add-recipient/index.js | 2 +- .../tests/add-recipient-component.test.js | 152 +- .../tests/add-recipient-container.test.js | 46 +- .../tests/add-recipient-utils.test.js | 52 +- ui/app/pages/send/send-content/index.js | 2 +- .../amount-max-button.component.js | 34 +- .../amount-max-button.container.js | 24 +- .../amount-max-button.utils.js | 10 +- .../amount-max-button/index.js | 2 +- .../tests/amount-max-button-component.test.js | 82 +- .../tests/amount-max-button-container.test.js | 68 +- .../tests/amount-max-button-utils.test.js | 16 +- .../send-content/send-amount-row/index.js | 2 +- .../send-amount-row.component.js | 60 +- .../send-amount-row.container.js | 22 +- .../tests/send-amount-row-component.test.js | 150 +- .../tests/send-amount-row-container.test.js | 82 +- .../send/send-content/send-asset-row/index.js | 2 +- .../send-asset-row.component.js | 58 +- .../send-asset-row.container.js | 17 +- .../send-content/send-content.component.js | 40 +- .../send-content/send-content.container.js | 22 +- .../gas-fee-display.component.js | 16 +- .../send-gas-row/gas-fee-display/index.js | 2 +- .../tests/gas-fee-display.component.test.js | 59 +- .../send/send-content/send-gas-row/index.js | 2 +- .../send-gas-row/send-gas-row.component.js | 62 +- .../send-gas-row/send-gas-row.container.js | 71 +- .../tests/send-gas-row-component.test.js | 106 +- .../tests/send-gas-row-container.test.js | 138 +- .../send-content/send-hex-data-row/index.js | 2 +- .../send-hex-data-row.component.js | 26 +- .../send-hex-data-row.container.js | 14 +- .../send-content/send-row-wrapper/index.js | 2 +- .../send-row-error-message/index.js | 2 +- .../send-row-error-message.component.js | 16 +- .../send-row-error-message.container.js | 10 +- .../send-row-error-message-component.test.js | 32 +- .../send-row-error-message-container.test.js | 20 +- .../send-row-wrapper.component.js | 30 +- .../tests/send-row-wrapper-component.test.js | 66 +- .../tests/send-content-component.test.js | 122 +- ui/app/pages/send/send-footer/index.js | 2 +- .../send/send-footer/send-footer.component.js | 56 +- .../send/send-footer/send-footer.container.js | 45 +- .../send/send-footer/send-footer.utils.js | 34 +- .../tests/send-footer-component.test.js | 166 +- .../tests/send-footer-container.test.js | 90 +- .../tests/send-footer-utils.test.js | 62 +- ui/app/pages/send/send-header/index.js | 2 +- .../send/send-header/send-header.component.js | 18 +- .../send/send-header/send-header.container.js | 16 +- .../tests/send-header-component.test.js | 78 +- ui/app/pages/send/send.component.js | 170 +- ui/app/pages/send/send.constants.js | 38 +- ui/app/pages/send/send.container.js | 38 +- ui/app/pages/send/send.utils.js | 130 +- .../pages/send/tests/send-component.test.js | 391 +-- .../pages/send/tests/send-container.test.js | 89 +- ui/app/pages/send/tests/send-utils.test.js | 276 +-- .../advanced-tab/advanced-tab.component.js | 156 +- .../advanced-tab/advanced-tab.container.js | 38 +- ui/app/pages/settings/advanced-tab/index.js | 2 +- .../tests/advanced-tab-component.test.js | 38 +- .../pages/settings/alerts-tab/alerts-tab.js | 38 +- ui/app/pages/settings/alerts-tab/index.js | 2 +- .../add-contact/add-contact.component.js | 66 +- .../add-contact/add-contact.container.js | 22 +- .../contact-list-tab/add-contact/index.js | 2 +- .../contact-list-tab.component.js | 70 +- .../contact-list-tab.container.js | 42 +- .../edit-contact/edit-contact.component.js | 52 +- .../edit-contact/edit-contact.container.js | 42 +- .../contact-list-tab/edit-contact/index.js | 2 +- .../pages/settings/contact-list-tab/index.js | 2 +- .../contact-list-tab/my-accounts/index.js | 2 +- .../my-accounts/my-accounts.component.js | 20 +- .../my-accounts/my-accounts.container.js | 18 +- .../contact-list-tab/view-contact/index.js | 2 +- .../view-contact/view-contact.component.js | 36 +- .../view-contact/view-contact.container.js | 36 +- ui/app/pages/settings/index.js | 2 +- ui/app/pages/settings/info-tab/index.js | 2 +- .../settings/info-tab/info-tab.component.js | 18 +- ui/app/pages/settings/networks-tab/index.js | 2 +- .../networks-tab/network-form/index.js | 2 +- .../network-form/network-form.component.js | 212 +- .../networks-tab/networks-tab.component.js | 88 +- .../networks-tab/networks-tab.constants.js | 6 +- .../networks-tab/networks-tab.container.js | 68 +- ui/app/pages/settings/security-tab/index.js | 2 +- .../security-tab/security-tab.component.js | 51 +- .../security-tab/security-tab.container.js | 24 +- .../security-tab/tests/security-tab.test.js | 54 +- ui/app/pages/settings/settings-tab/index.js | 2 +- .../settings-tab/settings-tab.component.js | 60 +- .../settings-tab/settings-tab.container.js | 26 +- .../settings-tab/tests/settings-tab.test.js | 52 +- ui/app/pages/settings/settings.component.js | 76 +- ui/app/pages/settings/settings.container.js | 76 +- .../actionable-message/actionable-message.js | 10 +- .../actionable-message.stories.js | 18 +- .../pages/swaps/actionable-message/index.js | 2 +- .../swaps/awaiting-swap/awaiting-swap.js | 172 +- ui/app/pages/swaps/awaiting-swap/index.js | 2 +- .../awaiting-swap/quotes-timeout-icon.js | 4 +- .../swaps/awaiting-swap/swap-failure-icon.js | 4 +- .../swaps/awaiting-swap/swap-success-icon.js | 4 +- .../view-on-ether-scan-link/index.js | 2 +- .../view-on-ether-scan-link.js | 14 +- ui/app/pages/swaps/build-quote/build-quote.js | 184 +- .../swaps/build-quote/build-quote.stories.js | 30 +- ui/app/pages/swaps/build-quote/index.js | 2 +- .../swaps/countdown-timer/countdown-timer.js | 80 +- .../countdown-timer.stories.js | 28 +- ui/app/pages/swaps/countdown-timer/index.js | 2 +- .../dropdown-input-pair.js | 50 +- .../dropdown-input-pair.stories.js | 16 +- .../pages/swaps/dropdown-input-pair/index.js | 2 +- .../dropdown-search-list.js | 72 +- .../dropdown-search-list.stories.js | 14 +- .../pages/swaps/dropdown-search-list/index.js | 2 +- .../exchange-rate-display.js | 50 +- .../exchange-rate-display.stories.js | 16 +- .../swaps/exchange-rate-display/index.js | 2 +- ui/app/pages/swaps/fee-card/fee-card.js | 20 +- .../pages/swaps/fee-card/fee-card.stories.js | 26 +- ui/app/pages/swaps/fee-card/index.js | 2 +- ui/app/pages/swaps/fee-card/pig-icon.js | 4 +- ui/app/pages/swaps/index.js | 236 +- ui/app/pages/swaps/intro-popup/index.js | 2 +- ui/app/pages/swaps/intro-popup/intro-popup.js | 62 +- .../loading-swaps-quotes/aggregator-logo.js | 16 +- .../background-animation.js | 4 +- .../pages/swaps/loading-swaps-quotes/index.js | 2 +- .../loading-swaps-quotes-stories-metadata.js | 2 +- .../loading-swaps-quotes.js | 115 +- .../pages/swaps/main-quote-summary/index.js | 2 +- .../main-quote-summary/main-quote-summary.js | 42 +- .../main-quote-summary.stories.js | 12 +- .../main-quote-summary/quote-backdrop.js | 8 +- .../pages/swaps/searchable-item-list/index.js | 2 +- .../searchable-item-list/item-list/index.js | 2 +- .../item-list/item-list.component.js | 22 +- .../list-item-search/index.js | 2 +- .../list-item-search.component.js | 44 +- .../searchable-item-list.js | 22 +- .../pages/swaps/select-quote-popover/index.js | 2 +- .../select-quote-popover/mock-quote-data.js | 4 +- .../quote-details/index.js | 2 +- .../quote-details/quote-details.js | 20 +- .../select-quote-popover-constants.js | 4 +- .../select-quote-popover.js | 64 +- .../select-quote-popover.stories.js | 20 +- .../select-quote-popover/sort-list/index.js | 2 +- .../sort-list/sort-list.js | 56 +- ui/app/pages/swaps/slippage-buttons/index.js | 2 +- .../slippage-buttons/slippage-buttons.js | 76 +- .../slippage-buttons.stories.js | 10 +- ui/app/pages/swaps/swaps-footer/index.js | 2 +- .../pages/swaps/swaps-footer/swaps-footer.js | 16 +- .../swaps-gas-customization-modal/index.js | 2 +- ...swaps-gas-customization-modal.component.js | 71 +- ...swaps-gas-customization-modal.container.js | 84 +- .../pages/swaps/swaps-util-test-constants.js | 21 +- ui/app/pages/swaps/swaps.util.js | 263 +- ui/app/pages/swaps/swaps.util.test.js | 88 +- ui/app/pages/swaps/view-quote/index.js | 2 +- .../tests/view-quote-price-difference.test.js | 84 +- .../view-quote/view-quote-price-difference.js | 46 +- ui/app/pages/swaps/view-quote/view-quote.js | 308 +-- ui/app/pages/unlock-page/index.js | 4 +- .../unlock-page/tests/unlock-page.test.js | 62 +- .../unlock-page/unlock-page.component.js | 84 +- .../unlock-page/unlock-page.container.js | 50 +- ui/app/selectors/confirm-transaction.js | 133 +- ui/app/selectors/custom-gas.js | 116 +- ui/app/selectors/first-time-flow.js | 26 +- ui/app/selectors/index.js | 14 +- ui/app/selectors/permissions.js | 146 +- ui/app/selectors/selectors.js | 216 +- ui/app/selectors/send.js | 98 +- .../tests/confirm-transaction.test.js | 52 +- ui/app/selectors/tests/custom-gas.test.js | 44 +- ui/app/selectors/tests/permissions.test.js | 40 +- ui/app/selectors/tests/selectors.test.js | 86 +- .../tests/send-selectors-test-data.js | 6 +- ui/app/selectors/tests/send.test.js | 276 +-- ui/app/selectors/tests/transactions.test.js | 104 +- ui/app/selectors/transactions.js | 158 +- ui/app/store/actionConstants.js | 160 +- ui/app/store/actions.js | 2148 +++++++++-------- ui/app/store/store.js | 12 +- ui/index.js | 160 +- ui/lib/account-link.js | 18 +- ui/lib/etherscan-prefix-for-network.js | 12 +- ui/lib/icon-factory.js | 64 +- ui/lib/is-mobile-view.js | 4 +- ui/lib/shallow-with-context.js | 4 +- ui/lib/storage-helpers.js | 16 +- ui/lib/test-timeout.js | 4 +- ui/lib/tx-helper.js | 48 +- ui/lib/webcam-utils.js | 32 +- yarn.lock | 8 +- 1169 files changed, 32856 insertions(+), 32510 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 445ee523c..5bebbe073 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -53,13 +53,6 @@ module.exports = { 'prettier/prettier': 'error', - // Our usage of spaces before *named* function parens is unusual, and - // doesn't match the prettier spec. prettier does not offer an option - // to configure this - 'space-before-function-paren': [ - 'error', - { anonymous: 'always', named: 'never' }, - ], // Our eslint config has the default setting for this as error. This // include beforeBlockComment: true, but in order to match the prettier // spec you have to enable before and after blocks, objects and arrays @@ -147,7 +140,10 @@ module.exports = { 'no-invalid-this': 'off', '@babel/no-invalid-this': 'error', - '@babel/semi': ['error', 'never'], + // prettier handles these + semi: 'off', + '@babel/semi': 'off', + 'mocha/no-setup-in-describe': 'off', 'node/no-process-env': 'off', @@ -213,4 +209,4 @@ module.exports = { version: 'detect', }, }, -} +}; diff --git a/.prettierrc.yml b/.prettierrc.yml index 0d65e758a..3e9d085ce 100644 --- a/.prettierrc.yml +++ b/.prettierrc.yml @@ -1,3 +1,2 @@ singleQuote: true -semi: false trailingComma: all diff --git a/app/scripts/account-import-strategies/index.js b/app/scripts/account-import-strategies/index.js index 49444c7ad..89fd0b8c1 100644 --- a/app/scripts/account-import-strategies/index.js +++ b/app/scripts/account-import-strategies/index.js @@ -1,53 +1,53 @@ -import log from 'loglevel' -import Wallet from 'ethereumjs-wallet' -import importers from 'ethereumjs-wallet/thirdparty' -import ethUtil from 'ethereumjs-util' -import { addHexPrefix } from '../lib/util' +import log from 'loglevel'; +import Wallet from 'ethereumjs-wallet'; +import importers from 'ethereumjs-wallet/thirdparty'; +import ethUtil from 'ethereumjs-util'; +import { addHexPrefix } from '../lib/util'; const accountImporter = { importAccount(strategy, args) { try { - const importer = this.strategies[strategy] - const privateKeyHex = importer(...args) - return Promise.resolve(privateKeyHex) + const importer = this.strategies[strategy]; + const privateKeyHex = importer(...args); + return Promise.resolve(privateKeyHex); } catch (e) { - return Promise.reject(e) + return Promise.reject(e); } }, strategies: { 'Private Key': (privateKey) => { if (!privateKey) { - throw new Error('Cannot import an empty key.') + throw new Error('Cannot import an empty key.'); } - const prefixed = addHexPrefix(privateKey) - const buffer = ethUtil.toBuffer(prefixed) + const prefixed = addHexPrefix(privateKey); + const buffer = ethUtil.toBuffer(prefixed); if (!ethUtil.isValidPrivate(buffer)) { - throw new Error('Cannot import invalid private key.') + throw new Error('Cannot import invalid private key.'); } - const stripped = ethUtil.stripHexPrefix(prefixed) - return stripped + const stripped = ethUtil.stripHexPrefix(prefixed); + return stripped; }, 'JSON File': (input, password) => { - let wallet + let wallet; try { - wallet = importers.fromEtherWallet(input, password) + wallet = importers.fromEtherWallet(input, password); } catch (e) { - log.debug('Attempt to import as EtherWallet format failed, trying V3') - wallet = Wallet.fromV3(input, password, true) + log.debug('Attempt to import as EtherWallet format failed, trying V3'); + wallet = Wallet.fromV3(input, password, true); } - return walletToPrivateKey(wallet) + return walletToPrivateKey(wallet); }, }, -} +}; function walletToPrivateKey(wallet) { - const privateKeyBuffer = wallet.getPrivateKey() - return ethUtil.bufferToHex(privateKeyBuffer) + const privateKeyBuffer = wallet.getPrivateKey(); + return ethUtil.bufferToHex(privateKeyBuffer); } -export default accountImporter +export default accountImporter; diff --git a/app/scripts/background.js b/app/scripts/background.js index c63c4ade0..55a8f5a63 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -3,68 +3,68 @@ */ // these need to run before anything else /* eslint-disable import/first,import/order */ -import setupFetchDebugging from './lib/setupFetchDebugging' +import setupFetchDebugging from './lib/setupFetchDebugging'; /* eslint-enable import/order */ -setupFetchDebugging() +setupFetchDebugging(); // polyfills -import 'abortcontroller-polyfill/dist/polyfill-patch-fetch' +import 'abortcontroller-polyfill/dist/polyfill-patch-fetch'; -import endOfStream from 'end-of-stream' -import pump from 'pump' -import debounce from 'debounce-stream' -import log from 'loglevel' -import extension from 'extensionizer' -import { storeAsStream, storeTransformStream } from '@metamask/obs-store' -import PortStream from 'extension-port-stream' -import { captureException } from '@sentry/browser' +import endOfStream from 'end-of-stream'; +import pump from 'pump'; +import debounce from 'debounce-stream'; +import log from 'loglevel'; +import extension from 'extensionizer'; +import { storeAsStream, storeTransformStream } from '@metamask/obs-store'; +import PortStream from 'extension-port-stream'; +import { captureException } from '@sentry/browser'; import { ENVIRONMENT_TYPE_POPUP, ENVIRONMENT_TYPE_NOTIFICATION, ENVIRONMENT_TYPE_FULLSCREEN, -} from '../../shared/constants/app' -import migrations from './migrations' -import Migrator from './lib/migrator' -import ExtensionPlatform from './platforms/extension' -import LocalStore from './lib/local-store' -import ReadOnlyNetworkStore from './lib/network-store' -import createStreamSink from './lib/createStreamSink' -import NotificationManager from './lib/notification-manager' -import MetamaskController from './metamask-controller' -import rawFirstTimeState from './first-time-state' -import getFirstPreferredLangCode from './lib/get-first-preferred-lang-code' -import getObjStructure from './lib/getObjStructure' -import setupEnsIpfsResolver from './lib/ens-ipfs/setup' +} from '../../shared/constants/app'; +import migrations from './migrations'; +import Migrator from './lib/migrator'; +import ExtensionPlatform from './platforms/extension'; +import LocalStore from './lib/local-store'; +import ReadOnlyNetworkStore from './lib/network-store'; +import createStreamSink from './lib/createStreamSink'; +import NotificationManager from './lib/notification-manager'; +import MetamaskController from './metamask-controller'; +import rawFirstTimeState from './first-time-state'; +import getFirstPreferredLangCode from './lib/get-first-preferred-lang-code'; +import getObjStructure from './lib/getObjStructure'; +import setupEnsIpfsResolver from './lib/ens-ipfs/setup'; /* eslint-enable import/first */ -const { sentry } = global -const firstTimeState = { ...rawFirstTimeState } +const { sentry } = global; +const firstTimeState = { ...rawFirstTimeState }; -log.setDefaultLevel(process.env.METAMASK_DEBUG ? 'debug' : 'warn') +log.setDefaultLevel(process.env.METAMASK_DEBUG ? 'debug' : 'warn'); -const platform = new ExtensionPlatform() +const platform = new ExtensionPlatform(); -const notificationManager = new NotificationManager() -global.METAMASK_NOTIFIER = notificationManager +const notificationManager = new NotificationManager(); +global.METAMASK_NOTIFIER = notificationManager; -let popupIsOpen = false -let notificationIsOpen = false -const openMetamaskTabsIDs = {} -const requestAccountTabIds = {} +let popupIsOpen = false; +let notificationIsOpen = false; +const openMetamaskTabsIDs = {}; +const requestAccountTabIds = {}; // state persistence -const inTest = process.env.IN_TEST === 'true' -const localStore = inTest ? new ReadOnlyNetworkStore() : new LocalStore() -let versionedData +const inTest = process.env.IN_TEST === 'true'; +const localStore = inTest ? new ReadOnlyNetworkStore() : new LocalStore(); +let versionedData; if (inTest || process.env.METAMASK_DEBUG) { - global.metamaskGetState = localStore.get.bind(localStore) + global.metamaskGetState = localStore.get.bind(localStore); } // initialization flow -initialize().catch(log.error) +initialize().catch(log.error); /** * An object representing a transaction, in whatever state it is in. @@ -139,10 +139,10 @@ initialize().catch(log.error) * @returns {Promise} Setup complete. */ async function initialize() { - const initState = await loadStateFromPersistence() - const initLangCode = await getFirstPreferredLangCode() - await setupController(initState, initLangCode) - log.debug('MetaMask initialization complete.') + const initState = await loadStateFromPersistence(); + const initLangCode = await getFirstPreferredLangCode(); + await setupController(initState, initLangCode); + log.debug('MetaMask initialization complete.'); } // @@ -156,13 +156,13 @@ async function initialize() { */ async function loadStateFromPersistence() { // migrations - const migrator = new Migrator({ migrations }) - migrator.on('error', console.warn) + const migrator = new Migrator({ migrations }); + migrator.on('error', console.warn); // read from disk // first from preferred, async API: versionedData = - (await localStore.get()) || migrator.generateInitialState(firstTimeState) + (await localStore.get()) || migrator.generateInitialState(firstTimeState); // check if somehow state is empty // this should never happen but new error reporting suggests that it has @@ -170,38 +170,38 @@ async function loadStateFromPersistence() { // https://github.com/metamask/metamask-extension/issues/3919 if (versionedData && !versionedData.data) { // unable to recover, clear state - versionedData = migrator.generateInitialState(firstTimeState) - sentry.captureMessage('MetaMask - Empty vault found - unable to recover') + versionedData = migrator.generateInitialState(firstTimeState); + sentry.captureMessage('MetaMask - Empty vault found - unable to recover'); } // report migration errors to sentry migrator.on('error', (err) => { // get vault structure without secrets - const vaultStructure = getObjStructure(versionedData) + const vaultStructure = getObjStructure(versionedData); sentry.captureException(err, { // "extra" key is required by Sentry extra: { vaultStructure }, - }) - }) + }); + }); // migrate data - versionedData = await migrator.migrateData(versionedData) + versionedData = await migrator.migrateData(versionedData); if (!versionedData) { - throw new Error('MetaMask - migrator returned undefined') + throw new Error('MetaMask - migrator returned undefined'); } // write to disk if (localStore.isSupported) { - localStore.set(versionedData) + localStore.set(versionedData); } else { // throw in setTimeout so as to not block boot setTimeout(() => { - throw new Error('MetaMask - Localstore not supported') - }) + throw new Error('MetaMask - Localstore not supported'); + }); } // return just the data - return versionedData.data + return versionedData.data; } /** @@ -232,12 +232,12 @@ function setupController(initState, initLangCode) { platform, extension, getRequestAccountTabIds: () => { - return requestAccountTabIds + return requestAccountTabIds; }, getOpenMetamaskTabsIds: () => { - return openMetamaskTabsIDs + return openMetamaskTabsIDs; }, - }) + }); setupEnsIpfsResolver({ getCurrentNetwork: controller.getCurrentNetwork, @@ -245,7 +245,7 @@ function setupController(initState, initLangCode) { controller.preferencesController, ), provider: controller.provider, - }) + }); // setup state persistence pump( @@ -254,9 +254,9 @@ function setupController(initState, initLangCode) { storeTransformStream(versionifyData), createStreamSink(persistData), (error) => { - log.error('MetaMask - Persistence pipeline failed', error) + log.error('MetaMask - Persistence pipeline failed', error); }, - ) + ); /** * Assigns the given state to the versioned object (with metadata), and returns that. @@ -264,32 +264,32 @@ function setupController(initState, initLangCode) { * @returns {VersionedData} The state object wrapped in an object that includes a metadata key. */ function versionifyData(state) { - versionedData.data = state - return versionedData + versionedData.data = state; + return versionedData; } - let dataPersistenceFailing = false + let dataPersistenceFailing = false; async function persistData(state) { if (!state) { - throw new Error('MetaMask - updated state is missing') + throw new Error('MetaMask - updated state is missing'); } if (!state.data) { - throw new Error('MetaMask - updated state does not have data') + throw new Error('MetaMask - updated state does not have data'); } if (localStore.isSupported) { try { - await localStore.set(state) + await localStore.set(state); if (dataPersistenceFailing) { - dataPersistenceFailing = false + dataPersistenceFailing = false; } } catch (err) { // log error so we dont break the pipeline if (!dataPersistenceFailing) { - dataPersistenceFailing = true - captureException(err) + dataPersistenceFailing = true; + captureException(err); } - log.error('error setting state in local store:', err) + log.error('error setting state in local store:', err); } } } @@ -297,24 +297,24 @@ function setupController(initState, initLangCode) { // // connect to other contexts // - extension.runtime.onConnect.addListener(connectRemote) - extension.runtime.onConnectExternal.addListener(connectExternal) + extension.runtime.onConnect.addListener(connectRemote); + extension.runtime.onConnectExternal.addListener(connectExternal); const metamaskInternalProcessHash = { [ENVIRONMENT_TYPE_POPUP]: true, [ENVIRONMENT_TYPE_NOTIFICATION]: true, [ENVIRONMENT_TYPE_FULLSCREEN]: true, - } + }; - const metamaskBlockedPorts = ['trezor-connect'] + const metamaskBlockedPorts = ['trezor-connect']; const isClientOpenStatus = () => { return ( popupIsOpen || Boolean(Object.keys(openMetamaskTabsIDs).length) || notificationIsOpen - ) - } + ); + }; /** * A runtime.Port object, as provided by the browser: @@ -329,99 +329,99 @@ function setupController(initState, initLangCode) { * @param {Port} remotePort - The port provided by a new context. */ function connectRemote(remotePort) { - const processName = remotePort.name - const isMetaMaskInternalProcess = metamaskInternalProcessHash[processName] + const processName = remotePort.name; + const isMetaMaskInternalProcess = metamaskInternalProcessHash[processName]; if (metamaskBlockedPorts.includes(remotePort.name)) { - return + return; } if (isMetaMaskInternalProcess) { - const portStream = new PortStream(remotePort) + const portStream = new PortStream(remotePort); // communication with popup - controller.isClientOpen = true - controller.setupTrustedCommunication(portStream, remotePort.sender) + controller.isClientOpen = true; + controller.setupTrustedCommunication(portStream, remotePort.sender); if (processName === ENVIRONMENT_TYPE_POPUP) { - popupIsOpen = true + popupIsOpen = true; endOfStream(portStream, () => { - popupIsOpen = false - controller.isClientOpen = isClientOpenStatus() - }) + popupIsOpen = false; + controller.isClientOpen = isClientOpenStatus(); + }); } if (processName === ENVIRONMENT_TYPE_NOTIFICATION) { - notificationIsOpen = true + notificationIsOpen = true; endOfStream(portStream, () => { - notificationIsOpen = false - controller.isClientOpen = isClientOpenStatus() - }) + notificationIsOpen = false; + controller.isClientOpen = isClientOpenStatus(); + }); } if (processName === ENVIRONMENT_TYPE_FULLSCREEN) { - const tabId = remotePort.sender.tab.id - openMetamaskTabsIDs[tabId] = true + const tabId = remotePort.sender.tab.id; + openMetamaskTabsIDs[tabId] = true; endOfStream(portStream, () => { - delete openMetamaskTabsIDs[tabId] - controller.isClientOpen = isClientOpenStatus() - }) + delete openMetamaskTabsIDs[tabId]; + controller.isClientOpen = isClientOpenStatus(); + }); } } else { if (remotePort.sender && remotePort.sender.tab && remotePort.sender.url) { - const tabId = remotePort.sender.tab.id - const url = new URL(remotePort.sender.url) - const { origin } = url + const tabId = remotePort.sender.tab.id; + const url = new URL(remotePort.sender.url); + const { origin } = url; remotePort.onMessage.addListener((msg) => { if (msg.data && msg.data.method === 'eth_requestAccounts') { - requestAccountTabIds[origin] = tabId + requestAccountTabIds[origin] = tabId; } - }) + }); } - connectExternal(remotePort) + connectExternal(remotePort); } } // communication with page or other extension function connectExternal(remotePort) { - const portStream = new PortStream(remotePort) - controller.setupUntrustedCommunication(portStream, remotePort.sender) + const portStream = new PortStream(remotePort); + controller.setupUntrustedCommunication(portStream, remotePort.sender); } // // User Interface setup // - updateBadge() - controller.txController.on('update:badge', updateBadge) - controller.messageManager.on('updateBadge', updateBadge) - controller.personalMessageManager.on('updateBadge', updateBadge) - controller.decryptMessageManager.on('updateBadge', updateBadge) - controller.encryptionPublicKeyManager.on('updateBadge', updateBadge) - controller.typedMessageManager.on('updateBadge', updateBadge) - controller.approvalController.subscribe(updateBadge) - controller.appStateController.on('updateBadge', updateBadge) + updateBadge(); + controller.txController.on('update:badge', updateBadge); + controller.messageManager.on('updateBadge', updateBadge); + controller.personalMessageManager.on('updateBadge', updateBadge); + controller.decryptMessageManager.on('updateBadge', updateBadge); + controller.encryptionPublicKeyManager.on('updateBadge', updateBadge); + controller.typedMessageManager.on('updateBadge', updateBadge); + controller.approvalController.subscribe(updateBadge); + controller.appStateController.on('updateBadge', updateBadge); /** * Updates the Web Extension's "badge" number, on the little fox in the toolbar. * The number reflects the current number of pending transactions or message signatures needing user approval. */ function updateBadge() { - let label = '' - const unapprovedTxCount = controller.txController.getUnapprovedTxCount() - const { unapprovedMsgCount } = controller.messageManager - const { unapprovedPersonalMsgCount } = controller.personalMessageManager - const { unapprovedDecryptMsgCount } = controller.decryptMessageManager + let label = ''; + const unapprovedTxCount = controller.txController.getUnapprovedTxCount(); + const { unapprovedMsgCount } = controller.messageManager; + const { unapprovedPersonalMsgCount } = controller.personalMessageManager; + const { unapprovedDecryptMsgCount } = controller.decryptMessageManager; const { unapprovedEncryptionPublicKeyMsgCount, - } = controller.encryptionPublicKeyManager - const { unapprovedTypedMessagesCount } = controller.typedMessageManager - const pendingApprovalCount = controller.approvalController.getTotalApprovalCount() + } = controller.encryptionPublicKeyManager; + const { unapprovedTypedMessagesCount } = controller.typedMessageManager; + const pendingApprovalCount = controller.approvalController.getTotalApprovalCount(); const waitingForUnlockCount = - controller.appStateController.waitingForUnlock.length + controller.appStateController.waitingForUnlock.length; const count = unapprovedTxCount + unapprovedMsgCount + @@ -430,15 +430,15 @@ function setupController(initState, initLangCode) { unapprovedEncryptionPublicKeyMsgCount + unapprovedTypedMessagesCount + pendingApprovalCount + - waitingForUnlockCount + waitingForUnlockCount; if (count) { - label = String(count) + label = String(count); } - extension.browserAction.setBadgeText({ text: label }) - extension.browserAction.setBadgeBackgroundColor({ color: '#037DD6' }) + extension.browserAction.setBadgeText({ text: label }); + extension.browserAction.setBadgeBackgroundColor({ color: '#037DD6' }); } - return Promise.resolve() + return Promise.resolve(); } // @@ -449,18 +449,18 @@ function setupController(initState, initLangCode) { * Opens the browser popup for user confirmation */ async function triggerUi() { - const tabs = await platform.getActiveTabs() + const tabs = await platform.getActiveTabs(); const currentlyActiveMetamaskTab = Boolean( tabs.find((tab) => openMetamaskTabsIDs[tab.id]), - ) + ); // Vivaldi is not closing port connection on popup close, so popupIsOpen does not work correctly // To be reviewed in the future if this behaviour is fixed - also the way we determine isVivaldi variable might change at some point const isVivaldi = tabs.length > 0 && tabs[0].extData && - tabs[0].extData.indexOf('vivaldi_tab') > -1 + tabs[0].extData.indexOf('vivaldi_tab') > -1; if ((isVivaldi || !popupIsOpen) && !currentlyActiveMetamaskTab) { - await notificationManager.showPopup() + await notificationManager.showPopup(); } } @@ -469,15 +469,15 @@ async function triggerUi() { * then it waits until user interact with the UI */ async function openPopup() { - await triggerUi() + await triggerUi(); await new Promise((resolve) => { const interval = setInterval(() => { if (!notificationIsOpen) { - clearInterval(interval) - resolve() + clearInterval(interval); + resolve(); } - }, 1000) - }) + }, 1000); + }); } // On first install, open a new tab with MetaMask @@ -486,6 +486,6 @@ extension.runtime.onInstalled.addListener(({ reason }) => { reason === 'install' && !(process.env.METAMASK_DEBUG || process.env.IN_TEST) ) { - platform.openExtensionInBrowser() + platform.openExtensionInBrowser(); } -}) +}); diff --git a/app/scripts/constants/contracts.js b/app/scripts/constants/contracts.js index c2a8c9737..90df403c2 100644 --- a/app/scripts/constants/contracts.js +++ b/app/scripts/constants/contracts.js @@ -1,8 +1,8 @@ export const SINGLE_CALL_BALANCES_ADDRESS = - '0xb1f8e55c7f64d203c1400b9d8555d050f94adf39' + '0xb1f8e55c7f64d203c1400b9d8555d050f94adf39'; export const SINGLE_CALL_BALANCES_ADDRESS_RINKEBY = - '0x9f510b19f1ad66f0dcf6e45559fab0d6752c1db7' + '0x9f510b19f1ad66f0dcf6e45559fab0d6752c1db7'; export const SINGLE_CALL_BALANCES_ADDRESS_ROPSTEN = - '0xb8e671734ce5c8d7dfbbea5574fa4cf39f7a54a4' + '0xb8e671734ce5c8d7dfbbea5574fa4cf39f7a54a4'; export const SINGLE_CALL_BALANCES_ADDRESS_KOVAN = - '0xb1d3fbb2f83aecd196f474c16ca5d9cffa0d0ffc' + '0xb1d3fbb2f83aecd196f474c16ca5d9cffa0d0ffc'; diff --git a/app/scripts/contentscript.js b/app/scripts/contentscript.js index 116cad02d..a404a9cd8 100644 --- a/app/scripts/contentscript.js +++ b/app/scripts/contentscript.js @@ -1,35 +1,35 @@ -import querystring from 'querystring' -import pump from 'pump' -import LocalMessageDuplexStream from 'post-message-stream' -import ObjectMultiplex from 'obj-multiplex' -import extension from 'extensionizer' -import PortStream from 'extension-port-stream' -import { obj as createThoughStream } from 'through2' +import querystring from 'querystring'; +import pump from 'pump'; +import LocalMessageDuplexStream from 'post-message-stream'; +import ObjectMultiplex from 'obj-multiplex'; +import extension from 'extensionizer'; +import PortStream from 'extension-port-stream'; +import { obj as createThoughStream } from 'through2'; // These require calls need to use require to be statically recognized by browserify -const fs = require('fs') -const path = require('path') +const fs = require('fs'); +const path = require('path'); const inpageContent = fs.readFileSync( path.join(__dirname, '..', '..', 'dist', 'chrome', 'inpage.js'), 'utf8', -) -const inpageSuffix = `//# sourceURL=${extension.runtime.getURL('inpage.js')}\n` -const inpageBundle = inpageContent + inpageSuffix +); +const inpageSuffix = `//# sourceURL=${extension.runtime.getURL('inpage.js')}\n`; +const inpageBundle = inpageContent + inpageSuffix; -const CONTENT_SCRIPT = 'metamask-contentscript' -const INPAGE = 'metamask-inpage' -const PROVIDER = 'metamask-provider' +const CONTENT_SCRIPT = 'metamask-contentscript'; +const INPAGE = 'metamask-inpage'; +const PROVIDER = 'metamask-provider'; // TODO:LegacyProvider: Delete -const LEGACY_CONTENT_SCRIPT = 'contentscript' -const LEGACY_INPAGE = 'inpage' -const LEGACY_PROVIDER = 'provider' -const LEGACY_PUBLIC_CONFIG = 'publicConfig' +const LEGACY_CONTENT_SCRIPT = 'contentscript'; +const LEGACY_INPAGE = 'inpage'; +const LEGACY_PROVIDER = 'provider'; +const LEGACY_PUBLIC_CONFIG = 'publicConfig'; if (shouldInjectProvider()) { - injectScript(inpageBundle) - setupStreams() + injectScript(inpageBundle); + setupStreams(); } /** @@ -39,14 +39,14 @@ if (shouldInjectProvider()) { */ function injectScript(content) { try { - const container = document.head || document.documentElement - const scriptTag = document.createElement('script') - scriptTag.setAttribute('async', 'false') - scriptTag.textContent = content - container.insertBefore(scriptTag, container.children[0]) - container.removeChild(scriptTag) + const container = document.head || document.documentElement; + const scriptTag = document.createElement('script'); + scriptTag.setAttribute('async', 'false'); + scriptTag.textContent = content; + container.insertBefore(scriptTag, container.children[0]); + container.removeChild(scriptTag); } catch (error) { - console.error('MetaMask: Provider injection failed.', error) + console.error('MetaMask: Provider injection failed.', error); } } @@ -60,81 +60,81 @@ async function setupStreams() { const pageStream = new LocalMessageDuplexStream({ name: CONTENT_SCRIPT, target: INPAGE, - }) - const extensionPort = extension.runtime.connect({ name: CONTENT_SCRIPT }) - const extensionStream = new PortStream(extensionPort) + }); + const extensionPort = extension.runtime.connect({ name: CONTENT_SCRIPT }); + const extensionStream = new PortStream(extensionPort); // create and connect channel muxers // so we can handle the channels individually - const pageMux = new ObjectMultiplex() - pageMux.setMaxListeners(25) - const extensionMux = new ObjectMultiplex() - extensionMux.setMaxListeners(25) - extensionMux.ignoreStream(LEGACY_PUBLIC_CONFIG) // TODO:LegacyProvider: Delete + const pageMux = new ObjectMultiplex(); + pageMux.setMaxListeners(25); + const extensionMux = new ObjectMultiplex(); + extensionMux.setMaxListeners(25); + extensionMux.ignoreStream(LEGACY_PUBLIC_CONFIG); // TODO:LegacyProvider: Delete pump(pageMux, pageStream, pageMux, (err) => logStreamDisconnectWarning('MetaMask Inpage Multiplex', err), - ) + ); pump(extensionMux, extensionStream, extensionMux, (err) => { - logStreamDisconnectWarning('MetaMask Background Multiplex', err) - notifyInpageOfStreamFailure() - }) + logStreamDisconnectWarning('MetaMask Background Multiplex', err); + notifyInpageOfStreamFailure(); + }); // forward communication across inpage-background for these channels only - forwardTrafficBetweenMuxes(PROVIDER, pageMux, extensionMux) + forwardTrafficBetweenMuxes(PROVIDER, pageMux, extensionMux); // connect "phishing" channel to warning system - const phishingStream = extensionMux.createStream('phishing') - phishingStream.once('data', redirectToPhishingWarning) + const phishingStream = extensionMux.createStream('phishing'); + phishingStream.once('data', redirectToPhishingWarning); // TODO:LegacyProvider: Delete // handle legacy provider const legacyPageStream = new LocalMessageDuplexStream({ name: LEGACY_CONTENT_SCRIPT, target: LEGACY_INPAGE, - }) + }); - const legacyPageMux = new ObjectMultiplex() - legacyPageMux.setMaxListeners(25) - const legacyExtensionMux = new ObjectMultiplex() - legacyExtensionMux.setMaxListeners(25) + const legacyPageMux = new ObjectMultiplex(); + legacyPageMux.setMaxListeners(25); + const legacyExtensionMux = new ObjectMultiplex(); + legacyExtensionMux.setMaxListeners(25); pump(legacyPageMux, legacyPageStream, legacyPageMux, (err) => logStreamDisconnectWarning('MetaMask Legacy Inpage Multiplex', err), - ) + ); pump( legacyExtensionMux, extensionStream, getNotificationTransformStream(), legacyExtensionMux, (err) => { - logStreamDisconnectWarning('MetaMask Background Legacy Multiplex', err) - notifyInpageOfStreamFailure() + logStreamDisconnectWarning('MetaMask Background Legacy Multiplex', err); + notifyInpageOfStreamFailure(); }, - ) + ); forwardNamedTrafficBetweenMuxes( LEGACY_PROVIDER, PROVIDER, legacyPageMux, legacyExtensionMux, - ) + ); forwardTrafficBetweenMuxes( LEGACY_PUBLIC_CONFIG, legacyPageMux, legacyExtensionMux, - ) + ); } function forwardTrafficBetweenMuxes(channelName, muxA, muxB) { - const channelA = muxA.createStream(channelName) - const channelB = muxB.createStream(channelName) + const channelA = muxA.createStream(channelName); + const channelB = muxB.createStream(channelName); pump(channelA, channelB, channelA, (error) => console.debug( `MetaMask: Muxed traffic for channel "${channelName}" failed.`, error, ), - ) + ); } // TODO:LegacyProvider: Delete @@ -144,14 +144,14 @@ function forwardNamedTrafficBetweenMuxes( muxA, muxB, ) { - const channelA = muxA.createStream(channelAName) - const channelB = muxB.createStream(channelBName) + const channelA = muxA.createStream(channelAName); + const channelB = muxB.createStream(channelBName); pump(channelA, channelB, channelA, (error) => console.debug( `MetaMask: Muxed traffic between channels "${channelAName}" and "${channelBName}" failed.`, error, ), - ) + ); } // TODO:LegacyProvider: Delete @@ -159,13 +159,13 @@ function getNotificationTransformStream() { return createThoughStream((chunk, _, cb) => { if (chunk?.name === PROVIDER) { if (chunk.data?.method === 'metamask_accountsChanged') { - chunk.data.method = 'wallet_accountsChanged' - chunk.data.result = chunk.data.params - delete chunk.data.params + chunk.data.method = 'wallet_accountsChanged'; + chunk.data.result = chunk.data.params; + delete chunk.data.params; } } - cb(null, chunk) - }) + cb(null, chunk); + }); } /** @@ -178,7 +178,7 @@ function logStreamDisconnectWarning(remoteLabel, error) { console.debug( `MetaMask: Content script lost connection to "${remoteLabel}".`, error, - ) + ); } /** @@ -200,7 +200,7 @@ function notifyInpageOfStreamFailure() { }, }, window.location.origin, - ) + ); } /** @@ -214,7 +214,7 @@ function shouldInjectProvider() { suffixCheck() && documentElementCheck() && !blockedDomainCheck() - ) + ); } /** @@ -223,11 +223,11 @@ function shouldInjectProvider() { * @returns {boolean} {@code true} if the doctype is html or if none exists */ function doctypeCheck() { - const { doctype } = window.document + const { doctype } = window.document; if (doctype) { - return doctype.name === 'html' + return doctype.name === 'html'; } - return true + return true; } /** @@ -240,14 +240,14 @@ function doctypeCheck() { * @returns {boolean} whether or not the extension of the current document is prohibited */ function suffixCheck() { - const prohibitedTypes = [/\.xml$/u, /\.pdf$/u] - const currentUrl = window.location.pathname + const prohibitedTypes = [/\.xml$/u, /\.pdf$/u]; + const currentUrl = window.location.pathname; for (let i = 0; i < prohibitedTypes.length; i++) { if (prohibitedTypes[i].test(currentUrl)) { - return false + return false; } } - return true + return true; } /** @@ -256,11 +256,11 @@ function suffixCheck() { * @returns {boolean} {@code true} if the documentElement is an html node or if none exists */ function documentElementCheck() { - const documentElement = document.documentElement.nodeName + const documentElement = document.documentElement.nodeName; if (documentElement) { - return documentElement.toLowerCase() === 'html' + return documentElement.toLowerCase() === 'html'; } - return true + return true; } /** @@ -280,30 +280,30 @@ function blockedDomainCheck() { 'ani.gamer.com.tw', 'blueskybooking.com', 'sharefile.com', - ] - const currentUrl = window.location.href - let currentRegex + ]; + const currentUrl = window.location.href; + let currentRegex; for (let i = 0; i < blockedDomains.length; i++) { - const blockedDomain = blockedDomains[i].replace('.', '\\.') + const blockedDomain = blockedDomains[i].replace('.', '\\.'); currentRegex = new RegExp( `(?:https?:\\/\\/)(?:(?!${blockedDomain}).)*$`, 'u', - ) + ); if (!currentRegex.test(currentUrl)) { - return true + return true; } } - return false + return false; } /** * Redirects the current page to a phishing information page */ function redirectToPhishingWarning() { - console.debug('MetaMask: Routing to Phishing Warning component.') - const extensionURL = extension.runtime.getURL('phishing.html') + console.debug('MetaMask: Routing to Phishing Warning component.'); + const extensionURL = extension.runtime.getURL('phishing.html'); window.location.href = `${extensionURL}#${querystring.stringify({ hostname: window.location.hostname, href: window.location.href, - })}` + })}`; } diff --git a/app/scripts/controllers/alert.js b/app/scripts/controllers/alert.js index a58276d88..c7c78c04a 100644 --- a/app/scripts/controllers/alert.js +++ b/app/scripts/controllers/alert.js @@ -1,8 +1,8 @@ -import { ObservableStore } from '@metamask/obs-store' +import { ObservableStore } from '@metamask/obs-store'; import { TOGGLEABLE_ALERT_TYPES, WEB3_SHIM_USAGE_ALERT_STATES, -} from '../../../shared/constants/alerts' +} from '../../../shared/constants/alerts'; /** * @typedef {Object} AlertControllerInitState @@ -21,14 +21,14 @@ import { const defaultState = { alertEnabledness: TOGGLEABLE_ALERT_TYPES.reduce( (alertEnabledness, alertType) => { - alertEnabledness[alertType] = true - return alertEnabledness + alertEnabledness[alertType] = true; + return alertEnabledness; }, {}, ), unconnectedAccountAlertShownOrigins: {}, web3ShimUsageOrigins: {}, -} +}; /** * Controller responsible for maintaining alert-related state. @@ -39,36 +39,36 @@ export default class AlertController { * @param {AlertControllerOptions} [opts] - Controller configuration parameters */ constructor(opts = {}) { - const { initState = {}, preferencesStore } = opts + const { initState = {}, preferencesStore } = opts; const state = { ...defaultState, alertEnabledness: { ...defaultState.alertEnabledness, ...initState.alertEnabledness, }, - } + }; - this.store = new ObservableStore(state) + this.store = new ObservableStore(state); - this.selectedAddress = preferencesStore.getState().selectedAddress + this.selectedAddress = preferencesStore.getState().selectedAddress; preferencesStore.subscribe(({ selectedAddress }) => { - const currentState = this.store.getState() + const currentState = this.store.getState(); if ( currentState.unconnectedAccountAlertShownOrigins && this.selectedAddress !== selectedAddress ) { - this.selectedAddress = selectedAddress - this.store.updateState({ unconnectedAccountAlertShownOrigins: {} }) + this.selectedAddress = selectedAddress; + this.store.updateState({ unconnectedAccountAlertShownOrigins: {} }); } - }) + }); } setAlertEnabledness(alertId, enabledness) { - let { alertEnabledness } = this.store.getState() - alertEnabledness = { ...alertEnabledness } - alertEnabledness[alertId] = enabledness - this.store.updateState({ alertEnabledness }) + let { alertEnabledness } = this.store.getState(); + alertEnabledness = { ...alertEnabledness }; + alertEnabledness[alertId] = enabledness; + this.store.updateState({ alertEnabledness }); } /** @@ -76,12 +76,12 @@ export default class AlertController { * @param {string} origin - The origin the alert has been shown for */ setUnconnectedAccountAlertShown(origin) { - let { unconnectedAccountAlertShownOrigins } = this.store.getState() + let { unconnectedAccountAlertShownOrigins } = this.store.getState(); unconnectedAccountAlertShownOrigins = { ...unconnectedAccountAlertShownOrigins, - } - unconnectedAccountAlertShownOrigins[origin] = true - this.store.updateState({ unconnectedAccountAlertShownOrigins }) + }; + unconnectedAccountAlertShownOrigins[origin] = true; + this.store.updateState({ unconnectedAccountAlertShownOrigins }); } /** @@ -92,7 +92,7 @@ export default class AlertController { * origin, or undefined. */ getWeb3ShimUsageState(origin) { - return this.store.getState().web3ShimUsageOrigins[origin] + return this.store.getState().web3ShimUsageOrigins[origin]; } /** @@ -101,7 +101,7 @@ export default class AlertController { * @param {string} origin - The origin the that used the web3 shim. */ setWeb3ShimUsageRecorded(origin) { - this._setWeb3ShimUsageState(origin, WEB3_SHIM_USAGE_ALERT_STATES.RECORDED) + this._setWeb3ShimUsageState(origin, WEB3_SHIM_USAGE_ALERT_STATES.RECORDED); } /** @@ -111,7 +111,7 @@ export default class AlertController { * dismissed for. */ setWeb3ShimUsageAlertDismissed(origin) { - this._setWeb3ShimUsageState(origin, WEB3_SHIM_USAGE_ALERT_STATES.DISMISSED) + this._setWeb3ShimUsageState(origin, WEB3_SHIM_USAGE_ALERT_STATES.DISMISSED); } /** @@ -120,11 +120,11 @@ export default class AlertController { * @param {number} value - The state value to set. */ _setWeb3ShimUsageState(origin, value) { - let { web3ShimUsageOrigins } = this.store.getState() + let { web3ShimUsageOrigins } = this.store.getState(); web3ShimUsageOrigins = { ...web3ShimUsageOrigins, - } - web3ShimUsageOrigins[origin] = value - this.store.updateState({ web3ShimUsageOrigins }) + }; + web3ShimUsageOrigins[origin] = value; + this.store.updateState({ web3ShimUsageOrigins }); } } diff --git a/app/scripts/controllers/app-state.js b/app/scripts/controllers/app-state.js index 207ce96e4..0bf791821 100644 --- a/app/scripts/controllers/app-state.js +++ b/app/scripts/controllers/app-state.js @@ -1,5 +1,5 @@ -import EventEmitter from 'events' -import { ObservableStore } from '@metamask/obs-store' +import EventEmitter from 'events'; +import { ObservableStore } from '@metamask/obs-store'; export default class AppStateController extends EventEmitter { /** @@ -14,34 +14,34 @@ export default class AppStateController extends EventEmitter { onInactiveTimeout, showUnlockRequest, preferencesStore, - } = opts - super() + } = opts; + super(); - this.onInactiveTimeout = onInactiveTimeout || (() => undefined) + this.onInactiveTimeout = onInactiveTimeout || (() => undefined); this.store = new ObservableStore({ timeoutMinutes: 0, connectedStatusPopoverHasBeenShown: true, swapsWelcomeMessageHasBeenShown: false, defaultHomeActiveTabName: null, ...initState, - }) - this.timer = null + }); + this.timer = null; - this.isUnlocked = isUnlocked - this.waitingForUnlock = [] - addUnlockListener(this.handleUnlock.bind(this)) + this.isUnlocked = isUnlocked; + this.waitingForUnlock = []; + addUnlockListener(this.handleUnlock.bind(this)); - this._showUnlockRequest = showUnlockRequest + this._showUnlockRequest = showUnlockRequest; preferencesStore.subscribe(({ preferences }) => { - const currentState = this.store.getState() + const currentState = this.store.getState(); if (currentState.timeoutMinutes !== preferences.autoLockTimeLimit) { - this._setInactiveTimeout(preferences.autoLockTimeLimit) + this._setInactiveTimeout(preferences.autoLockTimeLimit); } - }) + }); - const { preferences } = preferencesStore.getState() - this._setInactiveTimeout(preferences.autoLockTimeLimit) + const { preferences } = preferencesStore.getState(); + this._setInactiveTimeout(preferences.autoLockTimeLimit); } /** @@ -56,11 +56,11 @@ export default class AppStateController extends EventEmitter { getUnlockPromise(shouldShowUnlockRequest) { return new Promise((resolve) => { if (this.isUnlocked()) { - resolve() + resolve(); } else { - this.waitForUnlock(resolve, shouldShowUnlockRequest) + this.waitForUnlock(resolve, shouldShowUnlockRequest); } - }) + }); } /** @@ -73,10 +73,10 @@ export default class AppStateController extends EventEmitter { * popup should be opened. */ waitForUnlock(resolve, shouldShowUnlockRequest) { - this.waitingForUnlock.push({ resolve }) - this.emit('updateBadge') + this.waitingForUnlock.push({ resolve }); + this.emit('updateBadge'); if (shouldShowUnlockRequest) { - this._showUnlockRequest() + this._showUnlockRequest(); } } @@ -86,9 +86,9 @@ export default class AppStateController extends EventEmitter { handleUnlock() { if (this.waitingForUnlock.length > 0) { while (this.waitingForUnlock.length > 0) { - this.waitingForUnlock.shift().resolve() + this.waitingForUnlock.shift().resolve(); } - this.emit('updateBadge') + this.emit('updateBadge'); } } @@ -99,7 +99,7 @@ export default class AppStateController extends EventEmitter { setDefaultHomeActiveTabName(defaultHomeActiveTabName) { this.store.updateState({ defaultHomeActiveTabName, - }) + }); } /** @@ -108,7 +108,7 @@ export default class AppStateController extends EventEmitter { setConnectedStatusPopoverHasBeenShown() { this.store.updateState({ connectedStatusPopoverHasBeenShown: true, - }) + }); } /** @@ -117,7 +117,7 @@ export default class AppStateController extends EventEmitter { setSwapsWelcomeMessageHasBeenShown() { this.store.updateState({ swapsWelcomeMessageHasBeenShown: true, - }) + }); } /** @@ -125,7 +125,7 @@ export default class AppStateController extends EventEmitter { * @returns {void} */ setLastActiveTime() { - this._resetTimer() + this._resetTimer(); } /** @@ -137,9 +137,9 @@ export default class AppStateController extends EventEmitter { _setInactiveTimeout(timeoutMinutes) { this.store.updateState({ timeoutMinutes, - }) + }); - this._resetTimer() + this._resetTimer(); } /** @@ -152,19 +152,19 @@ export default class AppStateController extends EventEmitter { * @private */ _resetTimer() { - const { timeoutMinutes } = this.store.getState() + const { timeoutMinutes } = this.store.getState(); if (this.timer) { - clearTimeout(this.timer) + clearTimeout(this.timer); } if (!timeoutMinutes) { - return + return; } this.timer = setTimeout( () => this.onInactiveTimeout(), timeoutMinutes * 60 * 1000, - ) + ); } } diff --git a/app/scripts/controllers/cached-balances.js b/app/scripts/controllers/cached-balances.js index 16ef40e88..d4762f84f 100644 --- a/app/scripts/controllers/cached-balances.js +++ b/app/scripts/controllers/cached-balances.js @@ -1,4 +1,4 @@ -import { ObservableStore } from '@metamask/obs-store' +import { ObservableStore } from '@metamask/obs-store'; /** * @typedef {Object} CachedBalancesOptions @@ -18,15 +18,15 @@ export default class CachedBalancesController { * @param {CachedBalancesOptions} [opts] - Controller configuration parameters */ constructor(opts = {}) { - const { accountTracker, getNetwork } = opts + const { accountTracker, getNetwork } = opts; - this.accountTracker = accountTracker - this.getNetwork = getNetwork + this.accountTracker = accountTracker; + this.getNetwork = getNetwork; - const initState = { cachedBalances: {}, ...opts.initState } - this.store = new ObservableStore(initState) + const initState = { cachedBalances: {}, ...opts.initState }; + this.store = new ObservableStore(initState); - this._registerUpdates() + this._registerUpdates(); } /** @@ -37,33 +37,33 @@ export default class CachedBalancesController { * @returns {Promise} */ async updateCachedBalances({ accounts }) { - const network = await this.getNetwork() + const network = await this.getNetwork(); const balancesToCache = await this._generateBalancesToCache( accounts, network, - ) + ); this.store.updateState({ cachedBalances: balancesToCache, - }) + }); } _generateBalancesToCache(newAccounts, currentNetwork) { - const { cachedBalances } = this.store.getState() - const currentNetworkBalancesToCache = { ...cachedBalances[currentNetwork] } + const { cachedBalances } = this.store.getState(); + const currentNetworkBalancesToCache = { ...cachedBalances[currentNetwork] }; Object.keys(newAccounts).forEach((accountID) => { - const account = newAccounts[accountID] + const account = newAccounts[accountID]; if (account.balance) { - currentNetworkBalancesToCache[accountID] = account.balance + currentNetworkBalancesToCache[accountID] = account.balance; } - }) + }); const balancesToCache = { ...cachedBalances, [currentNetwork]: currentNetworkBalancesToCache, - } + }; - return balancesToCache + return balancesToCache; } /** @@ -71,7 +71,7 @@ export default class CachedBalancesController { */ clearCachedBalances() { - this.store.updateState({ cachedBalances: {} }) + this.store.updateState({ cachedBalances: {} }); } /** @@ -83,7 +83,7 @@ export default class CachedBalancesController { * */ _registerUpdates() { - const update = this.updateCachedBalances.bind(this) - this.accountTracker.store.subscribe(update) + const update = this.updateCachedBalances.bind(this); + this.accountTracker.store.subscribe(update); } } diff --git a/app/scripts/controllers/detect-tokens.js b/app/scripts/controllers/detect-tokens.js index d91fdb989..3115f94d3 100644 --- a/app/scripts/controllers/detect-tokens.js +++ b/app/scripts/controllers/detect-tokens.js @@ -1,12 +1,12 @@ -import Web3 from 'web3' -import contracts from '@metamask/contract-metadata' -import { warn } from 'loglevel' -import SINGLE_CALL_BALANCES_ABI from 'single-call-balance-checker-abi' -import { MAINNET_CHAIN_ID } from '../../../shared/constants/network' -import { SINGLE_CALL_BALANCES_ADDRESS } from '../constants/contracts' +import Web3 from 'web3'; +import contracts from '@metamask/contract-metadata'; +import { warn } from 'loglevel'; +import SINGLE_CALL_BALANCES_ABI from 'single-call-balance-checker-abi'; +import { MAINNET_CHAIN_ID } from '../../../shared/constants/network'; +import { SINGLE_CALL_BALANCES_ADDRESS } from '../constants/contracts'; // By default, poll every 3 minutes -const DEFAULT_INTERVAL = 180 * 1000 +const DEFAULT_INTERVAL = 180 * 1000; /** * A controller that polls for token exchange @@ -24,10 +24,10 @@ export default class DetectTokensController { network, keyringMemStore, } = {}) { - this.preferences = preferences - this.interval = interval - this.network = network - this.keyringMemStore = keyringMemStore + this.preferences = preferences; + this.interval = interval; + this.network = network; + this.keyringMemStore = keyringMemStore; } /** @@ -35,59 +35,59 @@ export default class DetectTokensController { */ async detectNewTokens() { if (!this.isActive) { - return + return; } if (this._network.store.getState().provider.chainId !== MAINNET_CHAIN_ID) { - return + return; } - const tokensToDetect = [] - this.web3.setProvider(this._network._provider) + const tokensToDetect = []; + this.web3.setProvider(this._network._provider); for (const contractAddress in contracts) { if ( contracts[contractAddress].erc20 && !this.tokenAddresses.includes(contractAddress.toLowerCase()) && !this.hiddenTokens.includes(contractAddress.toLowerCase()) ) { - tokensToDetect.push(contractAddress) + tokensToDetect.push(contractAddress); } } - let result + let result; try { - result = await this._getTokenBalances(tokensToDetect) + result = await this._getTokenBalances(tokensToDetect); } catch (error) { warn( `MetaMask - DetectTokensController single call balance fetch failed`, error, - ) - return + ); + return; } tokensToDetect.forEach((tokenAddress, index) => { - const balance = result[index] + const balance = result[index]; if (balance && !balance.isZero()) { this._preferences.addToken( tokenAddress, contracts[tokenAddress].symbol, contracts[tokenAddress].decimals, - ) + ); } - }) + }); } async _getTokenBalances(tokens) { const ethContract = this.web3.eth .contract(SINGLE_CALL_BALANCES_ABI) - .at(SINGLE_CALL_BALANCES_ADDRESS) + .at(SINGLE_CALL_BALANCES_ADDRESS); return new Promise((resolve, reject) => { ethContract.balances([this.selectedAddress], tokens, (error, result) => { if (error) { - return reject(error) + return reject(error); } - return resolve(result) - }) - }) + return resolve(result); + }); + }); } /** @@ -97,10 +97,10 @@ export default class DetectTokensController { */ restartTokenDetection() { if (!(this.isActive && this.selectedAddress)) { - return + return; } - this.detectNewTokens() - this.interval = DEFAULT_INTERVAL + this.detectNewTokens(); + this.interval = DEFAULT_INTERVAL; } /* eslint-disable accessor-pairs */ @@ -108,13 +108,13 @@ export default class DetectTokensController { * @type {Number} */ set interval(interval) { - this._handle && clearInterval(this._handle) + this._handle && clearInterval(this._handle); if (!interval) { - return + return; } this._handle = setInterval(() => { - this.detectNewTokens() - }, interval) + this.detectNewTokens(); + }, interval); } /** @@ -123,26 +123,26 @@ export default class DetectTokensController { */ set preferences(preferences) { if (!preferences) { - return + return; } - this._preferences = preferences - const currentTokens = preferences.store.getState().tokens + this._preferences = preferences; + const currentTokens = preferences.store.getState().tokens; this.tokenAddresses = currentTokens ? currentTokens.map((token) => token.address) - : [] - this.hiddenTokens = preferences.store.getState().hiddenTokens + : []; + this.hiddenTokens = preferences.store.getState().hiddenTokens; preferences.store.subscribe(({ tokens = [], hiddenTokens = [] }) => { this.tokenAddresses = tokens.map((token) => { - return token.address - }) - this.hiddenTokens = hiddenTokens - }) + return token.address; + }); + this.hiddenTokens = hiddenTokens; + }); preferences.store.subscribe(({ selectedAddress }) => { if (this.selectedAddress !== selectedAddress) { - this.selectedAddress = selectedAddress - this.restartTokenDetection() + this.selectedAddress = selectedAddress; + this.restartTokenDetection(); } - }) + }); } /** @@ -150,10 +150,10 @@ export default class DetectTokensController { */ set network(network) { if (!network) { - return + return; } - this._network = network - this.web3 = new Web3(network._provider) + this._network = network; + this.web3 = new Web3(network._provider); } /** @@ -162,17 +162,17 @@ export default class DetectTokensController { */ set keyringMemStore(keyringMemStore) { if (!keyringMemStore) { - return + return; } - this._keyringMemStore = keyringMemStore + this._keyringMemStore = keyringMemStore; this._keyringMemStore.subscribe(({ isUnlocked }) => { if (this.isUnlocked !== isUnlocked) { - this.isUnlocked = isUnlocked + this.isUnlocked = isUnlocked; if (isUnlocked) { - this.restartTokenDetection() + this.restartTokenDetection(); } } - }) + }); } /** @@ -180,7 +180,7 @@ export default class DetectTokensController { * @type {Object} */ get isActive() { - return this.isOpen && this.isUnlocked + return this.isOpen && this.isUnlocked; } /* eslint-enable accessor-pairs */ } diff --git a/app/scripts/controllers/ens/ens.js b/app/scripts/controllers/ens/ens.js index f29d46aaa..0a629dd40 100644 --- a/app/scripts/controllers/ens/ens.js +++ b/app/scripts/controllers/ens/ens.js @@ -1,23 +1,23 @@ -import EthJsEns from 'ethjs-ens' -import ensNetworkMap from 'ethereum-ens-network-map' +import EthJsEns from 'ethjs-ens'; +import ensNetworkMap from 'ethereum-ens-network-map'; export default class Ens { static getNetworkEnsSupport(network) { - return Boolean(ensNetworkMap[network]) + return Boolean(ensNetworkMap[network]); } constructor({ network, provider } = {}) { this._ethJsEns = new EthJsEns({ network, provider, - }) + }); } lookup(ensName) { - return this._ethJsEns.lookup(ensName) + return this._ethJsEns.lookup(ensName); } reverse(address) { - return this._ethJsEns.reverse(address) + return this._ethJsEns.reverse(address); } } diff --git a/app/scripts/controllers/ens/index.js b/app/scripts/controllers/ens/index.js index 08647b12f..05d531103 100644 --- a/app/scripts/controllers/ens/index.js +++ b/app/scripts/controllers/ens/index.js @@ -1,95 +1,95 @@ -import punycode from 'punycode/punycode' -import ethUtil from 'ethereumjs-util' -import { ObservableStore } from '@metamask/obs-store' -import log from 'loglevel' -import Ens from './ens' +import punycode from 'punycode/punycode'; +import ethUtil from 'ethereumjs-util'; +import { ObservableStore } from '@metamask/obs-store'; +import log from 'loglevel'; +import Ens from './ens'; -const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000' -const ZERO_X_ERROR_ADDRESS = '0x' +const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'; +const ZERO_X_ERROR_ADDRESS = '0x'; export default class EnsController { constructor({ ens, provider, networkStore } = {}) { const initState = { ensResolutionsByAddress: {}, - } + }; - this._ens = ens + this._ens = ens; if (!this._ens) { - const network = networkStore.getState() + const network = networkStore.getState(); if (Ens.getNetworkEnsSupport(network)) { this._ens = new Ens({ network, provider, - }) + }); } } - this.store = new ObservableStore(initState) + this.store = new ObservableStore(initState); networkStore.subscribe((network) => { - this.store.putState(initState) + this.store.putState(initState); if (Ens.getNetworkEnsSupport(network)) { this._ens = new Ens({ network, provider, - }) + }); } else { - delete this._ens + delete this._ens; } - }) + }); } reverseResolveAddress(address) { - return this._reverseResolveAddress(ethUtil.toChecksumAddress(address)) + return this._reverseResolveAddress(ethUtil.toChecksumAddress(address)); } async _reverseResolveAddress(address) { if (!this._ens) { - return undefined + return undefined; } - const state = this.store.getState() + const state = this.store.getState(); if (state.ensResolutionsByAddress[address]) { - return state.ensResolutionsByAddress[address] + return state.ensResolutionsByAddress[address]; } - let domain + let domain; try { - domain = await this._ens.reverse(address) + domain = await this._ens.reverse(address); } catch (error) { - log.debug(error) - return undefined + log.debug(error); + return undefined; } - let registeredAddress + let registeredAddress; try { - registeredAddress = await this._ens.lookup(domain) + registeredAddress = await this._ens.lookup(domain); } catch (error) { - log.debug(error) - return undefined + log.debug(error); + return undefined; } if ( registeredAddress === ZERO_ADDRESS || registeredAddress === ZERO_X_ERROR_ADDRESS ) { - return undefined + return undefined; } if (ethUtil.toChecksumAddress(registeredAddress) !== address) { - return undefined + return undefined; } - this._updateResolutionsByAddress(address, punycode.toASCII(domain)) - return domain + this._updateResolutionsByAddress(address, punycode.toASCII(domain)); + return domain; } _updateResolutionsByAddress(address, domain) { - const oldState = this.store.getState() + const oldState = this.store.getState(); this.store.putState({ ensResolutionsByAddress: { ...oldState.ensResolutionsByAddress, [address]: domain, }, - }) + }); } } diff --git a/app/scripts/controllers/incoming-transactions.js b/app/scripts/controllers/incoming-transactions.js index e1ff68895..481810ec1 100644 --- a/app/scripts/controllers/incoming-transactions.js +++ b/app/scripts/controllers/incoming-transactions.js @@ -1,14 +1,14 @@ -import { ObservableStore } from '@metamask/obs-store' -import log from 'loglevel' -import BN from 'bn.js' -import createId from '../lib/random-id' -import { bnToHex } from '../lib/util' -import getFetchWithTimeout from '../../../shared/modules/fetch-with-timeout' +import { ObservableStore } from '@metamask/obs-store'; +import log from 'loglevel'; +import BN from 'bn.js'; +import createId from '../lib/random-id'; +import { bnToHex } from '../lib/util'; +import getFetchWithTimeout from '../../../shared/modules/fetch-with-timeout'; import { TRANSACTION_CATEGORIES, TRANSACTION_STATUSES, -} from '../../../shared/constants/transaction' +} from '../../../shared/constants/transaction'; import { CHAIN_ID_TO_NETWORK_ID_MAP, CHAIN_ID_TO_TYPE_MAP, @@ -22,9 +22,9 @@ import { RINKEBY_CHAIN_ID, ROPSTEN, ROPSTEN_CHAIN_ID, -} from '../../../shared/constants/network' +} from '../../../shared/constants/network'; -const fetchWithTimeout = getFetchWithTimeout(30000) +const fetchWithTimeout = getFetchWithTimeout(30000); /** * This controller is responsible for retrieving incoming transactions. Etherscan is polled once every block to check @@ -39,23 +39,23 @@ const etherscanSupportedNetworks = [ MAINNET_CHAIN_ID, RINKEBY_CHAIN_ID, ROPSTEN_CHAIN_ID, -] +]; export default class IncomingTransactionsController { constructor(opts = {}) { - const { blockTracker, networkController, preferencesController } = opts - this.blockTracker = blockTracker - this.networkController = networkController - this.preferencesController = preferencesController + const { blockTracker, networkController, preferencesController } = opts; + this.blockTracker = blockTracker; + this.networkController = networkController; + this.preferencesController = preferencesController; this._onLatestBlock = async (newBlockNumberHex) => { - const selectedAddress = this.preferencesController.getSelectedAddress() - const newBlockNumberDec = parseInt(newBlockNumberHex, 16) + const selectedAddress = this.preferencesController.getSelectedAddress(); + const newBlockNumberDec = parseInt(newBlockNumberHex, 16); await this._update({ address: selectedAddress, newBlockNumberDec, - }) - } + }); + }; const initState = { incomingTransactions: {}, @@ -67,8 +67,8 @@ export default class IncomingTransactionsController { [ROPSTEN]: null, }, ...opts.initState, - } - this.store = new ObservableStore(initState) + }; + this.store = new ObservableStore(initState); this.preferencesController.store.subscribe( pairwise((prevState, currState) => { @@ -76,79 +76,79 @@ export default class IncomingTransactionsController { featureFlags: { showIncomingTransactions: prevShowIncomingTransactions, } = {}, - } = prevState + } = prevState; const { featureFlags: { showIncomingTransactions: currShowIncomingTransactions, } = {}, - } = currState + } = currState; if (currShowIncomingTransactions === prevShowIncomingTransactions) { - return + return; } if (prevShowIncomingTransactions && !currShowIncomingTransactions) { - this.stop() - return + this.stop(); + return; } - this.start() + this.start(); }), - ) + ); this.preferencesController.store.subscribe( pairwise(async (prevState, currState) => { - const { selectedAddress: prevSelectedAddress } = prevState - const { selectedAddress: currSelectedAddress } = currState + const { selectedAddress: prevSelectedAddress } = prevState; + const { selectedAddress: currSelectedAddress } = currState; if (currSelectedAddress === prevSelectedAddress) { - return + return; } await this._update({ address: currSelectedAddress, - }) + }); }), - ) + ); this.networkController.on('networkDidChange', async () => { - const address = this.preferencesController.getSelectedAddress() + const address = this.preferencesController.getSelectedAddress(); await this._update({ address, - }) - }) + }); + }); } start() { - const { featureFlags = {} } = this.preferencesController.store.getState() - const { showIncomingTransactions } = featureFlags + const { featureFlags = {} } = this.preferencesController.store.getState(); + const { showIncomingTransactions } = featureFlags; if (!showIncomingTransactions) { - return + return; } - this.blockTracker.removeListener('latest', this._onLatestBlock) - this.blockTracker.addListener('latest', this._onLatestBlock) + this.blockTracker.removeListener('latest', this._onLatestBlock); + this.blockTracker.addListener('latest', this._onLatestBlock); } stop() { - this.blockTracker.removeListener('latest', this._onLatestBlock) + this.blockTracker.removeListener('latest', this._onLatestBlock); } async _update({ address, newBlockNumberDec } = {}) { - const chainId = this.networkController.getCurrentChainId() + const chainId = this.networkController.getCurrentChainId(); if (!etherscanSupportedNetworks.includes(chainId)) { - return + return; } try { const dataForUpdate = await this._getDataForUpdate({ address, chainId, newBlockNumberDec, - }) - this._updateStateWithNewTxData(dataForUpdate) + }); + this._updateStateWithNewTxData(dataForUpdate); } catch (err) { - log.error(err) + log.error(err); } } @@ -156,20 +156,20 @@ export default class IncomingTransactionsController { const { incomingTransactions: currentIncomingTxs, incomingTxLastFetchedBlocksByNetwork: currentBlocksByNetwork, - } = this.store.getState() + } = this.store.getState(); const lastFetchBlockByCurrentNetwork = - currentBlocksByNetwork[CHAIN_ID_TO_TYPE_MAP[chainId]] - let blockToFetchFrom = lastFetchBlockByCurrentNetwork || newBlockNumberDec + currentBlocksByNetwork[CHAIN_ID_TO_TYPE_MAP[chainId]]; + let blockToFetchFrom = lastFetchBlockByCurrentNetwork || newBlockNumberDec; if (blockToFetchFrom === undefined) { - blockToFetchFrom = parseInt(this.blockTracker.getCurrentBlock(), 16) + blockToFetchFrom = parseInt(this.blockTracker.getCurrentBlock(), 16); } const { latestIncomingTxBlockNumber, txs: newTxs } = await this._fetchAll( address, blockToFetchFrom, chainId, - ) + ); return { latestIncomingTxBlockNumber, @@ -178,7 +178,7 @@ export default class IncomingTransactionsController { currentBlocksByNetwork, fetchedBlockNumber: blockToFetchFrom, chainId, - } + }; } _updateStateWithNewTxData({ @@ -191,13 +191,13 @@ export default class IncomingTransactionsController { }) { const newLatestBlockHashByNetwork = latestIncomingTxBlockNumber ? parseInt(latestIncomingTxBlockNumber, 10) + 1 - : fetchedBlockNumber + 1 + : fetchedBlockNumber + 1; const newIncomingTransactions = { ...currentIncomingTxs, - } + }; newTxs.forEach((tx) => { - newIncomingTransactions[tx.hash] = tx - }) + newIncomingTransactions[tx.hash] = tx; + }); this.store.updateState({ incomingTxLastFetchedBlocksByNetwork: { @@ -205,53 +205,53 @@ export default class IncomingTransactionsController { [CHAIN_ID_TO_TYPE_MAP[chainId]]: newLatestBlockHashByNetwork, }, incomingTransactions: newIncomingTransactions, - }) + }); } async _fetchAll(address, fromBlock, chainId) { - const fetchedTxResponse = await this._fetchTxs(address, fromBlock, chainId) - return this._processTxFetchResponse(fetchedTxResponse) + const fetchedTxResponse = await this._fetchTxs(address, fromBlock, chainId); + return this._processTxFetchResponse(fetchedTxResponse); } async _fetchTxs(address, fromBlock, chainId) { const etherscanSubdomain = chainId === MAINNET_CHAIN_ID ? 'api' - : `api-${CHAIN_ID_TO_TYPE_MAP[chainId]}` + : `api-${CHAIN_ID_TO_TYPE_MAP[chainId]}`; - const apiUrl = `https://${etherscanSubdomain}.etherscan.io` - let url = `${apiUrl}/api?module=account&action=txlist&address=${address}&tag=latest&page=1` + const apiUrl = `https://${etherscanSubdomain}.etherscan.io`; + let url = `${apiUrl}/api?module=account&action=txlist&address=${address}&tag=latest&page=1`; if (fromBlock) { - url += `&startBlock=${parseInt(fromBlock, 10)}` + url += `&startBlock=${parseInt(fromBlock, 10)}`; } - const response = await fetchWithTimeout(url) - const parsedResponse = await response.json() + const response = await fetchWithTimeout(url); + const parsedResponse = await response.json(); return { ...parsedResponse, address, chainId, - } + }; } _processTxFetchResponse({ status, result = [], address, chainId }) { if (status === '1' && Array.isArray(result) && result.length > 0) { - const remoteTxList = {} - const remoteTxs = [] + const remoteTxList = {}; + const remoteTxs = []; result.forEach((tx) => { if (!remoteTxList[tx.hash]) { - remoteTxs.push(this._normalizeTxFromEtherscan(tx, chainId)) - remoteTxList[tx.hash] = 1 + remoteTxs.push(this._normalizeTxFromEtherscan(tx, chainId)); + remoteTxList[tx.hash] = 1; } - }) + }); const incomingTxs = remoteTxs.filter( (tx) => tx.txParams?.to?.toLowerCase() === address.toLowerCase(), - ) - incomingTxs.sort((a, b) => (a.time < b.time ? -1 : 1)) + ); + incomingTxs.sort((a, b) => (a.time < b.time ? -1 : 1)); - let latestIncomingTxBlockNumber = null + let latestIncomingTxBlockNumber = null; incomingTxs.forEach((tx) => { if ( tx.blockNumber && @@ -259,26 +259,26 @@ export default class IncomingTransactionsController { parseInt(latestIncomingTxBlockNumber, 10) < parseInt(tx.blockNumber, 10)) ) { - latestIncomingTxBlockNumber = tx.blockNumber + latestIncomingTxBlockNumber = tx.blockNumber; } - }) + }); return { latestIncomingTxBlockNumber, txs: incomingTxs, - } + }; } return { latestIncomingTxBlockNumber: null, txs: [], - } + }; } _normalizeTxFromEtherscan(txMeta, chainId) { - const time = parseInt(txMeta.timeStamp, 10) * 1000 + const time = parseInt(txMeta.timeStamp, 10) * 1000; const status = txMeta.isError === '0' ? TRANSACTION_STATUSES.CONFIRMED - : TRANSACTION_STATUSES.FAILED + : TRANSACTION_STATUSES.FAILED; return { blockNumber: txMeta.blockNumber, id: createId(), @@ -295,22 +295,22 @@ export default class IncomingTransactionsController { }, hash: txMeta.hash, transactionCategory: TRANSACTION_CATEGORIES.INCOMING, - } + }; } } function pairwise(fn) { - let first = true - let cache + let first = true; + let cache; return (value) => { try { if (first) { - first = false - return fn(value, value) + first = false; + return fn(value, value); } - return fn(cache, value) + return fn(cache, value); } finally { - cache = value + cache = value; } - } + }; } diff --git a/app/scripts/controllers/metametrics.js b/app/scripts/controllers/metametrics.js index 2c84ee78c..4bb1c4f46 100644 --- a/app/scripts/controllers/metametrics.js +++ b/app/scripts/controllers/metametrics.js @@ -1,11 +1,11 @@ -import { merge, omit } from 'lodash' -import { ObservableStore } from '@metamask/obs-store' -import { bufferToHex, sha3 } from 'ethereumjs-util' -import { ENVIRONMENT_TYPE_BACKGROUND } from '../../../shared/constants/app' +import { merge, omit } from 'lodash'; +import { ObservableStore } from '@metamask/obs-store'; +import { bufferToHex, sha3 } from 'ethereumjs-util'; +import { ENVIRONMENT_TYPE_BACKGROUND } from '../../../shared/constants/app'; import { METAMETRICS_ANONYMOUS_ID, METAMETRICS_BACKGROUND_PAGE_OBJECT, -} from '../../../shared/constants/metametrics' +} from '../../../shared/constants/metametrics'; /** * Used to determine whether or not to attach a user's metametrics id @@ -25,10 +25,10 @@ const trackableSendCounts = { 5000: true, 10000: true, 25000: true, -} +}; export function sendCountIsTrackable(sendCount) { - return Boolean(trackableSendCounts[sendCount]) + return Boolean(trackableSendCounts[sendCount]); } /** @@ -82,30 +82,30 @@ export default class MetaMetricsController { environment, initState, }) { - const prefState = preferencesStore.getState() - this.chainId = getCurrentChainId() - this.network = getNetworkIdentifier() - this.locale = prefState.currentLocale.replace('_', '-') + const prefState = preferencesStore.getState(); + this.chainId = getCurrentChainId(); + this.network = getNetworkIdentifier(); + this.locale = prefState.currentLocale.replace('_', '-'); this.version = - environment === 'production' ? version : `${version}-${environment}` + environment === 'production' ? version : `${version}-${environment}`; this.store = new ObservableStore({ participateInMetaMetrics: null, metaMetricsId: null, metaMetricsSendCount: 0, ...initState, - }) + }); preferencesStore.subscribe(({ currentLocale }) => { - this.locale = currentLocale.replace('_', '-') - }) + this.locale = currentLocale.replace('_', '-'); + }); onNetworkDidChange(() => { - this.chainId = getCurrentChainId() - this.network = getNetworkIdentifier() - }) - this.segment = segment - this.segmentLegacy = segmentLegacy + this.chainId = getCurrentChainId(); + this.network = getNetworkIdentifier(); + }); + this.segment = segment; + this.segmentLegacy = segmentLegacy; } generateMetaMetricsId() { @@ -114,7 +114,7 @@ export default class MetaMetricsController { String(Date.now()) + String(Math.round(Math.random() * Number.MAX_SAFE_INTEGER)), ), - ) + ); } /** @@ -126,22 +126,22 @@ export default class MetaMetricsController { * if not set */ setParticipateInMetaMetrics(participateInMetaMetrics) { - let { metaMetricsId } = this.state + let { metaMetricsId } = this.state; if (participateInMetaMetrics && !metaMetricsId) { - metaMetricsId = this.generateMetaMetricsId() + metaMetricsId = this.generateMetaMetricsId(); } else if (participateInMetaMetrics === false) { - metaMetricsId = null + metaMetricsId = null; } - this.store.updateState({ participateInMetaMetrics, metaMetricsId }) - return metaMetricsId + this.store.updateState({ participateInMetaMetrics, metaMetricsId }); + return metaMetricsId; } get state() { - return this.store.getState() + return this.store.getState(); } setMetaMetricsSendCount(val) { - this.store.updateState({ metaMetricsSendCount: val }) + this.store.updateState({ metaMetricsSendCount: val }); } /** @@ -162,7 +162,7 @@ export default class MetaMetricsController { userAgent: window.navigator.userAgent, page, referrer, - } + }; } /** @@ -185,7 +185,7 @@ export default class MetaMetricsController { page, referrer, environmentType = ENVIRONMENT_TYPE_BACKGROUND, - } = rawPayload + } = rawPayload; return { event, properties: { @@ -206,7 +206,7 @@ export default class MetaMetricsController { environment_type: environmentType, }, context: this._buildContext(referrer, page), - } + }; } /** @@ -225,20 +225,20 @@ export default class MetaMetricsController { metaMetricsId: metaMetricsIdOverride, matomoEvent, flushImmediately, - } = options || {} - let idType = 'userId' - let idValue = this.state.metaMetricsId - let excludeMetaMetricsId = options?.excludeMetaMetricsId ?? false + } = options || {}; + let idType = 'userId'; + let idValue = this.state.metaMetricsId; + let excludeMetaMetricsId = options?.excludeMetaMetricsId ?? false; // This is carried over from the old implementation, and will likely need // to be updated to work with the new tracking plan. I think we should use // a config setting for this instead of trying to match the event name - const isSendFlow = Boolean(payload.event.match(/^send|^confirm/iu)) + const isSendFlow = Boolean(payload.event.match(/^send|^confirm/iu)); if ( isSendFlow && this.state.metaMetricsSendCount && !sendCountIsTrackable(this.state.metaMetricsSendCount + 1) ) { - excludeMetaMetricsId = true + excludeMetaMetricsId = true; } // If we are tracking sensitive data we will always use the anonymousId // property as well as our METAMETRICS_ANONYMOUS_ID. This prevents us from @@ -251,12 +251,12 @@ export default class MetaMetricsController { // case we will track the opt in event to the user's id. In all other cases // we use the metaMetricsId from state. if (excludeMetaMetricsId || (isOptIn && !metaMetricsIdOverride)) { - idType = 'anonymousId' - idValue = METAMETRICS_ANONYMOUS_ID + idType = 'anonymousId'; + idValue = METAMETRICS_ANONYMOUS_ID; } else if (isOptIn && metaMetricsIdOverride) { - idValue = metaMetricsIdOverride + idValue = metaMetricsIdOverride; } - payload[idType] = idValue + payload[idType] = idValue; // Promises will only resolve when the event is sent to segment. For any // event that relies on this promise being fulfilled before performing UI @@ -269,20 +269,20 @@ export default class MetaMetricsController { // that seemingly breaks with lockdown enabled. Creating a new error // here prevents the system from freezing when the network request to // segment fails for any reason. - const safeError = new Error(err.message) - safeError.stack = err.stack - return reject(safeError) + const safeError = new Error(err.message); + safeError.stack = err.stack; + return reject(safeError); } - return resolve() - } + return resolve(); + }; - const target = matomoEvent === true ? this.segmentLegacy : this.segment + const target = matomoEvent === true ? this.segmentLegacy : this.segment; - target.track(payload, callback) + target.track(payload, callback); if (flushImmediately) { - target.flush() + target.flush(); } - }) + }); } /** @@ -293,15 +293,15 @@ export default class MetaMetricsController { */ trackPage({ name, params, environmentType, page, referrer }, options) { if (this.state.participateInMetaMetrics === false) { - return + return; } if (this.state.participateInMetaMetrics === null && !options?.isOptInPath) { - return + return; } - const { metaMetricsId } = this.state - const idTrait = metaMetricsId ? 'userId' : 'anonymousId' - const idValue = metaMetricsId ?? METAMETRICS_ANONYMOUS_ID + const { metaMetricsId } = this.state; + const idTrait = metaMetricsId ? 'userId' : 'anonymousId'; + const idValue = metaMetricsId ?? METAMETRICS_ANONYMOUS_ID; this.segment.page({ [idTrait]: idValue, name, @@ -313,7 +313,7 @@ export default class MetaMetricsController { environment_type: environmentType, }, context: this._buildContext(referrer, page), - }) + }); } /** @@ -328,16 +328,16 @@ export default class MetaMetricsController { async trackEvent(payload, options) { // event and category are required fields for all payloads if (!payload.event || !payload.category) { - throw new Error('Must specify event and category.') + throw new Error('Must specify event and category.'); } if (!this.state.participateInMetaMetrics && !options?.isOptIn) { - return + return; } // We might track multiple events if sensitiveProperties is included, this array will hold // the promises returned from this._track. - const events = [] + const events = []; if (payload.sensitiveProperties) { // sensitiveProperties will only be tracked using the anonymousId property and generic id @@ -346,13 +346,13 @@ export default class MetaMetricsController { if (options?.excludeMetaMetricsId === true) { throw new Error( 'sensitiveProperties was specified in an event payload that also set the excludeMetaMetricsId flag', - ) + ); } const combinedProperties = merge( payload.sensitiveProperties, payload.properties, - ) + ); events.push( this._track( @@ -362,11 +362,11 @@ export default class MetaMetricsController { }), { ...options, excludeMetaMetricsId: true }, ), - ) + ); } - events.push(this._track(this._buildEventPayload(payload), options)) + events.push(this._track(this._buildEventPayload(payload), options)); - await Promise.all(events) + await Promise.all(events); } } diff --git a/app/scripts/controllers/network/createInfuraClient.js b/app/scripts/controllers/network/createInfuraClient.js index 0f37ea4ca..00f5d8c68 100644 --- a/app/scripts/controllers/network/createInfuraClient.js +++ b/app/scripts/controllers/network/createInfuraClient.js @@ -1,14 +1,14 @@ -import { createScaffoldMiddleware, mergeMiddleware } from 'json-rpc-engine' -import createBlockReRefMiddleware from 'eth-json-rpc-middleware/block-ref' -import createRetryOnEmptyMiddleware from 'eth-json-rpc-middleware/retryOnEmpty' -import createBlockCacheMiddleware from 'eth-json-rpc-middleware/block-cache' -import createInflightMiddleware from 'eth-json-rpc-middleware/inflight-cache' -import createBlockTrackerInspectorMiddleware from 'eth-json-rpc-middleware/block-tracker-inspector' -import providerFromMiddleware from 'eth-json-rpc-middleware/providerFromMiddleware' -import createInfuraMiddleware from 'eth-json-rpc-infura' -import BlockTracker from 'eth-block-tracker' +import { createScaffoldMiddleware, mergeMiddleware } from 'json-rpc-engine'; +import createBlockReRefMiddleware from 'eth-json-rpc-middleware/block-ref'; +import createRetryOnEmptyMiddleware from 'eth-json-rpc-middleware/retryOnEmpty'; +import createBlockCacheMiddleware from 'eth-json-rpc-middleware/block-cache'; +import createInflightMiddleware from 'eth-json-rpc-middleware/inflight-cache'; +import createBlockTrackerInspectorMiddleware from 'eth-json-rpc-middleware/block-tracker-inspector'; +import providerFromMiddleware from 'eth-json-rpc-middleware/providerFromMiddleware'; +import createInfuraMiddleware from 'eth-json-rpc-infura'; +import BlockTracker from 'eth-block-tracker'; -import { NETWORK_TYPE_TO_ID_MAP } from '../../../../shared/constants/network' +import { NETWORK_TYPE_TO_ID_MAP } from '../../../../shared/constants/network'; export default function createInfuraClient({ network, projectId }) { const infuraMiddleware = createInfuraMiddleware({ @@ -16,9 +16,9 @@ export default function createInfuraClient({ network, projectId }) { projectId, maxAttempts: 5, source: 'metamask', - }) - const infuraProvider = providerFromMiddleware(infuraMiddleware) - const blockTracker = new BlockTracker({ provider: infuraProvider }) + }); + const infuraProvider = providerFromMiddleware(infuraMiddleware); + const blockTracker = new BlockTracker({ provider: infuraProvider }); const networkMiddleware = mergeMiddleware([ createNetworkAndChainIdMiddleware({ network }), @@ -28,19 +28,19 @@ export default function createInfuraClient({ network, projectId }) { createRetryOnEmptyMiddleware({ blockTracker, provider: infuraProvider }), createBlockTrackerInspectorMiddleware({ blockTracker }), infuraMiddleware, - ]) - return { networkMiddleware, blockTracker } + ]); + return { networkMiddleware, blockTracker }; } function createNetworkAndChainIdMiddleware({ network }) { if (!NETWORK_TYPE_TO_ID_MAP[network]) { - throw new Error(`createInfuraClient - unknown network "${network}"`) + throw new Error(`createInfuraClient - unknown network "${network}"`); } - const { chainId, networkId } = NETWORK_TYPE_TO_ID_MAP[network] + const { chainId, networkId } = NETWORK_TYPE_TO_ID_MAP[network]; return createScaffoldMiddleware({ eth_chainId: chainId, net_version: networkId, - }) + }); } diff --git a/app/scripts/controllers/network/createJsonRpcClient.js b/app/scripts/controllers/network/createJsonRpcClient.js index cc8e9edc5..836801a0f 100644 --- a/app/scripts/controllers/network/createJsonRpcClient.js +++ b/app/scripts/controllers/network/createJsonRpcClient.js @@ -1,25 +1,25 @@ -import { createAsyncMiddleware, mergeMiddleware } from 'json-rpc-engine' -import createFetchMiddleware from 'eth-json-rpc-middleware/fetch' -import createBlockRefRewriteMiddleware from 'eth-json-rpc-middleware/block-ref-rewrite' -import createBlockCacheMiddleware from 'eth-json-rpc-middleware/block-cache' -import createInflightMiddleware from 'eth-json-rpc-middleware/inflight-cache' -import createBlockTrackerInspectorMiddleware from 'eth-json-rpc-middleware/block-tracker-inspector' -import providerFromMiddleware from 'eth-json-rpc-middleware/providerFromMiddleware' -import BlockTracker from 'eth-block-tracker' +import { createAsyncMiddleware, mergeMiddleware } from 'json-rpc-engine'; +import createFetchMiddleware from 'eth-json-rpc-middleware/fetch'; +import createBlockRefRewriteMiddleware from 'eth-json-rpc-middleware/block-ref-rewrite'; +import createBlockCacheMiddleware from 'eth-json-rpc-middleware/block-cache'; +import createInflightMiddleware from 'eth-json-rpc-middleware/inflight-cache'; +import createBlockTrackerInspectorMiddleware from 'eth-json-rpc-middleware/block-tracker-inspector'; +import providerFromMiddleware from 'eth-json-rpc-middleware/providerFromMiddleware'; +import BlockTracker from 'eth-block-tracker'; -const inTest = process.env.IN_TEST === 'true' -const blockTrackerOpts = inTest ? { pollingInterval: 1000 } : {} +const inTest = process.env.IN_TEST === 'true'; +const blockTrackerOpts = inTest ? { pollingInterval: 1000 } : {}; const getTestMiddlewares = () => { - return inTest ? [createEstimateGasDelayTestMiddleware()] : [] -} + return inTest ? [createEstimateGasDelayTestMiddleware()] : []; +}; export default function createJsonRpcClient({ rpcUrl, chainId }) { - const fetchMiddleware = createFetchMiddleware({ rpcUrl }) - const blockProvider = providerFromMiddleware(fetchMiddleware) + const fetchMiddleware = createFetchMiddleware({ rpcUrl }); + const blockProvider = providerFromMiddleware(fetchMiddleware); const blockTracker = new BlockTracker({ ...blockTrackerOpts, provider: blockProvider, - }) + }); const networkMiddleware = mergeMiddleware([ ...getTestMiddlewares(), @@ -29,19 +29,19 @@ export default function createJsonRpcClient({ rpcUrl, chainId }) { createInflightMiddleware(), createBlockTrackerInspectorMiddleware({ blockTracker }), fetchMiddleware, - ]) + ]); - return { networkMiddleware, blockTracker } + return { networkMiddleware, blockTracker }; } function createChainIdMiddleware(chainId) { return (req, res, next, end) => { if (req.method === 'eth_chainId') { - res.result = chainId - return end() + res.result = chainId; + return end(); } - return next() - } + return next(); + }; } /** @@ -51,8 +51,8 @@ function createChainIdMiddleware(chainId) { function createEstimateGasDelayTestMiddleware() { return createAsyncMiddleware(async (req, _, next) => { if (req.method === 'eth_estimateGas') { - await new Promise((resolve) => setTimeout(resolve, 2000)) + await new Promise((resolve) => setTimeout(resolve, 2000)); } - return next() - }) + return next(); + }); } diff --git a/app/scripts/controllers/network/createMetamaskMiddleware.js b/app/scripts/controllers/network/createMetamaskMiddleware.js index f4e9c5d1a..c3803a061 100644 --- a/app/scripts/controllers/network/createMetamaskMiddleware.js +++ b/app/scripts/controllers/network/createMetamaskMiddleware.js @@ -1,9 +1,9 @@ -import { createScaffoldMiddleware, mergeMiddleware } from 'json-rpc-engine' -import createWalletSubprovider from 'eth-json-rpc-middleware/wallet' +import { createScaffoldMiddleware, mergeMiddleware } from 'json-rpc-engine'; +import createWalletSubprovider from 'eth-json-rpc-middleware/wallet'; import { createPendingNonceMiddleware, createPendingTxMiddleware, -} from './middleware/pending' +} from './middleware/pending'; export default function createMetamaskMiddleware({ version, @@ -38,6 +38,6 @@ export default function createMetamaskMiddleware({ }), createPendingNonceMiddleware({ getPendingNonce }), createPendingTxMiddleware({ getPendingTransactionByHash }), - ]) - return metamaskMiddleware + ]); + return metamaskMiddleware; } diff --git a/app/scripts/controllers/network/index.js b/app/scripts/controllers/network/index.js index a090538f5..a0a43faa5 100644 --- a/app/scripts/controllers/network/index.js +++ b/app/scripts/controllers/network/index.js @@ -1 +1 @@ -export { default } from './network' +export { default } from './network'; diff --git a/app/scripts/controllers/network/middleware/pending.js b/app/scripts/controllers/network/middleware/pending.js index 905e44129..9852d5552 100644 --- a/app/scripts/controllers/network/middleware/pending.js +++ b/app/scripts/controllers/network/middleware/pending.js @@ -1,35 +1,35 @@ -import { createAsyncMiddleware } from 'json-rpc-engine' -import { formatTxMetaForRpcResult } from '../util' +import { createAsyncMiddleware } from 'json-rpc-engine'; +import { formatTxMetaForRpcResult } from '../util'; export function createPendingNonceMiddleware({ getPendingNonce }) { return createAsyncMiddleware(async (req, res, next) => { - const { method, params } = req + const { method, params } = req; if (method !== 'eth_getTransactionCount') { - next() - return + next(); + return; } - const [param, blockRef] = params + const [param, blockRef] = params; if (blockRef !== 'pending') { - next() - return + next(); + return; } - res.result = await getPendingNonce(param) - }) + res.result = await getPendingNonce(param); + }); } export function createPendingTxMiddleware({ getPendingTransactionByHash }) { return createAsyncMiddleware(async (req, res, next) => { - const { method, params } = req + const { method, params } = req; if (method !== 'eth_getTransactionByHash') { - next() - return + next(); + return; } - const [hash] = params - const txMeta = getPendingTransactionByHash(hash) + const [hash] = params; + const txMeta = getPendingTransactionByHash(hash); if (!txMeta) { - next() - return + next(); + return; } - res.result = formatTxMetaForRpcResult(txMeta) - }) + res.result = formatTxMetaForRpcResult(txMeta); + }); } diff --git a/app/scripts/controllers/network/network.js b/app/scripts/controllers/network/network.js index 605d01ade..605b0063a 100644 --- a/app/scripts/controllers/network/network.js +++ b/app/scripts/controllers/network/network.js @@ -1,14 +1,14 @@ -import assert from 'assert' -import EventEmitter from 'events' -import { ComposedStore, ObservableStore } from '@metamask/obs-store' -import { JsonRpcEngine } from 'json-rpc-engine' -import providerFromEngine from 'eth-json-rpc-middleware/providerFromEngine' -import log from 'loglevel' +import assert from 'assert'; +import EventEmitter from 'events'; +import { ComposedStore, ObservableStore } from '@metamask/obs-store'; +import { JsonRpcEngine } from 'json-rpc-engine'; +import providerFromEngine from 'eth-json-rpc-middleware/providerFromEngine'; +import log from 'loglevel'; import { createSwappableProxy, createEventEmitterProxy, -} from 'swappable-obj-proxy' -import EthQuery from 'eth-query' +} from 'swappable-obj-proxy'; +import EthQuery from 'eth-query'; import { RINKEBY, MAINNET, @@ -17,63 +17,63 @@ import { NETWORK_TYPE_TO_ID_MAP, MAINNET_CHAIN_ID, RINKEBY_CHAIN_ID, -} from '../../../../shared/constants/network' +} from '../../../../shared/constants/network'; import { isPrefixedFormattedHexString, isSafeChainId, -} from '../../../../shared/modules/utils' -import createMetamaskMiddleware from './createMetamaskMiddleware' -import createInfuraClient from './createInfuraClient' -import createJsonRpcClient from './createJsonRpcClient' +} from '../../../../shared/modules/utils'; +import createMetamaskMiddleware from './createMetamaskMiddleware'; +import createInfuraClient from './createInfuraClient'; +import createJsonRpcClient from './createJsonRpcClient'; -const env = process.env.METAMASK_ENV +const env = process.env.METAMASK_ENV; -let defaultProviderConfigOpts +let defaultProviderConfigOpts; if (process.env.IN_TEST === 'true') { defaultProviderConfigOpts = { type: NETWORK_TYPE_RPC, rpcUrl: 'http://localhost:8545', chainId: '0x539', nickname: 'Localhost 8545', - } + }; } else if (process.env.METAMASK_DEBUG || env === 'test') { - defaultProviderConfigOpts = { type: RINKEBY, chainId: RINKEBY_CHAIN_ID } + defaultProviderConfigOpts = { type: RINKEBY, chainId: RINKEBY_CHAIN_ID }; } else { - defaultProviderConfigOpts = { type: MAINNET, chainId: MAINNET_CHAIN_ID } + defaultProviderConfigOpts = { type: MAINNET, chainId: MAINNET_CHAIN_ID }; } const defaultProviderConfig = { ticker: 'ETH', ...defaultProviderConfigOpts, -} +}; export default class NetworkController extends EventEmitter { constructor(opts = {}) { - super() + super(); // create stores this.providerStore = new ObservableStore( opts.provider || { ...defaultProviderConfig }, - ) + ); this.previousProviderStore = new ObservableStore( this.providerStore.getState(), - ) - this.networkStore = new ObservableStore('loading') + ); + this.networkStore = new ObservableStore('loading'); this.store = new ComposedStore({ provider: this.providerStore, previousProviderStore: this.previousProviderStore, network: this.networkStore, - }) + }); // provider and block tracker - this._provider = null - this._blockTracker = null + this._provider = null; + this._blockTracker = null; // provider and block tracker proxies - because the network changes - this._providerProxy = null - this._blockTrackerProxy = null + this._providerProxy = null; + this._blockTrackerProxy = null; - this.on('networkDidChange', this.lookupNetwork) + this.on('networkDidChange', this.lookupNetwork); } /** @@ -85,43 +85,43 @@ export default class NetworkController extends EventEmitter { */ setInfuraProjectId(projectId) { if (!projectId || typeof projectId !== 'string') { - throw new Error('Invalid Infura project ID') + throw new Error('Invalid Infura project ID'); } - this._infuraProjectId = projectId + this._infuraProjectId = projectId; } initializeProvider(providerParams) { - this._baseProviderParams = providerParams - const { type, rpcUrl, chainId } = this.getProviderConfig() - this._configureProvider({ type, rpcUrl, chainId }) - this.lookupNetwork() + this._baseProviderParams = providerParams; + const { type, rpcUrl, chainId } = this.getProviderConfig(); + this._configureProvider({ type, rpcUrl, chainId }); + this.lookupNetwork(); } // return the proxies so the references will always be good getProviderAndBlockTracker() { - const provider = this._providerProxy - const blockTracker = this._blockTrackerProxy - return { provider, blockTracker } + const provider = this._providerProxy; + const blockTracker = this._blockTrackerProxy; + return { provider, blockTracker }; } verifyNetwork() { // Check network when restoring connectivity: if (this.isNetworkLoading()) { - this.lookupNetwork() + this.lookupNetwork(); } } getNetworkState() { - return this.networkStore.getState() + return this.networkStore.getState(); } setNetworkState(network) { - this.networkStore.putState(network) + this.networkStore.putState(network); } isNetworkLoading() { - return this.getNetworkState() === 'loading' + return this.getNetworkState() === 'loading'; } lookupNetwork() { @@ -129,49 +129,49 @@ export default class NetworkController extends EventEmitter { if (!this._provider) { log.warn( 'NetworkController - lookupNetwork aborted due to missing provider', - ) - return + ); + return; } - const chainId = this.getCurrentChainId() + const chainId = this.getCurrentChainId(); if (!chainId) { log.warn( 'NetworkController - lookupNetwork aborted due to missing chainId', - ) - this.setNetworkState('loading') - return + ); + this.setNetworkState('loading'); + return; } // Ping the RPC endpoint so we can confirm that it works - const ethQuery = new EthQuery(this._provider) - const initialNetwork = this.getNetworkState() + const ethQuery = new EthQuery(this._provider); + const initialNetwork = this.getNetworkState(); ethQuery.sendAsync({ method: 'net_version' }, (err, networkVersion) => { - const currentNetwork = this.getNetworkState() + const currentNetwork = this.getNetworkState(); if (initialNetwork === currentNetwork) { if (err) { - this.setNetworkState('loading') - return + this.setNetworkState('loading'); + return; } - this.setNetworkState(networkVersion) + this.setNetworkState(networkVersion); } - }) + }); } getCurrentChainId() { - const { type, chainId: configChainId } = this.getProviderConfig() - return NETWORK_TYPE_TO_ID_MAP[type]?.chainId || configChainId + const { type, chainId: configChainId } = this.getProviderConfig(); + return NETWORK_TYPE_TO_ID_MAP[type]?.chainId || configChainId; } setRpcTarget(rpcUrl, chainId, ticker = 'ETH', nickname = '', rpcPrefs) { assert.ok( isPrefixedFormattedHexString(chainId), `Invalid chain ID "${chainId}": invalid hex string.`, - ) + ); assert.ok( isSafeChainId(parseInt(chainId, 16)), `Invalid chain ID "${chainId}": numerical value greater than max safe value.`, - ) + ); this.setProviderConfig({ type: NETWORK_TYPE_RPC, rpcUrl, @@ -179,7 +179,7 @@ export default class NetworkController extends EventEmitter { ticker, nickname, rpcPrefs, - }) + }); } async setProviderType(type, rpcUrl = '', ticker = 'ETH', nickname = '') { @@ -187,41 +187,41 @@ export default class NetworkController extends EventEmitter { type, NETWORK_TYPE_RPC, `NetworkController - cannot call "setProviderType" with type "${NETWORK_TYPE_RPC}". Use "setRpcTarget"`, - ) + ); assert.ok( INFURA_PROVIDER_TYPES.includes(type), `Unknown Infura provider type "${type}".`, - ) - const { chainId } = NETWORK_TYPE_TO_ID_MAP[type] - this.setProviderConfig({ type, rpcUrl, chainId, ticker, nickname }) + ); + const { chainId } = NETWORK_TYPE_TO_ID_MAP[type]; + this.setProviderConfig({ type, rpcUrl, chainId, ticker, nickname }); } resetConnection() { - this.setProviderConfig(this.getProviderConfig()) + this.setProviderConfig(this.getProviderConfig()); } /** * Sets the provider config and switches the network. */ setProviderConfig(config) { - this.previousProviderStore.updateState(this.getProviderConfig()) - this.providerStore.updateState(config) - this._switchNetwork(config) + this.previousProviderStore.updateState(this.getProviderConfig()); + this.providerStore.updateState(config); + this._switchNetwork(config); } rollbackToPreviousProvider() { - const config = this.previousProviderStore.getState() - this.providerStore.updateState(config) - this._switchNetwork(config) + const config = this.previousProviderStore.getState(); + this.providerStore.updateState(config); + this._switchNetwork(config); } getProviderConfig() { - return this.providerStore.getState() + return this.providerStore.getState(); } getNetworkIdentifier() { - const provider = this.providerStore.getState() - return provider.type === NETWORK_TYPE_RPC ? provider.rpcUrl : provider.type + const provider = this.providerStore.getState(); + return provider.type === NETWORK_TYPE_RPC ? provider.rpcUrl : provider.type; } // @@ -229,68 +229,68 @@ export default class NetworkController extends EventEmitter { // _switchNetwork(opts) { - this.setNetworkState('loading') - this._configureProvider(opts) - this.emit('networkDidChange', opts.type) + this.setNetworkState('loading'); + this._configureProvider(opts); + this.emit('networkDidChange', opts.type); } _configureProvider({ type, rpcUrl, chainId }) { // infura type-based endpoints - const isInfura = INFURA_PROVIDER_TYPES.includes(type) + const isInfura = INFURA_PROVIDER_TYPES.includes(type); if (isInfura) { - this._configureInfuraProvider(type, this._infuraProjectId) + this._configureInfuraProvider(type, this._infuraProjectId); // url-based rpc endpoints } else if (type === NETWORK_TYPE_RPC) { - this._configureStandardProvider(rpcUrl, chainId) + this._configureStandardProvider(rpcUrl, chainId); } else { throw new Error( `NetworkController - _configureProvider - unknown type "${type}"`, - ) + ); } } _configureInfuraProvider(type, projectId) { - log.info('NetworkController - configureInfuraProvider', type) + log.info('NetworkController - configureInfuraProvider', type); const networkClient = createInfuraClient({ network: type, projectId, - }) - this._setNetworkClient(networkClient) + }); + this._setNetworkClient(networkClient); } _configureStandardProvider(rpcUrl, chainId) { - log.info('NetworkController - configureStandardProvider', rpcUrl) - const networkClient = createJsonRpcClient({ rpcUrl, chainId }) - this._setNetworkClient(networkClient) + log.info('NetworkController - configureStandardProvider', rpcUrl); + const networkClient = createJsonRpcClient({ rpcUrl, chainId }); + this._setNetworkClient(networkClient); } _setNetworkClient({ networkMiddleware, blockTracker }) { const metamaskMiddleware = createMetamaskMiddleware( this._baseProviderParams, - ) - const engine = new JsonRpcEngine() - engine.push(metamaskMiddleware) - engine.push(networkMiddleware) - const provider = providerFromEngine(engine) - this._setProviderAndBlockTracker({ provider, blockTracker }) + ); + const engine = new JsonRpcEngine(); + engine.push(metamaskMiddleware); + engine.push(networkMiddleware); + const provider = providerFromEngine(engine); + this._setProviderAndBlockTracker({ provider, blockTracker }); } _setProviderAndBlockTracker({ provider, blockTracker }) { // update or intialize proxies if (this._providerProxy) { - this._providerProxy.setTarget(provider) + this._providerProxy.setTarget(provider); } else { - this._providerProxy = createSwappableProxy(provider) + this._providerProxy = createSwappableProxy(provider); } if (this._blockTrackerProxy) { - this._blockTrackerProxy.setTarget(blockTracker) + this._blockTrackerProxy.setTarget(blockTracker); } else { this._blockTrackerProxy = createEventEmitterProxy(blockTracker, { eventFilter: 'skipInternal', - }) + }); } // set new provider and blockTracker - this._provider = provider - this._blockTracker = blockTracker + this._provider = provider; + this._blockTracker = blockTracker; } } diff --git a/app/scripts/controllers/network/util.js b/app/scripts/controllers/network/util.js index 9c80db551..7f55f2521 100644 --- a/app/scripts/controllers/network/util.js +++ b/app/scripts/controllers/network/util.js @@ -1,6 +1,6 @@ -import { NETWORK_TO_NAME_MAP } from '../../../../shared/constants/network' +import { NETWORK_TO_NAME_MAP } from '../../../../shared/constants/network'; -export const getNetworkDisplayName = (key) => NETWORK_TO_NAME_MAP[key] +export const getNetworkDisplayName = (key) => NETWORK_TO_NAME_MAP[key]; export function formatTxMetaForRpcResult(txMeta) { return { @@ -20,5 +20,5 @@ export function formatTxMetaForRpcResult(txMeta) { v: txMeta.v, r: txMeta.r, s: txMeta.s, - } + }; } diff --git a/app/scripts/controllers/onboarding.js b/app/scripts/controllers/onboarding.js index 011edbfc3..5e55d0e0f 100644 --- a/app/scripts/controllers/onboarding.js +++ b/app/scripts/controllers/onboarding.js @@ -1,5 +1,5 @@ -import { ObservableStore } from '@metamask/obs-store' -import log from 'loglevel' +import { ObservableStore } from '@metamask/obs-store'; +import log from 'loglevel'; /** * @typedef {Object} InitState @@ -25,30 +25,30 @@ export default class OnboardingController { constructor(opts = {}) { const initialTransientState = { onboardingTabs: {}, - } + }; const initState = { seedPhraseBackedUp: null, ...opts.initState, ...initialTransientState, - } - this.store = new ObservableStore(initState) - this.preferencesController = opts.preferencesController - this.completedOnboarding = this.preferencesController.store.getState().completedOnboarding + }; + this.store = new ObservableStore(initState); + this.preferencesController = opts.preferencesController; + this.completedOnboarding = this.preferencesController.store.getState().completedOnboarding; this.preferencesController.store.subscribe(({ completedOnboarding }) => { if (completedOnboarding !== this.completedOnboarding) { - this.completedOnboarding = completedOnboarding + this.completedOnboarding = completedOnboarding; if (completedOnboarding) { - this.store.updateState(initialTransientState) + this.store.updateState(initialTransientState); } } - }) + }); } setSeedPhraseBackedUp(newSeedPhraseBackUpState) { this.store.updateState({ seedPhraseBackedUp: newSeedPhraseBackUpState, - }) + }); } /** @@ -59,16 +59,16 @@ export default class OnboardingController { */ registerOnboarding = async (location, tabId) => { if (this.completedOnboarding) { - log.debug('Ignoring registerOnboarding; user already onboarded') - return + log.debug('Ignoring registerOnboarding; user already onboarded'); + return; } - const onboardingTabs = { ...this.store.getState().onboardingTabs } + const onboardingTabs = { ...this.store.getState().onboardingTabs }; if (!onboardingTabs[location] || onboardingTabs[location] !== tabId) { log.debug( `Registering onboarding tab at location '${location}' with tabId '${tabId}'`, - ) - onboardingTabs[location] = tabId - this.store.updateState({ onboardingTabs }) + ); + onboardingTabs[location] = tabId; + this.store.updateState({ onboardingTabs }); } - } + }; } diff --git a/app/scripts/controllers/permissions/enums.js b/app/scripts/controllers/permissions/enums.js index 21356804f..447040bed 100644 --- a/app/scripts/controllers/permissions/enums.js +++ b/app/scripts/controllers/permissions/enums.js @@ -1,37 +1,37 @@ -export const APPROVAL_TYPE = 'wallet_requestPermissions' +export const APPROVAL_TYPE = 'wallet_requestPermissions'; -export const WALLET_PREFIX = 'wallet_' +export const WALLET_PREFIX = 'wallet_'; -export const HISTORY_STORE_KEY = 'permissionsHistory' +export const HISTORY_STORE_KEY = 'permissionsHistory'; -export const LOG_STORE_KEY = 'permissionsLog' +export const LOG_STORE_KEY = 'permissionsLog'; -export const METADATA_STORE_KEY = 'domainMetadata' +export const METADATA_STORE_KEY = 'domainMetadata'; -export const METADATA_CACHE_MAX_SIZE = 100 +export const METADATA_CACHE_MAX_SIZE = 100; export const CAVEAT_TYPES = { limitResponseLength: 'limitResponseLength', filterResponse: 'filterResponse', -} +}; export const NOTIFICATION_NAMES = { accountsChanged: 'metamask_accountsChanged', unlockStateChanged: 'metamask_unlockStateChanged', chainChanged: 'metamask_chainChanged', -} +}; export const LOG_IGNORE_METHODS = [ 'wallet_registerOnboarding', 'wallet_watchAsset', -] +]; export const LOG_METHOD_TYPES = { restricted: 'restricted', internal: 'internal', -} +}; -export const LOG_LIMIT = 100 +export const LOG_LIMIT = 100; export const SAFE_METHODS = [ 'eth_blockNumber', @@ -90,4 +90,4 @@ export const SAFE_METHODS = [ 'wallet_watchAsset', 'web3_clientVersion', 'web3_sha3', -] +]; diff --git a/app/scripts/controllers/permissions/index.js b/app/scripts/controllers/permissions/index.js index 5d22a69c4..c10a950cb 100644 --- a/app/scripts/controllers/permissions/index.js +++ b/app/scripts/controllers/permissions/index.js @@ -1,12 +1,12 @@ -import nanoid from 'nanoid' -import { JsonRpcEngine } from 'json-rpc-engine' -import { ObservableStore } from '@metamask/obs-store' -import log from 'loglevel' -import { CapabilitiesController as RpcCap } from 'rpc-cap' -import { ethErrors } from 'eth-rpc-errors' -import { cloneDeep } from 'lodash' +import nanoid from 'nanoid'; +import { JsonRpcEngine } from 'json-rpc-engine'; +import { ObservableStore } from '@metamask/obs-store'; +import log from 'loglevel'; +import { CapabilitiesController as RpcCap } from 'rpc-cap'; +import { ethErrors } from 'eth-rpc-errors'; +import { cloneDeep } from 'lodash'; -import { CAVEAT_NAMES } from '../../../../shared/constants/permissions' +import { CAVEAT_NAMES } from '../../../../shared/constants/permissions'; import { APPROVAL_TYPE, SAFE_METHODS, // methods that do not require any permissions to use @@ -17,13 +17,13 @@ import { HISTORY_STORE_KEY, NOTIFICATION_NAMES, CAVEAT_TYPES, -} from './enums' +} from './enums'; -import createPermissionsMethodMiddleware from './permissionsMethodMiddleware' -import PermissionsLogController from './permissionsLog' +import createPermissionsMethodMiddleware from './permissionsMethodMiddleware'; +import PermissionsLogController from './permissionsLog'; // instanbul ignore next -const noop = () => undefined +const noop = () => undefined; export class PermissionsController { constructor( @@ -44,56 +44,56 @@ export class PermissionsController { this.store = new ObservableStore({ [LOG_STORE_KEY]: restoredState[LOG_STORE_KEY] || [], [HISTORY_STORE_KEY]: restoredState[HISTORY_STORE_KEY] || {}, - }) + }); - this.getKeyringAccounts = getKeyringAccounts - this._getUnlockPromise = getUnlockPromise - this._notifyDomain = notifyDomain - this._notifyAllDomains = notifyAllDomains - this._isUnlocked = isUnlocked + this.getKeyringAccounts = getKeyringAccounts; + this._getUnlockPromise = getUnlockPromise; + this._notifyDomain = notifyDomain; + this._notifyAllDomains = notifyAllDomains; + this._isUnlocked = isUnlocked; this._restrictedMethods = getRestrictedMethods({ getKeyringAccounts: this.getKeyringAccounts.bind(this), getIdentities: this._getIdentities.bind(this), - }) + }); this.permissionsLog = new PermissionsLogController({ restrictedMethods: Object.keys(this._restrictedMethods), store: this.store, - }) + }); /** * @type {import('@metamask/controllers').ApprovalController} * @public */ - this.approvals = approvals - this._initializePermissions(restoredPermissions) - this._lastSelectedAddress = preferences.getState().selectedAddress - this.preferences = preferences + this.approvals = approvals; + this._initializePermissions(restoredPermissions); + this._lastSelectedAddress = preferences.getState().selectedAddress; + this.preferences = preferences; - this._initializeMetadataStore(restoredState) + this._initializeMetadataStore(restoredState); preferences.subscribe(async ({ selectedAddress }) => { if (selectedAddress && selectedAddress !== this._lastSelectedAddress) { - this._lastSelectedAddress = selectedAddress - await this._handleAccountSelected(selectedAddress) + this._lastSelectedAddress = selectedAddress; + await this._handleAccountSelected(selectedAddress); } - }) + }); } createMiddleware({ origin, extensionId }) { if (typeof origin !== 'string' || !origin.length) { - throw new Error('Must provide non-empty string origin.') + throw new Error('Must provide non-empty string origin.'); } - const metadataState = this.store.getState()[METADATA_STORE_KEY] + const metadataState = this.store.getState()[METADATA_STORE_KEY]; if (extensionId && metadataState[origin]?.extensionId !== extensionId) { - this.addDomainMetadata(origin, { extensionId }) + this.addDomainMetadata(origin, { extensionId }); } - const engine = new JsonRpcEngine() + const engine = new JsonRpcEngine(); - engine.push(this.permissionsLog.createMiddleware()) + engine.push(this.permissionsLog.createMiddleware()); engine.push( createPermissionsMethodMiddleware({ @@ -108,15 +108,15 @@ export class PermissionsController { { eth_accounts: {} }, ), }), - ) + ); engine.push( this.permissions.providerMiddlewareFunction.bind(this.permissions, { origin, }), - ) + ); - return engine.asMiddleware() + return engine.asMiddleware(); } /** @@ -125,9 +125,9 @@ export class PermissionsController { * @returns {Promise} The permissions request ID */ async requestAccountsPermissionWithId(origin) { - const id = nanoid() - this._requestPermissions({ origin }, { eth_accounts: {} }, id) - return id + const id = nanoid(); + this._requestPermissions({ origin }, { eth_accounts: {} }, id); + return id; } /** @@ -139,24 +139,24 @@ export class PermissionsController { */ getAccounts(origin) { return new Promise((resolve, _) => { - const req = { method: 'eth_accounts' } - const res = {} + const req = { method: 'eth_accounts' }; + const res = {}; this.permissions.providerMiddlewareFunction( { origin }, req, res, noop, _end, - ) + ); function _end() { if (res.error || !Array.isArray(res.result)) { - resolve([]) + resolve([]); } else { - resolve(res.result) + resolve(res.result); } } - }) + }); } /** @@ -167,7 +167,7 @@ export class PermissionsController { * @returns {boolean} Whether the origin has the permission. */ hasPermission(origin, permission) { - return Boolean(this.permissions.getPermission(origin, permission)) + return Boolean(this.permissions.getPermission(origin, permission)); } /** @@ -176,7 +176,7 @@ export class PermissionsController { * @returns {Object} identities */ _getIdentities() { - return this.preferences.getState().identities + return this.preferences.getState().identities; } /** @@ -196,20 +196,20 @@ export class PermissionsController { id, method: 'wallet_requestPermissions', params: [permissions], - } - const res = {} + }; + const res = {}; - this.permissions.providerMiddlewareFunction(domain, req, res, noop, _end) + this.permissions.providerMiddlewareFunction(domain, req, res, noop, _end); function _end(_err) { - const err = _err || res.error + const err = _err || res.error; if (err) { - reject(err) + reject(err); } else { - resolve(res.result) + resolve(res.result); } } - }) + }); } /** @@ -222,11 +222,11 @@ export class PermissionsController { * @param {Array} accounts - The accounts to expose, if any */ async approvePermissionsRequest(approved, accounts) { - const { id } = approved.metadata + const { id } = approved.metadata; if (!this.approvals.has({ id })) { - log.debug(`Permissions request with id '${id}' not found.`) - return + log.debug(`Permissions request with id '${id}' not found.`); + return; } try { @@ -236,15 +236,15 @@ export class PermissionsController { ethErrors.rpc.invalidRequest({ message: 'Must request at least one permission.', }), - ) + ); } else { // attempt to finalize the request and resolve it, // settings caveats as necessary approved.permissions = await this.finalizePermissionsRequest( approved.permissions, accounts, - ) - this.approvals.resolve(id, approved.permissions) + ); + this.approvals.resolve(id, approved.permissions); } } catch (err) { // if finalization fails, reject the request @@ -254,7 +254,7 @@ export class PermissionsController { message: err.message, data: err, }), - ) + ); } } @@ -267,11 +267,11 @@ export class PermissionsController { */ async rejectPermissionsRequest(id) { if (!this.approvals.has({ id })) { - log.debug(`Permissions request with id '${id}' not found.`) - return + log.debug(`Permissions request with id '${id}' not found.`); + return; } - this.approvals.reject(id, ethErrors.provider.userRejectedRequest()) + this.approvals.reject(id, ethErrors.provider.userRejectedRequest()); } /** @@ -284,18 +284,18 @@ export class PermissionsController { * @param {string} account - The new account to expose. */ async addPermittedAccount(origin, account) { - const domains = this.permissions.getDomains() + const domains = this.permissions.getDomains(); if (!domains[origin]) { - throw new Error('Unrecognized domain') + throw new Error('Unrecognized domain'); } - this.validatePermittedAccounts([account]) + this.validatePermittedAccounts([account]); - const oldPermittedAccounts = this._getPermittedAccounts(origin) + const oldPermittedAccounts = this._getPermittedAccounts(origin); if (!oldPermittedAccounts) { - throw new Error(`Origin does not have 'eth_accounts' permission`) + throw new Error(`Origin does not have 'eth_accounts' permission`); } else if (oldPermittedAccounts.includes(account)) { - throw new Error('Account is already permitted for origin') + throw new Error('Account is already permitted for origin'); } this.permissions.updateCaveatFor( @@ -303,11 +303,11 @@ export class PermissionsController { 'eth_accounts', CAVEAT_NAMES.exposedAccounts, [...oldPermittedAccounts, account], - ) + ); - const permittedAccounts = await this.getAccounts(origin) + const permittedAccounts = await this.getAccounts(origin); - this.notifyAccountsChanged(origin, permittedAccounts) + this.notifyAccountsChanged(origin, permittedAccounts); } /** @@ -322,38 +322,38 @@ export class PermissionsController { * @param {string} account - The account to remove. */ async removePermittedAccount(origin, account) { - const domains = this.permissions.getDomains() + const domains = this.permissions.getDomains(); if (!domains[origin]) { - throw new Error('Unrecognized domain') + throw new Error('Unrecognized domain'); } - this.validatePermittedAccounts([account]) + this.validatePermittedAccounts([account]); - const oldPermittedAccounts = this._getPermittedAccounts(origin) + const oldPermittedAccounts = this._getPermittedAccounts(origin); if (!oldPermittedAccounts) { - throw new Error(`Origin does not have 'eth_accounts' permission`) + throw new Error(`Origin does not have 'eth_accounts' permission`); } else if (!oldPermittedAccounts.includes(account)) { - throw new Error('Account is not permitted for origin') + throw new Error('Account is not permitted for origin'); } let newPermittedAccounts = oldPermittedAccounts.filter( (acc) => acc !== account, - ) + ); if (newPermittedAccounts.length === 0) { - this.removePermissionsFor({ [origin]: ['eth_accounts'] }) + this.removePermissionsFor({ [origin]: ['eth_accounts'] }); } else { this.permissions.updateCaveatFor( origin, 'eth_accounts', CAVEAT_NAMES.exposedAccounts, newPermittedAccounts, - ) + ); - newPermittedAccounts = await this.getAccounts(origin) + newPermittedAccounts = await this.getAccounts(origin); } - this.notifyAccountsChanged(origin, newPermittedAccounts) + this.notifyAccountsChanged(origin, newPermittedAccounts); } /** @@ -365,18 +365,18 @@ export class PermissionsController { * @param {string} account - The account to remove. */ async removeAllAccountPermissions(account) { - this.validatePermittedAccounts([account]) + this.validatePermittedAccounts([account]); - const domains = this.permissions.getDomains() + const domains = this.permissions.getDomains(); const connectedOrigins = Object.keys(domains).filter((origin) => this._getPermittedAccounts(origin).includes(account), - ) + ); await Promise.all( connectedOrigins.map((origin) => this.removePermittedAccount(origin, account), ), - ) + ); } /** @@ -390,16 +390,16 @@ export class PermissionsController { * @returns {Object} The finalized permissions request object. */ async finalizePermissionsRequest(requestedPermissions, requestedAccounts) { - const finalizedPermissions = cloneDeep(requestedPermissions) - const finalizedAccounts = cloneDeep(requestedAccounts) + const finalizedPermissions = cloneDeep(requestedPermissions); + const finalizedAccounts = cloneDeep(requestedAccounts); - const { eth_accounts: ethAccounts } = finalizedPermissions + const { eth_accounts: ethAccounts } = finalizedPermissions; if (ethAccounts) { - this.validatePermittedAccounts(finalizedAccounts) + this.validatePermittedAccounts(finalizedAccounts); if (!ethAccounts.caveats) { - ethAccounts.caveats = [] + ethAccounts.caveats = []; } // caveat names are unique, and we will only construct this caveat here @@ -407,22 +407,22 @@ export class PermissionsController { (c) => c.name !== CAVEAT_NAMES.exposedAccounts && c.name !== CAVEAT_NAMES.primaryAccountOnly, - ) + ); ethAccounts.caveats.push({ type: CAVEAT_TYPES.limitResponseLength, value: 1, name: CAVEAT_NAMES.primaryAccountOnly, - }) + }); ethAccounts.caveats.push({ type: CAVEAT_TYPES.filterResponse, value: finalizedAccounts, name: CAVEAT_NAMES.exposedAccounts, - }) + }); } - return finalizedPermissions + return finalizedPermissions; } /** @@ -433,16 +433,16 @@ export class PermissionsController { */ validatePermittedAccounts(accounts) { if (!Array.isArray(accounts) || accounts.length === 0) { - throw new Error('Must provide non-empty array of account(s).') + throw new Error('Must provide non-empty array of account(s).'); } // assert accounts exist - const allIdentities = this._getIdentities() + const allIdentities = this._getIdentities(); accounts.forEach((acc) => { if (!allIdentities[acc]) { - throw new Error(`Unknown account: ${acc}`) + throw new Error(`Unknown account: ${acc}`); } - }) + }); } /** @@ -454,11 +454,11 @@ export class PermissionsController { */ notifyAccountsChanged(origin, newAccounts) { if (typeof origin !== 'string' || !origin) { - throw new Error(`Invalid origin: '${origin}'`) + throw new Error(`Invalid origin: '${origin}'`); } if (!Array.isArray(newAccounts)) { - throw new Error('Invalid accounts', newAccounts) + throw new Error('Invalid accounts', newAccounts); } // We do not share accounts when the extension is locked. @@ -466,8 +466,8 @@ export class PermissionsController { this._notifyDomain(origin, { method: NOTIFICATION_NAMES.accountsChanged, params: newAccounts, - }) - this.permissionsLog.updateAccountsHistory(origin, newAccounts) + }); + this.permissionsLog.updateAccountsHistory(origin, newAccounts); } // NOTE: @@ -491,26 +491,26 @@ export class PermissionsController { origin, perms.map((methodName) => { if (methodName === 'eth_accounts') { - this.notifyAccountsChanged(origin, []) + this.notifyAccountsChanged(origin, []); } - return { parentCapability: methodName } + return { parentCapability: methodName }; }), - ) - }) + ); + }); } /** * Removes all known domains and their related permissions. */ clearPermissions() { - this.permissions.clearDomains() + this.permissions.clearDomains(); // It's safe to notify that no accounts are available, regardless of // extension lock state this._notifyAllDomains({ method: NOTIFICATION_NAMES.accountsChanged, params: [], - }) + }); } /** @@ -524,18 +524,18 @@ export class PermissionsController { * @param {Object} metadata - The domain's metadata that will be stored. */ addDomainMetadata(origin, metadata) { - const oldMetadataState = this.store.getState()[METADATA_STORE_KEY] - const newMetadataState = { ...oldMetadataState } + const oldMetadataState = this.store.getState()[METADATA_STORE_KEY]; + const newMetadataState = { ...oldMetadataState }; // delete pending metadata origin from queue, and delete its metadata if // it doesn't have any permissions if (this._pendingSiteMetadata.size >= METADATA_CACHE_MAX_SIZE) { - const permissionsDomains = this.permissions.getDomains() + const permissionsDomains = this.permissions.getDomains(); - const oldOrigin = this._pendingSiteMetadata.values().next().value - this._pendingSiteMetadata.delete(oldOrigin) + const oldOrigin = this._pendingSiteMetadata.values().next().value; + this._pendingSiteMetadata.delete(oldOrigin); if (!permissionsDomains[oldOrigin]) { - delete newMetadataState[oldOrigin] + delete newMetadataState[oldOrigin]; } } @@ -544,17 +544,17 @@ export class PermissionsController { ...oldMetadataState[origin], ...metadata, lastUpdated: Date.now(), - } + }; if ( !newMetadataState[origin].extensionId && !newMetadataState[origin].host ) { - newMetadataState[origin].host = new URL(origin).host + newMetadataState[origin].host = new URL(origin).host; } - this._pendingSiteMetadata.add(origin) - this._setDomainMetadata(newMetadataState) + this._pendingSiteMetadata.add(origin); + this._setDomainMetadata(newMetadataState); } /** @@ -566,11 +566,11 @@ export class PermissionsController { * @param {Object} restoredState - The restored permissions controller state. */ _initializeMetadataStore(restoredState) { - const metadataState = restoredState[METADATA_STORE_KEY] || {} - const newMetadataState = this._trimDomainMetadata(metadataState) + const metadataState = restoredState[METADATA_STORE_KEY] || {}; + const newMetadataState = this._trimDomainMetadata(metadataState); - this._pendingSiteMetadata = new Set() - this._setDomainMetadata(newMetadataState) + this._pendingSiteMetadata = new Set(); + this._setDomainMetadata(newMetadataState); } /** @@ -582,17 +582,17 @@ export class PermissionsController { * @returns {Object} The new metadata state object. */ _trimDomainMetadata(metadataState) { - const newMetadataState = { ...metadataState } - const origins = Object.keys(metadataState) - const permissionsDomains = this.permissions.getDomains() + const newMetadataState = { ...metadataState }; + const origins = Object.keys(metadataState); + const permissionsDomains = this.permissions.getDomains(); origins.forEach((origin) => { if (!permissionsDomains[origin]) { - delete newMetadataState[origin] + delete newMetadataState[origin]; } - }) + }); - return newMetadataState + return newMetadataState; } /** @@ -600,7 +600,7 @@ export class PermissionsController { * @param {Object} newMetadataState - The new metadata to set. */ _setDomainMetadata(newMetadataState) { - this.store.updateState({ [METADATA_STORE_KEY]: newMetadataState }) + this.store.updateState({ [METADATA_STORE_KEY]: newMetadataState }); } /** @@ -613,9 +613,9 @@ export class PermissionsController { const permittedAccounts = this.permissions .getPermission(origin, 'eth_accounts') ?.caveats?.find((caveat) => caveat.name === CAVEAT_NAMES.exposedAccounts) - ?.value + ?.value; - return permittedAccounts || null + return permittedAccounts || null; } /** @@ -629,27 +629,27 @@ export class PermissionsController { */ async _handleAccountSelected(account) { if (typeof account !== 'string') { - throw new Error('Selected account should be a non-empty string.') + throw new Error('Selected account should be a non-empty string.'); } - const domains = this.permissions.getDomains() || {} + const domains = this.permissions.getDomains() || {}; const connectedDomains = Object.entries(domains) .filter(([_, { permissions }]) => { const ethAccounts = permissions.find( (permission) => permission.parentCapability === 'eth_accounts', - ) + ); const exposedAccounts = ethAccounts?.caveats.find( (caveat) => caveat.name === 'exposedAccounts', - )?.value - return exposedAccounts?.includes(account) + )?.value; + return exposedAccounts?.includes(account); }) - .map(([domain]) => domain) + .map(([domain]) => domain); await Promise.all( connectedDomains.map((origin) => this._handleConnectedAccountSelected(origin), ), - ) + ); } /** @@ -661,9 +661,9 @@ export class PermissionsController { * @param {string} origin - The origin */ async _handleConnectedAccountSelected(origin) { - const permittedAccounts = await this.getAccounts(origin) + const permittedAccounts = await this.getAccounts(origin); - this.notifyAccountsChanged(origin, permittedAccounts) + this.notifyAccountsChanged(origin, permittedAccounts); } /** @@ -674,7 +674,7 @@ export class PermissionsController { */ _initializePermissions(restoredState) { // these permission requests are almost certainly stale - const initState = { ...restoredState, permissionsRequests: [] } + const initState = { ...restoredState, permissionsRequests: [] }; this.permissions = new RpcCap( { @@ -698,16 +698,16 @@ export class PermissionsController { requestUserApproval: async (req) => { const { metadata: { id, origin }, - } = req + } = req; return this.approvals.addAndShowApprovalRequest({ id, origin, type: APPROVAL_TYPE, - }) + }); }, }, initState, - ) + ); } } diff --git a/app/scripts/controllers/permissions/permissionsLog.js b/app/scripts/controllers/permissions/permissionsLog.js index 28c87af6b..d0ab55d23 100644 --- a/app/scripts/controllers/permissions/permissionsLog.js +++ b/app/scripts/controllers/permissions/permissionsLog.js @@ -1,5 +1,5 @@ -import { cloneDeep } from 'lodash' -import { CAVEAT_NAMES } from '../../../../shared/constants/permissions' +import { cloneDeep } from 'lodash'; +import { CAVEAT_NAMES } from '../../../../shared/constants/permissions'; import { HISTORY_STORE_KEY, LOG_IGNORE_METHODS, @@ -7,7 +7,7 @@ import { LOG_METHOD_TYPES, LOG_STORE_KEY, WALLET_PREFIX, -} from './enums' +} from './enums'; /** * Controller with middleware for logging requests and responses to restricted @@ -15,8 +15,8 @@ import { */ export default class PermissionsLogController { constructor({ restrictedMethods, store }) { - this.restrictedMethods = restrictedMethods - this.store = store + this.restrictedMethods = restrictedMethods; + this.store = store; } /** @@ -25,7 +25,7 @@ export default class PermissionsLogController { * @returns {Array} The activity log. */ getActivityLog() { - return this.store.getState()[LOG_STORE_KEY] || [] + return this.store.getState()[LOG_STORE_KEY] || []; } /** @@ -34,7 +34,7 @@ export default class PermissionsLogController { * @param {Array} logs - The new activity log array. */ updateActivityLog(logs) { - this.store.updateState({ [LOG_STORE_KEY]: logs }) + this.store.updateState({ [LOG_STORE_KEY]: logs }); } /** @@ -43,7 +43,7 @@ export default class PermissionsLogController { * @returns {Object} The permissions history log. */ getHistory() { - return this.store.getState()[HISTORY_STORE_KEY] || {} + return this.store.getState()[HISTORY_STORE_KEY] || {}; } /** @@ -52,7 +52,7 @@ export default class PermissionsLogController { * @param {Object} history - The new permissions history log object. */ updateHistory(history) { - this.store.updateState({ [HISTORY_STORE_KEY]: history }) + this.store.updateState({ [HISTORY_STORE_KEY]: history }); } /** @@ -65,16 +65,16 @@ export default class PermissionsLogController { */ updateAccountsHistory(origin, accounts) { if (accounts.length === 0) { - return + return; } - const accountToTimeMap = getAccountToTimeMap(accounts, Date.now()) + const accountToTimeMap = getAccountToTimeMap(accounts, Date.now()); this.commitNewHistory(origin, { eth_accounts: { accounts: accountToTimeMap, }, - }) + }); } /** @@ -89,37 +89,37 @@ export default class PermissionsLogController { */ createMiddleware() { return (req, res, next, _end) => { - let activityEntry, requestedMethods - const { origin, method } = req - const isInternal = method.startsWith(WALLET_PREFIX) + let activityEntry, requestedMethods; + const { origin, method } = req; + const isInternal = method.startsWith(WALLET_PREFIX); // we only log certain methods if ( !LOG_IGNORE_METHODS.includes(method) && (isInternal || this.restrictedMethods.includes(method)) ) { - activityEntry = this.logRequest(req, isInternal) + activityEntry = this.logRequest(req, isInternal); if (method === `${WALLET_PREFIX}requestPermissions`) { // get the corresponding methods from the requested permissions so // that we can record permissions history - requestedMethods = this.getRequestedMethods(req) + requestedMethods = this.getRequestedMethods(req); } } else if (method === 'eth_requestAccounts') { // eth_requestAccounts is a special case; we need to extract the accounts // from it - activityEntry = this.logRequest(req, isInternal) - requestedMethods = ['eth_accounts'] + activityEntry = this.logRequest(req, isInternal); + requestedMethods = ['eth_accounts']; } else { // no-op - next() - return + next(); + return; } // call next with a return handler for capturing the response next((cb) => { - const time = Date.now() - this.logResponse(activityEntry, res, time) + const time = Date.now(); + this.logResponse(activityEntry, res, time); if (requestedMethods && !res.error && res.result) { // any permissions or accounts changes will be recorded on the response, @@ -130,11 +130,11 @@ export default class PermissionsLogController { res.result, time, method === 'eth_requestAccounts', - ) + ); } - cb() - }) - } + cb(); + }); + }; } /** @@ -156,9 +156,9 @@ export default class PermissionsLogController { response: null, responseTime: null, success: null, - } - this.commitNewActivity(activityEntry) - return activityEntry + }; + this.commitNewActivity(activityEntry); + return activityEntry; } /** @@ -171,12 +171,12 @@ export default class PermissionsLogController { */ logResponse(entry, response, time) { if (!entry || !response) { - return + return; } - entry.response = cloneDeep(response) - entry.responseTime = time - entry.success = !response.error + entry.response = cloneDeep(response); + entry.responseTime = time; + entry.success = !response.error; } /** @@ -186,17 +186,17 @@ export default class PermissionsLogController { * @param {Object} entry - The activity log entry. */ commitNewActivity(entry) { - const logs = this.getActivityLog() + const logs = this.getActivityLog(); // add new entry to end of log - logs.push(entry) + logs.push(entry); // remove oldest log if exceeding size limit if (logs.length > LOG_LIMIT) { - logs.shift() + logs.shift(); } - this.updateActivityLog(logs) + this.updateActivityLog(logs); } /** @@ -215,18 +215,18 @@ export default class PermissionsLogController { time, isEthRequestAccounts, ) { - let accounts, newEntries + let accounts, newEntries; if (isEthRequestAccounts) { - accounts = result - const accountToTimeMap = getAccountToTimeMap(accounts, time) + accounts = result; + const accountToTimeMap = getAccountToTimeMap(accounts, time); newEntries = { eth_accounts: { accounts: accountToTimeMap, lastApproved: time, }, - } + }; } else { // Records new "lastApproved" times for the granted permissions, if any. // Special handling for eth_accounts, in order to record the time the @@ -234,33 +234,33 @@ export default class PermissionsLogController { newEntries = result .map((perm) => { if (perm.parentCapability === 'eth_accounts') { - accounts = this.getAccountsFromPermission(perm) + accounts = this.getAccountsFromPermission(perm); } - return perm.parentCapability + return perm.parentCapability; }) .reduce((acc, method) => { // all approved permissions will be included in the response, // not just the newly requested ones if (requestedMethods.includes(method)) { if (method === 'eth_accounts') { - const accountToTimeMap = getAccountToTimeMap(accounts, time) + const accountToTimeMap = getAccountToTimeMap(accounts, time); acc[method] = { lastApproved: time, accounts: accountToTimeMap, - } + }; } else { - acc[method] = { lastApproved: time } + acc[method] = { lastApproved: time }; } } - return acc - }, {}) + return acc; + }, {}); } if (Object.keys(newEntries).length > 0) { - this.commitNewHistory(origin, newEntries) + this.commitNewHistory(origin, newEntries); } } @@ -274,24 +274,24 @@ export default class PermissionsLogController { */ commitNewHistory(origin, newEntries) { // a simple merge updates most permissions - const history = this.getHistory() + const history = this.getHistory(); const newOriginHistory = { ...history[origin], ...newEntries, - } + }; // eth_accounts requires special handling, because of information // we store about the accounts const existingEthAccountsEntry = - history[origin] && history[origin].eth_accounts - const newEthAccountsEntry = newEntries.eth_accounts + history[origin] && history[origin].eth_accounts; + const newEthAccountsEntry = newEntries.eth_accounts; if (existingEthAccountsEntry && newEthAccountsEntry) { // we may intend to update just the accounts, not the permission // itself const lastApproved = newEthAccountsEntry.lastApproved || - existingEthAccountsEntry.lastApproved + existingEthAccountsEntry.lastApproved; // merge old and new eth_accounts history entries newOriginHistory.eth_accounts = { @@ -300,12 +300,12 @@ export default class PermissionsLogController { ...existingEthAccountsEntry.accounts, ...newEthAccountsEntry.accounts, }, - } + }; } - history[origin] = newOriginHistory + history[origin] = newOriginHistory; - this.updateHistory(history) + this.updateHistory(history); } /** @@ -321,9 +321,9 @@ export default class PermissionsLogController { typeof request.params[0] !== 'object' || Array.isArray(request.params[0]) ) { - return null + return null; } - return Object.keys(request.params[0]) + return Object.keys(request.params[0]); } /** @@ -335,21 +335,21 @@ export default class PermissionsLogController { */ getAccountsFromPermission(perm) { if (perm.parentCapability !== 'eth_accounts' || !perm.caveats) { - return [] + return []; } - const accounts = new Set() + const accounts = new Set(); for (const caveat of perm.caveats) { if ( caveat.name === CAVEAT_NAMES.exposedAccounts && Array.isArray(caveat.value) ) { for (const value of caveat.value) { - accounts.add(value) + accounts.add(value); } } } - return [...accounts] + return [...accounts]; } } @@ -363,5 +363,5 @@ export default class PermissionsLogController { * @returns {Object} A string:number map of addresses to time. */ function getAccountToTimeMap(accounts, time) { - return accounts.reduce((acc, account) => ({ ...acc, [account]: time }), {}) + return accounts.reduce((acc, account) => ({ ...acc, [account]: time }), {}); } diff --git a/app/scripts/controllers/permissions/permissionsMethodMiddleware.js b/app/scripts/controllers/permissions/permissionsMethodMiddleware.js index a4bac3976..10e5e1fa0 100644 --- a/app/scripts/controllers/permissions/permissionsMethodMiddleware.js +++ b/app/scripts/controllers/permissions/permissionsMethodMiddleware.js @@ -1,5 +1,5 @@ -import { createAsyncMiddleware } from 'json-rpc-engine' -import { ethErrors } from 'eth-rpc-errors' +import { createAsyncMiddleware } from 'json-rpc-engine'; +import { ethErrors } from 'eth-rpc-errors'; /** * Create middleware for handling certain methods and preprocessing permissions requests. @@ -12,73 +12,73 @@ export default function createPermissionsMethodMiddleware({ notifyAccountsChanged, requestAccountsPermission, }) { - let isProcessingRequestAccounts = false + let isProcessingRequestAccounts = false; return createAsyncMiddleware(async (req, res, next) => { - let responseHandler + let responseHandler; switch (req.method) { // Intercepting eth_accounts requests for backwards compatibility: // The getAccounts call below wraps the rpc-cap middleware, and returns // an empty array in case of errors (such as 4100:unauthorized) case 'eth_accounts': { - res.result = await getAccounts() - return + res.result = await getAccounts(); + return; } case 'eth_requestAccounts': { if (isProcessingRequestAccounts) { res.error = ethErrors.rpc.resourceUnavailable( 'Already processing eth_requestAccounts. Please wait.', - ) - return + ); + return; } if (hasPermission('eth_accounts')) { - isProcessingRequestAccounts = true - await getUnlockPromise() - isProcessingRequestAccounts = false + isProcessingRequestAccounts = true; + await getUnlockPromise(); + isProcessingRequestAccounts = false; } // first, just try to get accounts - let accounts = await getAccounts() + let accounts = await getAccounts(); if (accounts.length > 0) { - res.result = accounts - return + res.result = accounts; + return; } // if no accounts, request the accounts permission try { - await requestAccountsPermission() + await requestAccountsPermission(); } catch (err) { - res.error = err - return + res.error = err; + return; } // get the accounts again - accounts = await getAccounts() + accounts = await getAccounts(); /* istanbul ignore else: too hard to induce, see below comment */ if (accounts.length > 0) { - res.result = accounts + res.result = accounts; } else { // this should never happen, because it should be caught in the // above catch clause res.error = ethErrors.rpc.internal( 'Accounts unexpectedly unavailable. Please report this bug.', - ) + ); } - return + return; } // custom method for getting metadata from the requesting domain, // sent automatically by the inpage provider when it's initialized case 'metamask_sendDomainMetadata': { if (typeof req.params?.name === 'string') { - addDomainMetadata(req.origin, req.params) + addDomainMetadata(req.origin, req.params); } - res.result = true - return + res.result = true; + return; } // register return handler to send accountsChanged notification @@ -88,25 +88,25 @@ export default function createPermissionsMethodMiddleware({ if (Array.isArray(res.result)) { for (const permission of res.result) { if (permission.parentCapability === 'eth_accounts') { - notifyAccountsChanged(await getAccounts()) + notifyAccountsChanged(await getAccounts()); } } } - } + }; } - break + break; } default: - break + break; } // when this promise resolves, the response is on its way back // eslint-disable-next-line node/callback-return - await next() + await next(); if (responseHandler) { - responseHandler() + responseHandler(); } - }) + }); } diff --git a/app/scripts/controllers/permissions/restrictedMethods.js b/app/scripts/controllers/permissions/restrictedMethods.js index b8dd39c71..05e42cabc 100644 --- a/app/scripts/controllers/permissions/restrictedMethods.js +++ b/app/scripts/controllers/permissions/restrictedMethods.js @@ -6,35 +6,35 @@ export default function getRestrictedMethods({ eth_accounts: { method: async (_, res, __, end) => { try { - const accounts = await getKeyringAccounts() - const identities = getIdentities() + const accounts = await getKeyringAccounts(); + const identities = getIdentities(); res.result = accounts.sort((firstAddress, secondAddress) => { if (!identities[firstAddress]) { - throw new Error(`Missing identity for address ${firstAddress}`) + throw new Error(`Missing identity for address ${firstAddress}`); } else if (!identities[secondAddress]) { - throw new Error(`Missing identity for address ${secondAddress}`) + throw new Error(`Missing identity for address ${secondAddress}`); } else if ( identities[firstAddress].lastSelected === identities[secondAddress].lastSelected ) { - return 0 + return 0; } else if (identities[firstAddress].lastSelected === undefined) { - return 1 + return 1; } else if (identities[secondAddress].lastSelected === undefined) { - return -1 + return -1; } return ( identities[secondAddress].lastSelected - identities[firstAddress].lastSelected - ) - }) - end() + ); + }); + end(); } catch (err) { - res.error = err - end(err) + res.error = err; + end(err); } }, }, - } + }; } diff --git a/app/scripts/controllers/preferences.js b/app/scripts/controllers/preferences.js index 605400c4c..fc02a317f 100644 --- a/app/scripts/controllers/preferences.js +++ b/app/scripts/controllers/preferences.js @@ -1,13 +1,13 @@ -import { strict as assert } from 'assert' -import { ObservableStore } from '@metamask/obs-store' -import { ethErrors } from 'eth-rpc-errors' -import { normalize as normalizeAddress } from 'eth-sig-util' -import { isValidAddress } from 'ethereumjs-util' -import ethers from 'ethers' -import log from 'loglevel' -import { LISTED_CONTRACT_ADDRESSES } from '../../../shared/constants/tokens' -import { NETWORK_TYPE_TO_ID_MAP } from '../../../shared/constants/network' -import { isPrefixedFormattedHexString } from '../../../shared/modules/utils' +import { strict as assert } from 'assert'; +import { ObservableStore } from '@metamask/obs-store'; +import { ethErrors } from 'eth-rpc-errors'; +import { normalize as normalizeAddress } from 'eth-sig-util'; +import { isValidAddress } from 'ethereumjs-util'; +import ethers from 'ethers'; +import log from 'loglevel'; +import { LISTED_CONTRACT_ADDRESSES } from '../../../shared/constants/tokens'; +import { NETWORK_TYPE_TO_ID_MAP } from '../../../shared/constants/network'; +import { isPrefixedFormattedHexString } from '../../../shared/modules/utils'; export default class PreferencesController { /** @@ -65,18 +65,18 @@ export default class PreferencesController { // ENS decentralized website resolution ipfsGateway: 'dweb.link', ...opts.initState, - } + }; - this.network = opts.network - this.store = new ObservableStore(initState) - this.store.setMaxListeners(12) - this.openPopup = opts.openPopup - this.migrateAddressBookState = opts.migrateAddressBookState - this._subscribeProviderType() + this.network = opts.network; + this.store = new ObservableStore(initState); + this.store.setMaxListeners(12); + this.openPopup = opts.openPopup; + this.migrateAddressBookState = opts.migrateAddressBookState; + this._subscribeProviderType(); global.setPreference = (key, value) => { - return this.setFeatureFlag(key, value) - } + return this.setFeatureFlag(key, value); + }; } // PUBLIC METHODS @@ -85,7 +85,7 @@ export default class PreferencesController { * @param {boolean} forgottenPassword - whether or not the user has forgotten their password */ setPasswordForgotten(forgottenPassword) { - this.store.updateState({ forgottenPassword }) + this.store.updateState({ forgottenPassword }); } /** @@ -95,7 +95,7 @@ export default class PreferencesController { * */ setUseBlockie(val) { - this.store.updateState({ useBlockie: val }) + this.store.updateState({ useBlockie: val }); } /** @@ -105,7 +105,7 @@ export default class PreferencesController { * */ setUseNonceField(val) { - this.store.updateState({ useNonceField: val }) + this.store.updateState({ useNonceField: val }); } /** @@ -115,7 +115,7 @@ export default class PreferencesController { * */ setUsePhishDetect(val) { - this.store.updateState({ usePhishDetect: val }) + this.store.updateState({ usePhishDetect: val }); } /** @@ -125,15 +125,15 @@ export default class PreferencesController { * */ setFirstTimeFlowType(type) { - this.store.updateState({ firstTimeFlowType: type }) + this.store.updateState({ firstTimeFlowType: type }); } getSuggestedTokens() { - return this.store.getState().suggestedTokens + return this.store.getState().suggestedTokens; } getAssetImages() { - return this.store.getState().assetImages + return this.store.getState().assetImages; } /** @@ -143,9 +143,9 @@ export default class PreferencesController { * @param {string} methodData - Corresponding data method */ addKnownMethodData(fourBytePrefix, methodData) { - const { knownMethodData } = this.store.getState() - knownMethodData[fourBytePrefix] = methodData - this.store.updateState({ knownMethodData }) + const { knownMethodData } = this.store.getState(); + knownMethodData[fourBytePrefix] = methodData; + this.store.updateState({ knownMethodData }); } /** @@ -154,15 +154,15 @@ export default class PreferencesController { * @param {Object} req - The watchAsset JSON-RPC request object. */ async requestWatchAsset(req) { - const { type, options } = req.params + const { type, options } = req.params; switch (type) { case 'ERC20': - return await this._handleWatchAssetERC20(options) + return await this._handleWatchAssetERC20(options); default: throw ethErrors.rpc.invalidParams( `Asset of type "${type}" not supported.`, - ) + ); } } @@ -175,12 +175,12 @@ export default class PreferencesController { setCurrentLocale(key) { const textDirection = ['ar', 'dv', 'fa', 'he', 'ku'].includes(key) ? 'rtl' - : 'auto' + : 'auto'; this.store.updateState({ currentLocale: key, textDirection, - }) - return textDirection + }); + return textDirection; } /** @@ -191,26 +191,26 @@ export default class PreferencesController { * */ setAddresses(addresses) { - const oldIdentities = this.store.getState().identities - const oldAccountTokens = this.store.getState().accountTokens - const oldAccountHiddenTokens = this.store.getState().accountHiddenTokens + const oldIdentities = this.store.getState().identities; + const oldAccountTokens = this.store.getState().accountTokens; + const oldAccountHiddenTokens = this.store.getState().accountHiddenTokens; const identities = addresses.reduce((ids, address, index) => { - const oldId = oldIdentities[address] || {} - ids[address] = { name: `Account ${index + 1}`, address, ...oldId } - return ids - }, {}) + const oldId = oldIdentities[address] || {}; + ids[address] = { name: `Account ${index + 1}`, address, ...oldId }; + return ids; + }, {}); const accountTokens = addresses.reduce((tokens, address) => { - const oldTokens = oldAccountTokens[address] || {} - tokens[address] = oldTokens - return tokens - }, {}) + const oldTokens = oldAccountTokens[address] || {}; + tokens[address] = oldTokens; + return tokens; + }, {}); const accountHiddenTokens = addresses.reduce((hiddenTokens, address) => { - const oldHiddenTokens = oldAccountHiddenTokens[address] || {} - hiddenTokens[address] = oldHiddenTokens - return hiddenTokens - }, {}) - this.store.updateState({ identities, accountTokens, accountHiddenTokens }) + const oldHiddenTokens = oldAccountHiddenTokens[address] || {}; + hiddenTokens[address] = oldHiddenTokens; + return hiddenTokens; + }, {}); + this.store.updateState({ identities, accountTokens, accountHiddenTokens }); } /** @@ -224,23 +224,23 @@ export default class PreferencesController { identities, accountTokens, accountHiddenTokens, - } = this.store.getState() + } = this.store.getState(); if (!identities[address]) { - throw new Error(`${address} can't be deleted cause it was not found`) + throw new Error(`${address} can't be deleted cause it was not found`); } - delete identities[address] - delete accountTokens[address] - delete accountHiddenTokens[address] - this.store.updateState({ identities, accountTokens, accountHiddenTokens }) + delete identities[address]; + delete accountTokens[address]; + delete accountHiddenTokens[address]; + this.store.updateState({ identities, accountTokens, accountHiddenTokens }); // If the selected account is no longer valid, // select an arbitrary other account: if (address === this.getSelectedAddress()) { - const selected = Object.keys(identities)[0] - this.setSelectedAddress(selected) + const selected = Object.keys(identities)[0]; + this.setSelectedAddress(selected); } - return address + return address; } /** @@ -254,20 +254,20 @@ export default class PreferencesController { identities, accountTokens, accountHiddenTokens, - } = this.store.getState() + } = this.store.getState(); addresses.forEach((address) => { // skip if already exists if (identities[address]) { - return + return; } // add missing identity - const identityCount = Object.keys(identities).length + const identityCount = Object.keys(identities).length; - accountTokens[address] = {} - accountHiddenTokens[address] = {} - identities[address] = { name: `Account ${identityCount + 1}`, address } - }) - this.store.updateState({ identities, accountTokens, accountHiddenTokens }) + accountTokens[address] = {}; + accountHiddenTokens[address] = {}; + identities[address] = { name: `Account ${identityCount + 1}`, address }; + }); + this.store.updateState({ identities, accountTokens, accountHiddenTokens }); } /** @@ -279,46 +279,46 @@ export default class PreferencesController { */ syncAddresses(addresses) { if (!Array.isArray(addresses) || addresses.length === 0) { - throw new Error('Expected non-empty array of addresses.') + throw new Error('Expected non-empty array of addresses.'); } - const { identities, lostIdentities } = this.store.getState() + const { identities, lostIdentities } = this.store.getState(); - const newlyLost = {} + const newlyLost = {}; Object.keys(identities).forEach((identity) => { if (!addresses.includes(identity)) { - newlyLost[identity] = identities[identity] - delete identities[identity] + newlyLost[identity] = identities[identity]; + delete identities[identity]; } - }) + }); // Identities are no longer present. if (Object.keys(newlyLost).length > 0) { // store lost accounts Object.keys(newlyLost).forEach((key) => { - lostIdentities[key] = newlyLost[key] - }) + lostIdentities[key] = newlyLost[key]; + }); } - this.store.updateState({ identities, lostIdentities }) - this.addAddresses(addresses) + this.store.updateState({ identities, lostIdentities }); + this.addAddresses(addresses); // If the selected account is no longer valid, // select an arbitrary other account: - let selected = this.getSelectedAddress() + let selected = this.getSelectedAddress(); if (!addresses.includes(selected)) { - selected = addresses[0] - this.setSelectedAddress(selected) + selected = addresses[0]; + this.setSelectedAddress(selected); } - return selected + return selected; } removeSuggestedTokens() { return new Promise((resolve) => { - this.store.updateState({ suggestedTokens: {} }) - resolve({}) - }) + this.store.updateState({ suggestedTokens: {} }); + resolve({}); + }); } /** @@ -329,18 +329,18 @@ export default class PreferencesController { * */ setSelectedAddress(_address) { - const address = normalizeAddress(_address) - this._updateTokens(address) + const address = normalizeAddress(_address); + this._updateTokens(address); - const { identities, tokens } = this.store.getState() - const selectedIdentity = identities[address] + const { identities, tokens } = this.store.getState(); + const selectedIdentity = identities[address]; if (!selectedIdentity) { - throw new Error(`Identity for '${address} not found`) + throw new Error(`Identity for '${address} not found`); } - selectedIdentity.lastSelected = Date.now() - this.store.updateState({ identities, selectedAddress: address }) - return Promise.resolve(tokens) + selectedIdentity.lastSelected = Date.now(); + this.store.updateState({ identities, selectedAddress: address }); + return Promise.resolve(tokens); } /** @@ -350,7 +350,7 @@ export default class PreferencesController { * */ getSelectedAddress() { - return this.store.getState().selectedAddress + return this.store.getState().selectedAddress; } /** @@ -375,26 +375,26 @@ export default class PreferencesController { * */ async addToken(rawAddress, symbol, decimals, image) { - const address = normalizeAddress(rawAddress) - const newEntry = { address, symbol, decimals } - const { tokens, hiddenTokens } = this.store.getState() - const assetImages = this.getAssetImages() + const address = normalizeAddress(rawAddress); + const newEntry = { address, symbol, decimals }; + const { tokens, hiddenTokens } = this.store.getState(); + const assetImages = this.getAssetImages(); const updatedHiddenTokens = hiddenTokens.filter( (tokenAddress) => tokenAddress !== rawAddress.toLowerCase(), - ) + ); const previousEntry = tokens.find((token) => { - return token.address === address - }) - const previousIndex = tokens.indexOf(previousEntry) + return token.address === address; + }); + const previousIndex = tokens.indexOf(previousEntry); if (previousEntry) { - tokens[previousIndex] = newEntry + tokens[previousIndex] = newEntry; } else { - tokens.push(newEntry) + tokens.push(newEntry); } - assetImages[address] = image - this._updateAccountTokens(tokens, assetImages, updatedHiddenTokens) - return Promise.resolve(tokens) + assetImages[address] = image; + this._updateAccountTokens(tokens, assetImages, updatedHiddenTokens); + return Promise.resolve(tokens); } /** @@ -405,13 +405,15 @@ export default class PreferencesController { * */ removeToken(rawAddress) { - const { tokens, hiddenTokens } = this.store.getState() - const assetImages = this.getAssetImages() - const updatedTokens = tokens.filter((token) => token.address !== rawAddress) - const updatedHiddenTokens = [...hiddenTokens, rawAddress.toLowerCase()] - delete assetImages[rawAddress] - this._updateAccountTokens(updatedTokens, assetImages, updatedHiddenTokens) - return Promise.resolve(updatedTokens) + const { tokens, hiddenTokens } = this.store.getState(); + const assetImages = this.getAssetImages(); + const updatedTokens = tokens.filter( + (token) => token.address !== rawAddress, + ); + const updatedHiddenTokens = [...hiddenTokens, rawAddress.toLowerCase()]; + delete assetImages[rawAddress]; + this._updateAccountTokens(updatedTokens, assetImages, updatedHiddenTokens); + return Promise.resolve(updatedTokens); } /** @@ -421,7 +423,7 @@ export default class PreferencesController { * */ getTokens() { - return this.store.getState().tokens + return this.store.getState().tokens; } /** @@ -434,14 +436,14 @@ export default class PreferencesController { if (!account) { throw new Error( `setAccountLabel requires a valid address, got ${String(account)}`, - ) + ); } - const address = normalizeAddress(account) - const { identities } = this.store.getState() - identities[address] = identities[address] || {} - identities[address].name = label - this.store.updateState({ identities }) - return Promise.resolve(label) + const address = normalizeAddress(account); + const { identities } = this.store.getState(); + identities[address] = identities[address] || {}; + identities[address].name = label; + this.store.updateState({ identities }); + return Promise.resolve(label); } /** @@ -456,33 +458,33 @@ export default class PreferencesController { * */ async updateRpc(newRpcDetails) { - const rpcList = this.getFrequentRpcListDetail() + const rpcList = this.getFrequentRpcListDetail(); const index = rpcList.findIndex((element) => { - return element.rpcUrl === newRpcDetails.rpcUrl - }) + return element.rpcUrl === newRpcDetails.rpcUrl; + }); if (index > -1) { - const rpcDetail = rpcList[index] - const updatedRpc = { ...rpcDetail, ...newRpcDetails } + const rpcDetail = rpcList[index]; + const updatedRpc = { ...rpcDetail, ...newRpcDetails }; if (rpcDetail.chainId !== updatedRpc.chainId) { // When the chainId is changed, associated address book entries should // also be migrated. The address book entries are keyed by the `network` state, // which for custom networks is the chainId with a fallback to the networkId // if the chainId is not set. - let addressBookKey = rpcDetail.chainId + let addressBookKey = rpcDetail.chainId; if (!addressBookKey) { // We need to find the networkId to determine what these addresses were keyed by const provider = new ethers.providers.JsonRpcProvider( rpcDetail.rpcUrl, - ) + ); try { - addressBookKey = await provider.send('net_version') - assert(typeof addressBookKey === 'string') + addressBookKey = await provider.send('net_version'); + assert(typeof addressBookKey === 'string'); } catch (error) { - log.debug(error) + log.debug(error); log.warn( `Failed to get networkId from ${rpcDetail.rpcUrl}; skipping address book migration`, - ) + ); } } @@ -490,31 +492,37 @@ export default class PreferencesController { // value. In this case, the contact book entries are duplicated so that they remain // on both networks, since we don't know which network each contact is intended for. - let duplicate = false + let duplicate = false; const builtInProviderNetworkIds = Object.values( NETWORK_TYPE_TO_ID_MAP, - ).map((ids) => ids.networkId) + ).map((ids) => ids.networkId); const otherRpcEntries = rpcList.filter( (entry) => entry.rpcUrl !== newRpcDetails.rpcUrl, - ) + ); if ( builtInProviderNetworkIds.includes(addressBookKey) || otherRpcEntries.some((entry) => entry.chainId === addressBookKey) ) { - duplicate = true + duplicate = true; } this.migrateAddressBookState( addressBookKey, updatedRpc.chainId, duplicate, - ) + ); } - rpcList[index] = updatedRpc - this.store.updateState({ frequentRpcListDetail: rpcList }) + rpcList[index] = updatedRpc; + this.store.updateState({ frequentRpcListDetail: rpcList }); } else { - const { rpcUrl, chainId, ticker, nickname, rpcPrefs = {} } = newRpcDetails - this.addToFrequentRpcList(rpcUrl, chainId, ticker, nickname, rpcPrefs) + const { + rpcUrl, + chainId, + ticker, + nickname, + rpcPrefs = {}, + } = newRpcDetails; + this.addToFrequentRpcList(rpcUrl, chainId, ticker, nickname, rpcPrefs); } } @@ -535,21 +543,21 @@ export default class PreferencesController { nickname = '', rpcPrefs = {}, ) { - const rpcList = this.getFrequentRpcListDetail() + const rpcList = this.getFrequentRpcListDetail(); const index = rpcList.findIndex((element) => { - return element.rpcUrl === rpcUrl - }) + return element.rpcUrl === rpcUrl; + }); if (index !== -1) { - rpcList.splice(index, 1) + rpcList.splice(index, 1); } if (!isPrefixedFormattedHexString(chainId)) { - throw new Error(`Invalid chainId: "${chainId}"`) + throw new Error(`Invalid chainId: "${chainId}"`); } - rpcList.push({ rpcUrl, chainId, ticker, nickname, rpcPrefs }) - this.store.updateState({ frequentRpcListDetail: rpcList }) + rpcList.push({ rpcUrl, chainId, ticker, nickname, rpcPrefs }); + this.store.updateState({ frequentRpcListDetail: rpcList }); } /** @@ -560,15 +568,15 @@ export default class PreferencesController { * */ removeFromFrequentRpcList(url) { - const rpcList = this.getFrequentRpcListDetail() + const rpcList = this.getFrequentRpcListDetail(); const index = rpcList.findIndex((element) => { - return element.rpcUrl === url - }) + return element.rpcUrl === url; + }); if (index !== -1) { - rpcList.splice(index, 1) + rpcList.splice(index, 1); } - this.store.updateState({ frequentRpcListDetail: rpcList }) - return Promise.resolve(rpcList) + this.store.updateState({ frequentRpcListDetail: rpcList }); + return Promise.resolve(rpcList); } /** @@ -578,7 +586,7 @@ export default class PreferencesController { * */ getFrequentRpcListDetail() { - return this.store.getState().frequentRpcListDetail + return this.store.getState().frequentRpcListDetail; } /** @@ -590,15 +598,15 @@ export default class PreferencesController { * */ setFeatureFlag(feature, activated) { - const currentFeatureFlags = this.store.getState().featureFlags + const currentFeatureFlags = this.store.getState().featureFlags; const updatedFeatureFlags = { ...currentFeatureFlags, [feature]: activated, - } + }; - this.store.updateState({ featureFlags: updatedFeatureFlags }) + this.store.updateState({ featureFlags: updatedFeatureFlags }); - return Promise.resolve(updatedFeatureFlags) + return Promise.resolve(updatedFeatureFlags); } /** @@ -609,14 +617,14 @@ export default class PreferencesController { * @returns {Promise} Promises a new object; the updated preferences object. */ setPreference(preference, value) { - const currentPreferences = this.getPreferences() + const currentPreferences = this.getPreferences(); const updatedPreferences = { ...currentPreferences, [preference]: value, - } + }; - this.store.updateState({ preferences: updatedPreferences }) - return Promise.resolve(updatedPreferences) + this.store.updateState({ preferences: updatedPreferences }); + return Promise.resolve(updatedPreferences); } /** @@ -624,7 +632,7 @@ export default class PreferencesController { * @returns {Object} A key-boolean map of user-selected preferences. */ getPreferences() { - return this.store.getState().preferences + return this.store.getState().preferences; } /** @@ -632,8 +640,8 @@ export default class PreferencesController { * onboarding process. */ completeOnboarding() { - this.store.updateState({ completedOnboarding: true }) - return Promise.resolve(true) + this.store.updateState({ completedOnboarding: true }); + return Promise.resolve(true); } /** @@ -641,7 +649,7 @@ export default class PreferencesController { * @returns {string} The current IPFS gateway domain */ getIpfsGateway() { - return this.store.getState().ipfsGateway + return this.store.getState().ipfsGateway; } /** @@ -650,8 +658,8 @@ export default class PreferencesController { * @returns {Promise} A promise of the update IPFS gateway domain */ setIpfsGateway(domain) { - this.store.updateState({ ipfsGateway: domain }) - return Promise.resolve(domain) + this.store.updateState({ ipfsGateway: domain }); + return Promise.resolve(domain); } // @@ -665,9 +673,9 @@ export default class PreferencesController { */ _subscribeProviderType() { this.network.providerStore.subscribe(() => { - const { tokens, hiddenTokens } = this._getTokenRelatedStates() - this._updateAccountTokens(tokens, this.getAssetImages(), hiddenTokens) - }) + const { tokens, hiddenTokens } = this._getTokenRelatedStates(); + this._updateAccountTokens(tokens, this.getAssetImages(), hiddenTokens); + }); } /** @@ -684,16 +692,16 @@ export default class PreferencesController { providerType, selectedAddress, accountHiddenTokens, - } = this._getTokenRelatedStates() - accountTokens[selectedAddress][providerType] = tokens - accountHiddenTokens[selectedAddress][providerType] = hiddenTokens + } = this._getTokenRelatedStates(); + accountTokens[selectedAddress][providerType] = tokens; + accountHiddenTokens[selectedAddress][providerType] = hiddenTokens; this.store.updateState({ accountTokens, tokens, assetImages, accountHiddenTokens, hiddenTokens, - }) + }); } /** @@ -705,8 +713,8 @@ export default class PreferencesController { _updateTokens(selectedAddress) { const { tokens, hiddenTokens } = this._getTokenRelatedStates( selectedAddress, - ) - this.store.updateState({ tokens, hiddenTokens }) + ); + this.store.updateState({ tokens, hiddenTokens }); } /** @@ -717,26 +725,26 @@ export default class PreferencesController { * */ _getTokenRelatedStates(selectedAddress) { - const { accountTokens, accountHiddenTokens } = this.store.getState() + const { accountTokens, accountHiddenTokens } = this.store.getState(); if (!selectedAddress) { // eslint-disable-next-line no-param-reassign - selectedAddress = this.store.getState().selectedAddress + selectedAddress = this.store.getState().selectedAddress; } - const providerType = this.network.providerStore.getState().type + const providerType = this.network.providerStore.getState().type; if (!(selectedAddress in accountTokens)) { - accountTokens[selectedAddress] = {} + accountTokens[selectedAddress] = {}; } if (!(selectedAddress in accountHiddenTokens)) { - accountHiddenTokens[selectedAddress] = {} + accountHiddenTokens[selectedAddress] = {}; } if (!(providerType in accountTokens[selectedAddress])) { - accountTokens[selectedAddress][providerType] = [] + accountTokens[selectedAddress][providerType] = []; } if (!(providerType in accountHiddenTokens[selectedAddress])) { - accountHiddenTokens[selectedAddress][providerType] = [] + accountHiddenTokens[selectedAddress][providerType] = []; } - const tokens = accountTokens[selectedAddress][providerType] - const hiddenTokens = accountHiddenTokens[selectedAddress][providerType] + const tokens = accountTokens[selectedAddress][providerType]; + const hiddenTokens = accountHiddenTokens[selectedAddress][providerType]; return { tokens, accountTokens, @@ -744,7 +752,7 @@ export default class PreferencesController { accountHiddenTokens, providerType, selectedAddress, - } + }; } /** @@ -754,17 +762,17 @@ export default class PreferencesController { * */ async _handleWatchAssetERC20(tokenMetadata) { - this._validateERC20AssetParams(tokenMetadata) + this._validateERC20AssetParams(tokenMetadata); - const address = normalizeAddress(tokenMetadata.address) - const { symbol, decimals, image } = tokenMetadata - this._addSuggestedERC20Asset(address, symbol, decimals, image) + const address = normalizeAddress(tokenMetadata.address); + const { symbol, decimals, image } = tokenMetadata; + this._addSuggestedERC20Asset(address, symbol, decimals, image); - await this.openPopup() + await this.openPopup(); const tokenAddresses = this.getTokens().filter( (token) => token.address === address, - ) - return tokenAddresses.length > 0 + ); + return tokenAddresses.length > 0; } /** @@ -779,24 +787,24 @@ export default class PreferencesController { if (!address || !symbol || typeof decimals === 'undefined') { throw ethErrors.rpc.invalidParams( `Must specify address, symbol, and decimals.`, - ) + ); } if (typeof symbol !== 'string') { - throw ethErrors.rpc.invalidParams(`Invalid symbol: not a string.`) + throw ethErrors.rpc.invalidParams(`Invalid symbol: not a string.`); } if (!(symbol.length < 7)) { throw ethErrors.rpc.invalidParams( `Invalid symbol "${symbol}": longer than 6 characters.`, - ) + ); } - const numDecimals = parseInt(decimals, 10) + const numDecimals = parseInt(decimals, 10); if (isNaN(numDecimals) || numDecimals > 36 || numDecimals < 0) { throw ethErrors.rpc.invalidParams( `Invalid decimals "${decimals}": must be 0 <= 36.`, - ) + ); } if (!isValidAddress(address)) { - throw ethErrors.rpc.invalidParams(`Invalid address "${address}".`) + throw ethErrors.rpc.invalidParams(`Invalid address "${address}".`); } } @@ -807,9 +815,9 @@ export default class PreferencesController { decimals, image, unlisted: !LISTED_CONTRACT_ADDRESSES.includes(address), - } - const suggested = this.getSuggestedTokens() - suggested[address] = newEntry - this.store.updateState({ suggestedTokens: suggested }) + }; + const suggested = this.getSuggestedTokens(); + suggested[address] = newEntry; + this.store.updateState({ suggestedTokens: suggested }); } } diff --git a/app/scripts/controllers/swaps.js b/app/scripts/controllers/swaps.js index 0f599bb07..992af5578 100644 --- a/app/scripts/controllers/swaps.js +++ b/app/scripts/controllers/swaps.js @@ -1,54 +1,57 @@ -import { ethers } from 'ethers' -import log from 'loglevel' -import BigNumber from 'bignumber.js' -import { ObservableStore } from '@metamask/obs-store' -import { mapValues, cloneDeep } from 'lodash' -import abi from 'human-standard-token-abi' -import { calcTokenAmount } from '../../../ui/app/helpers/utils/token-util' -import { calcGasTotal } from '../../../ui/app/pages/send/send.utils' -import { conversionUtil } from '../../../ui/app/helpers/utils/conversion-util' +import { ethers } from 'ethers'; +import log from 'loglevel'; +import BigNumber from 'bignumber.js'; +import { ObservableStore } from '@metamask/obs-store'; +import { mapValues, cloneDeep } from 'lodash'; +import abi from 'human-standard-token-abi'; +import { calcTokenAmount } from '../../../ui/app/helpers/utils/token-util'; +import { calcGasTotal } from '../../../ui/app/pages/send/send.utils'; +import { conversionUtil } from '../../../ui/app/helpers/utils/conversion-util'; import { ETH_SWAPS_TOKEN_ADDRESS, DEFAULT_ERC20_APPROVE_GAS, QUOTES_EXPIRED_ERROR, QUOTES_NOT_AVAILABLE_ERROR, SWAPS_FETCH_ORDER_CONFLICT, -} from '../../../ui/app/helpers/constants/swaps' +} from '../../../ui/app/helpers/constants/swaps'; import { fetchTradesInfo as defaultFetchTradesInfo, fetchSwapsFeatureLiveness as defaultFetchSwapsFeatureLiveness, fetchSwapsQuoteRefreshTime as defaultFetchSwapsQuoteRefreshTime, -} from '../../../ui/app/pages/swaps/swaps.util' +} from '../../../ui/app/pages/swaps/swaps.util'; -const METASWAP_ADDRESS = '0x881d40237659c251811cec9c364ef91dc08d300c' +const METASWAP_ADDRESS = '0x881d40237659c251811cec9c364ef91dc08d300c'; // The MAX_GAS_LIMIT is a number that is higher than the maximum gas costs we have observed on any aggregator -const MAX_GAS_LIMIT = 2500000 +const MAX_GAS_LIMIT = 2500000; // To ensure that our serves are not spammed if MetaMask is left idle, we limit the number of fetches for quotes that are made on timed intervals. // 3 seems to be an appropriate balance of giving users the time they need when MetaMask is not left idle, and turning polling off when it is. -const POLL_COUNT_LIMIT = 3 +const POLL_COUNT_LIMIT = 3; // If for any reason the MetaSwap API fails to provide a refresh time, // provide a reasonable fallback to avoid further errors -const FALLBACK_QUOTE_REFRESH_TIME = 60000 +const FALLBACK_QUOTE_REFRESH_TIME = 60000; // This is the amount of time to wait, after successfully fetching quotes // and their gas estimates, before fetching for new quotes -const QUOTE_POLLING_DIFFERENCE_INTERVAL = 10 * 1000 +const QUOTE_POLLING_DIFFERENCE_INTERVAL = 10 * 1000; function calculateGasEstimateWithRefund( maxGas = MAX_GAS_LIMIT, estimatedRefund = 0, estimatedGas = 0, ) { - const maxGasMinusRefund = new BigNumber(maxGas, 10).minus(estimatedRefund, 10) + const maxGasMinusRefund = new BigNumber(maxGas, 10).minus( + estimatedRefund, + 10, + ); const gasEstimateWithRefund = maxGasMinusRefund.lt(estimatedGas, 16) ? maxGasMinusRefund.toString(16) - : estimatedGas + : estimatedGas; - return gasEstimateWithRefund + return gasEstimateWithRefund; } const initialState = { @@ -69,7 +72,7 @@ const initialState = { swapsFeatureIsLive: false, swapsQuoteRefreshTime: FALLBACK_QUOTE_REFRESH_TIME, }, -} +}; export default class SwapsController { constructor({ @@ -84,46 +87,46 @@ export default class SwapsController { }) { this.store = new ObservableStore({ swapsState: { ...initialState.swapsState }, - }) + }); - this._fetchTradesInfo = fetchTradesInfo - this._fetchSwapsFeatureLiveness = fetchSwapsFeatureLiveness - this._fetchSwapsQuoteRefreshTime = fetchSwapsQuoteRefreshTime + this._fetchTradesInfo = fetchTradesInfo; + this._fetchSwapsFeatureLiveness = fetchSwapsFeatureLiveness; + this._fetchSwapsQuoteRefreshTime = fetchSwapsQuoteRefreshTime; - this.getBufferedGasLimit = getBufferedGasLimit - this.tokenRatesStore = tokenRatesStore + this.getBufferedGasLimit = getBufferedGasLimit; + this.tokenRatesStore = tokenRatesStore; - this.pollCount = 0 - this.getProviderConfig = getProviderConfig + this.pollCount = 0; + this.getProviderConfig = getProviderConfig; - this.indexOfNewestCallInFlight = 0 + this.indexOfNewestCallInFlight = 0; - this.ethersProvider = new ethers.providers.Web3Provider(provider) - this._currentNetwork = networkController.store.getState().network + this.ethersProvider = new ethers.providers.Web3Provider(provider); + this._currentNetwork = networkController.store.getState().network; networkController.on('networkDidChange', (network) => { if (network !== 'loading' && network !== this._currentNetwork) { - this._currentNetwork = network - this.ethersProvider = new ethers.providers.Web3Provider(provider) + this._currentNetwork = network; + this.ethersProvider = new ethers.providers.Web3Provider(provider); } - }) + }); - this._setupSwapsLivenessFetching() + this._setupSwapsLivenessFetching(); } // Sets the refresh rate for quote updates from the MetaSwap API async _setSwapsQuoteRefreshTime() { // Default to fallback time unless API returns valid response - let swapsQuoteRefreshTime = FALLBACK_QUOTE_REFRESH_TIME + let swapsQuoteRefreshTime = FALLBACK_QUOTE_REFRESH_TIME; try { - swapsQuoteRefreshTime = await this._fetchSwapsQuoteRefreshTime() + swapsQuoteRefreshTime = await this._fetchSwapsQuoteRefreshTime(); } catch (e) { - console.error('Request for swaps quote refresh time failed: ', e) + console.error('Request for swaps quote refresh time failed: ', e); } - const { swapsState } = this.store.getState() + const { swapsState } = this.store.getState(); this.store.updateState({ swapsState: { ...swapsState, swapsQuoteRefreshTime }, - }) + }); } // Once quotes are fetched, we poll for new ones to keep the quotes up to date. Market and aggregator contract conditions can change fast enough @@ -133,20 +136,20 @@ export default class SwapsController { pollForNewQuotes() { const { swapsState: { swapsQuoteRefreshTime }, - } = this.store.getState() + } = this.store.getState(); this.pollingTimeout = setTimeout(() => { - const { swapsState } = this.store.getState() + const { swapsState } = this.store.getState(); this.fetchAndSetQuotes( swapsState.fetchParams, swapsState.fetchParams?.metaData, true, - ) - }, swapsQuoteRefreshTime - QUOTE_POLLING_DIFFERENCE_INTERVAL) + ); + }, swapsQuoteRefreshTime - QUOTE_POLLING_DIFFERENCE_INTERVAL); } stopPollingForQuotes() { - clearTimeout(this.pollingTimeout) + clearTimeout(this.pollingTimeout); } async fetchAndSetQuotes( @@ -155,37 +158,37 @@ export default class SwapsController { isPolledRequest, ) { if (!fetchParams) { - return null + return null; } // Every time we get a new request that is not from the polling, we reset the poll count so we can poll for up to three more sets of quotes with these new params. if (!isPolledRequest) { - this.pollCount = 0 + this.pollCount = 0; } // If there are any pending poll requests, clear them so that they don't get call while this new fetch is in process - clearTimeout(this.pollingTimeout) + clearTimeout(this.pollingTimeout); if (!isPolledRequest) { - this.setSwapsErrorKey('') + this.setSwapsErrorKey(''); } - const indexOfCurrentCall = this.indexOfNewestCallInFlight + 1 - this.indexOfNewestCallInFlight = indexOfCurrentCall + const indexOfCurrentCall = this.indexOfNewestCallInFlight + 1; + this.indexOfNewestCallInFlight = indexOfCurrentCall; let [newQuotes] = await Promise.all([ this._fetchTradesInfo(fetchParams), this._setSwapsQuoteRefreshTime(), - ]) + ]); newQuotes = mapValues(newQuotes, (quote) => ({ ...quote, sourceTokenInfo: fetchParamsMetaData.sourceTokenInfo, destinationTokenInfo: fetchParamsMetaData.destinationTokenInfo, - })) + })); - const quotesLastFetched = Date.now() + const quotesLastFetched = Date.now(); - let approvalRequired = false + let approvalRequired = false; if ( fetchParams.sourceToken !== ETH_SWAPS_TOKEN_ADDRESS && Object.values(newQuotes).length @@ -193,22 +196,22 @@ export default class SwapsController { const allowance = await this._getERC20Allowance( fetchParams.sourceToken, fetchParams.fromAddress, - ) + ); // For a user to be able to swap a token, they need to have approved the MetaSwap contract to withdraw that token. // _getERC20Allowance() returns the amount of the token they have approved for withdrawal. If that amount is greater // than 0, it means that approval has already occured and is not needed. Otherwise, for tokens to be swapped, a new // call of the ERC-20 approve method is required. - approvalRequired = allowance.eq(0) + approvalRequired = allowance.eq(0); if (!approvalRequired) { newQuotes = mapValues(newQuotes, (quote) => ({ ...quote, approvalNeeded: null, - })) + })); } else if (!isPolledRequest) { const { gasLimit: approvalGas } = await this.timedoutGasReturn( Object.values(newQuotes)[0].approvalNeeded, - ) + ); newQuotes = mapValues(newQuotes, (quote) => ({ ...quote, @@ -216,39 +219,39 @@ export default class SwapsController { ...quote.approvalNeeded, gas: approvalGas || DEFAULT_ERC20_APPROVE_GAS, }, - })) + })); } } - let topAggId = null + let topAggId = null; // We can reduce time on the loading screen by only doing this after the // loading screen and best quote have rendered. if (!approvalRequired && !fetchParams?.balanceError) { - newQuotes = await this.getAllQuotesWithGasEstimates(newQuotes) + newQuotes = await this.getAllQuotesWithGasEstimates(newQuotes); } if (Object.values(newQuotes).length === 0) { - this.setSwapsErrorKey(QUOTES_NOT_AVAILABLE_ERROR) + this.setSwapsErrorKey(QUOTES_NOT_AVAILABLE_ERROR); } else { const [ _topAggId, quotesWithSavingsAndFeeData, - ] = await this._findTopQuoteAndCalculateSavings(newQuotes) - topAggId = _topAggId - newQuotes = quotesWithSavingsAndFeeData + ] = await this._findTopQuoteAndCalculateSavings(newQuotes); + topAggId = _topAggId; + newQuotes = quotesWithSavingsAndFeeData; } // If a newer call has been made, don't update state with old information // Prevents timing conflicts between fetches if (this.indexOfNewestCallInFlight !== indexOfCurrentCall) { - throw new Error(SWAPS_FETCH_ORDER_CONFLICT) + throw new Error(SWAPS_FETCH_ORDER_CONFLICT); } - const { swapsState } = this.store.getState() - let { selectedAggId } = swapsState + const { swapsState } = this.store.getState(); + let { selectedAggId } = swapsState; if (!newQuotes[selectedAggId]) { - selectedAggId = null + selectedAggId = null; } this.store.updateState({ @@ -260,41 +263,41 @@ export default class SwapsController { selectedAggId, topAggId, }, - }) + }); // We only want to do up to a maximum of three requests from polling. - this.pollCount += 1 + this.pollCount += 1; if (this.pollCount < POLL_COUNT_LIMIT + 1) { - this.pollForNewQuotes() + this.pollForNewQuotes(); } else { - this.resetPostFetchState() - this.setSwapsErrorKey(QUOTES_EXPIRED_ERROR) - return null + this.resetPostFetchState(); + this.setSwapsErrorKey(QUOTES_EXPIRED_ERROR); + return null; } - return [newQuotes, topAggId] + return [newQuotes, topAggId]; } safeRefetchQuotes() { - const { swapsState } = this.store.getState() + const { swapsState } = this.store.getState(); if (!this.pollingTimeout && swapsState.fetchParams) { - this.fetchAndSetQuotes(swapsState.fetchParams) + this.fetchAndSetQuotes(swapsState.fetchParams); } } setSelectedQuoteAggId(selectedAggId) { - const { swapsState } = this.store.getState() - this.store.updateState({ swapsState: { ...swapsState, selectedAggId } }) + const { swapsState } = this.store.getState(); + this.store.updateState({ swapsState: { ...swapsState, selectedAggId } }); } setSwapsTokens(tokens) { - const { swapsState } = this.store.getState() - this.store.updateState({ swapsState: { ...swapsState, tokens } }) + const { swapsState } = this.store.getState(); + this.store.updateState({ swapsState: { ...swapsState, tokens } }); } setSwapsErrorKey(errorKey) { - const { swapsState } = this.store.getState() - this.store.updateState({ swapsState: { ...swapsState, errorKey } }) + const { swapsState } = this.store.getState(); + this.store.updateState({ swapsState: { ...swapsState, errorKey } }); } async getAllQuotesWithGasEstimates(quotes) { @@ -302,43 +305,43 @@ export default class SwapsController { Object.values(quotes).map(async (quote) => { const { gasLimit, simulationFails } = await this.timedoutGasReturn( quote.trade, - ) - return [gasLimit, simulationFails, quote.aggregator] + ); + return [gasLimit, simulationFails, quote.aggregator]; }), - ) + ); - const newQuotes = {} + const newQuotes = {}; quoteGasData.forEach(([gasLimit, simulationFails, aggId]) => { if (gasLimit && !simulationFails) { const gasEstimateWithRefund = calculateGasEstimateWithRefund( quotes[aggId].maxGas, quotes[aggId].estimatedRefund, gasLimit, - ) + ); newQuotes[aggId] = { ...quotes[aggId], gasEstimate: gasLimit, gasEstimateWithRefund, - } + }; } else if (quotes[aggId].approvalNeeded) { // If gas estimation fails, but an ERC-20 approve is needed, then we do not add any estimate property to the quote object // Such quotes will rely on the maxGas and averageGas properties from the api - newQuotes[aggId] = quotes[aggId] + newQuotes[aggId] = quotes[aggId]; } // If gas estimation fails and no approval is needed, then we filter that quote out, so that it is not shown to the user - }) - return newQuotes + }); + return newQuotes; } timedoutGasReturn(tradeTxParams) { return new Promise((resolve) => { - let gasTimedOut = false + let gasTimedOut = false; const gasTimeout = setTimeout(() => { - gasTimedOut = true - resolve({ gasLimit: null, simulationFails: true }) - }, 5000) + gasTimedOut = true; + resolve({ gasLimit: null, simulationFails: true }); + }, 5000); // Remove gas from params that will be passed to the `estimateGas` call // Including it can cause the estimate to fail if the actual gas needed @@ -348,44 +351,44 @@ export default class SwapsController { from: tradeTxParams.from, to: tradeTxParams.to, value: tradeTxParams.value, - } + }; this.getBufferedGasLimit({ txParams: tradeTxParamsForGasEstimate }, 1) .then(({ gasLimit, simulationFails }) => { if (!gasTimedOut) { - clearTimeout(gasTimeout) - resolve({ gasLimit, simulationFails }) + clearTimeout(gasTimeout); + resolve({ gasLimit, simulationFails }); } }) .catch((e) => { - log.error(e) + log.error(e); if (!gasTimedOut) { - clearTimeout(gasTimeout) - resolve({ gasLimit: null, simulationFails: true }) + clearTimeout(gasTimeout); + resolve({ gasLimit: null, simulationFails: true }); } - }) - }) + }); + }); } async setInitialGasEstimate(initialAggId) { - const { swapsState } = this.store.getState() + const { swapsState } = this.store.getState(); - const quoteToUpdate = { ...swapsState.quotes[initialAggId] } + const quoteToUpdate = { ...swapsState.quotes[initialAggId] }; const { gasLimit: newGasEstimate, simulationFails, - } = await this.timedoutGasReturn(quoteToUpdate.trade) + } = await this.timedoutGasReturn(quoteToUpdate.trade); if (newGasEstimate && !simulationFails) { const gasEstimateWithRefund = calculateGasEstimateWithRefund( quoteToUpdate.maxGas, quoteToUpdate.estimatedRefund, newGasEstimate, - ) + ); - quoteToUpdate.gasEstimate = newGasEstimate - quoteToUpdate.gasEstimateWithRefund = gasEstimateWithRefund + quoteToUpdate.gasEstimate = newGasEstimate; + quoteToUpdate.gasEstimateWithRefund = gasEstimateWithRefund; } this.store.updateState({ @@ -393,59 +396,61 @@ export default class SwapsController { ...swapsState, quotes: { ...swapsState.quotes, [initialAggId]: quoteToUpdate }, }, - }) + }); } setApproveTxId(approveTxId) { - const { swapsState } = this.store.getState() - this.store.updateState({ swapsState: { ...swapsState, approveTxId } }) + const { swapsState } = this.store.getState(); + this.store.updateState({ swapsState: { ...swapsState, approveTxId } }); } setTradeTxId(tradeTxId) { - const { swapsState } = this.store.getState() - this.store.updateState({ swapsState: { ...swapsState, tradeTxId } }) + const { swapsState } = this.store.getState(); + this.store.updateState({ swapsState: { ...swapsState, tradeTxId } }); } setQuotesLastFetched(quotesLastFetched) { - const { swapsState } = this.store.getState() - this.store.updateState({ swapsState: { ...swapsState, quotesLastFetched } }) + const { swapsState } = this.store.getState(); + this.store.updateState({ + swapsState: { ...swapsState, quotesLastFetched }, + }); } setSwapsTxGasPrice(gasPrice) { - const { swapsState } = this.store.getState() + const { swapsState } = this.store.getState(); this.store.updateState({ swapsState: { ...swapsState, customGasPrice: gasPrice }, - }) + }); } setSwapsTxGasLimit(gasLimit) { - const { swapsState } = this.store.getState() + const { swapsState } = this.store.getState(); this.store.updateState({ swapsState: { ...swapsState, customMaxGas: gasLimit }, - }) + }); } setCustomApproveTxData(data) { - const { swapsState } = this.store.getState() + const { swapsState } = this.store.getState(); this.store.updateState({ swapsState: { ...swapsState, customApproveTxData: data }, - }) + }); } setBackgroundSwapRouteState(routeState) { - const { swapsState } = this.store.getState() - this.store.updateState({ swapsState: { ...swapsState, routeState } }) + const { swapsState } = this.store.getState(); + this.store.updateState({ swapsState: { ...swapsState, routeState } }); } setSwapsLiveness(swapsFeatureIsLive) { - const { swapsState } = this.store.getState() + const { swapsState } = this.store.getState(); this.store.updateState({ swapsState: { ...swapsState, swapsFeatureIsLive }, - }) + }); } resetPostFetchState() { - const { swapsState } = this.store.getState() + const { swapsState } = this.store.getState(); this.store.updateState({ swapsState: { @@ -455,12 +460,12 @@ export default class SwapsController { swapsFeatureIsLive: swapsState.swapsFeatureIsLive, swapsQuoteRefreshTime: swapsState.swapsQuoteRefreshTime, }, - }) - clearTimeout(this.pollingTimeout) + }); + clearTimeout(this.pollingTimeout); } resetSwapsState() { - const { swapsState } = this.store.getState() + const { swapsState } = this.store.getState(); this.store.updateState({ swapsState: { @@ -469,33 +474,33 @@ export default class SwapsController { swapsFeatureIsLive: swapsState.swapsFeatureIsLive, swapsQuoteRefreshTime: swapsState.swapsQuoteRefreshTime, }, - }) - clearTimeout(this.pollingTimeout) + }); + clearTimeout(this.pollingTimeout); } async _getEthersGasPrice() { - const ethersGasPrice = await this.ethersProvider.getGasPrice() - return ethersGasPrice.toHexString() + const ethersGasPrice = await this.ethersProvider.getGasPrice(); + return ethersGasPrice.toHexString(); } async _findTopQuoteAndCalculateSavings(quotes = {}) { const tokenConversionRates = this.tokenRatesStore.getState() - .contractExchangeRates + .contractExchangeRates; const { swapsState: { customGasPrice }, - } = this.store.getState() + } = this.store.getState(); - const numQuotes = Object.keys(quotes).length + const numQuotes = Object.keys(quotes).length; if (!numQuotes) { - return {} + return {}; } - const newQuotes = cloneDeep(quotes) + const newQuotes = cloneDeep(quotes); - const usedGasPrice = customGasPrice || (await this._getEthersGasPrice()) + const usedGasPrice = customGasPrice || (await this._getEthersGasPrice()); - let topAggId = null - let overallValueOfBestQuoteForSorting = null + let topAggId = null; + let overallValueOfBestQuoteForSorting = null; Object.values(newQuotes).forEach((quote) => { const { @@ -510,20 +515,20 @@ export default class SwapsController { sourceToken, trade, fee: metaMaskFee, - } = quote + } = quote; const tradeGasLimitForCalculation = gasEstimate ? new BigNumber(gasEstimate, 16) - : new BigNumber(averageGas || MAX_GAS_LIMIT, 10) + : new BigNumber(averageGas || MAX_GAS_LIMIT, 10); const totalGasLimitForCalculation = tradeGasLimitForCalculation .plus(approvalNeeded?.gas || '0x0', 16) - .toString(16) + .toString(16); const gasTotalInWeiHex = calcGasTotal( totalGasLimitForCalculation, usedGasPrice, - ) + ); // trade.value is a sum of different values depending on the transaction. // It always includes any external fees charged by the quote source. In @@ -532,7 +537,7 @@ export default class SwapsController { const totalWeiCost = new BigNumber(gasTotalInWeiHex, 16).plus( trade.value, 16, - ) + ); const totalEthCost = conversionUtil(totalWeiCost, { fromCurrency: 'ETH', @@ -540,7 +545,7 @@ export default class SwapsController { toDenomination: 'ETH', fromNumericBase: 'BN', numberOfDecimals: 6, - }) + }); // The total fee is aggregator/exchange fees plus gas fees. // If the swap is from ETH, subtract the sourceAmount from the total cost. @@ -557,103 +562,103 @@ export default class SwapsController { numberOfDecimals: 6, }, ) - : totalEthCost + : totalEthCost; const decimalAdjustedDestinationAmount = calcTokenAmount( destinationAmount, destinationTokenInfo.decimals, - ) + ); const tokenPercentageOfPreFeeDestAmount = new BigNumber(100, 10) .minus(metaMaskFee, 10) - .div(100) + .div(100); const destinationAmountBeforeMetaMaskFee = decimalAdjustedDestinationAmount.div( tokenPercentageOfPreFeeDestAmount, - ) + ); const metaMaskFeeInTokens = destinationAmountBeforeMetaMaskFee.minus( decimalAdjustedDestinationAmount, - ) + ); - const tokenConversionRate = tokenConversionRates[destinationToken] - const conversionRateForSorting = tokenConversionRate || 1 + const tokenConversionRate = tokenConversionRates[destinationToken]; + const conversionRateForSorting = tokenConversionRate || 1; const ethValueOfTokens = decimalAdjustedDestinationAmount.times( conversionRateForSorting, 10, - ) + ); const conversionRateForCalculations = - destinationToken === ETH_SWAPS_TOKEN_ADDRESS ? 1 : tokenConversionRate + destinationToken === ETH_SWAPS_TOKEN_ADDRESS ? 1 : tokenConversionRate; const overallValueOfQuoteForSorting = conversionRateForCalculations === undefined ? ethValueOfTokens - : ethValueOfTokens.minus(ethFee, 10) + : ethValueOfTokens.minus(ethFee, 10); - quote.ethFee = ethFee.toString(10) + quote.ethFee = ethFee.toString(10); if (conversionRateForCalculations !== undefined) { - quote.ethValueOfTokens = ethValueOfTokens.toString(10) - quote.overallValueOfQuote = overallValueOfQuoteForSorting.toString(10) + quote.ethValueOfTokens = ethValueOfTokens.toString(10); + quote.overallValueOfQuote = overallValueOfQuoteForSorting.toString(10); quote.metaMaskFeeInEth = metaMaskFeeInTokens .times(conversionRateForCalculations) - .toString(10) + .toString(10); } if ( overallValueOfBestQuoteForSorting === null || overallValueOfQuoteForSorting.gt(overallValueOfBestQuoteForSorting) ) { - topAggId = aggregator - overallValueOfBestQuoteForSorting = overallValueOfQuoteForSorting + topAggId = aggregator; + overallValueOfBestQuoteForSorting = overallValueOfQuoteForSorting; } - }) + }); const isBest = newQuotes[topAggId].destinationToken === ETH_SWAPS_TOKEN_ADDRESS || - Boolean(tokenConversionRates[newQuotes[topAggId]?.destinationToken]) + Boolean(tokenConversionRates[newQuotes[topAggId]?.destinationToken]); - let savings = null + let savings = null; if (isBest) { - const bestQuote = newQuotes[topAggId] + const bestQuote = newQuotes[topAggId]; - savings = {} + savings = {}; const { ethFee: medianEthFee, metaMaskFeeInEth: medianMetaMaskFee, ethValueOfTokens: medianEthValueOfTokens, - } = getMedianEthValueQuote(Object.values(newQuotes)) + } = getMedianEthValueQuote(Object.values(newQuotes)); // Performance savings are calculated as: // (ethValueOfTokens for the best trade) - (ethValueOfTokens for the media trade) savings.performance = new BigNumber(bestQuote.ethValueOfTokens, 10).minus( medianEthValueOfTokens, 10, - ) + ); // Fee savings are calculated as: // (fee for the median trade) - (fee for the best trade) - savings.fee = new BigNumber(medianEthFee).minus(bestQuote.ethFee, 10) + savings.fee = new BigNumber(medianEthFee).minus(bestQuote.ethFee, 10); - savings.metaMaskFee = bestQuote.metaMaskFeeInEth + savings.metaMaskFee = bestQuote.metaMaskFeeInEth; // Total savings are calculated as: // performance savings + fee savings - metamask fee savings.total = savings.performance .plus(savings.fee) .minus(savings.metaMaskFee) - .toString(10) - savings.performance = savings.performance.toString(10) - savings.fee = savings.fee.toString(10) - savings.medianMetaMaskFee = medianMetaMaskFee + .toString(10); + savings.performance = savings.performance.toString(10); + savings.fee = savings.fee.toString(10); + savings.medianMetaMaskFee = medianMetaMaskFee; - newQuotes[topAggId].isBestQuote = true - newQuotes[topAggId].savings = savings + newQuotes[topAggId].isBestQuote = true; + newQuotes[topAggId].savings = savings; } - return [topAggId, newQuotes] + return [topAggId, newQuotes]; } async _getERC20Allowance(contractAddress, walletAddress) { @@ -661,8 +666,8 @@ export default class SwapsController { contractAddress, abi, this.ethersProvider, - ) - return await contract.allowance(walletAddress, METASWAP_ADDRESS) + ); + return await contract.allowance(walletAddress, METASWAP_ADDRESS); } /** @@ -674,8 +679,8 @@ export default class SwapsController { * until the value can be fetched again. */ _setupSwapsLivenessFetching() { - const TEN_MINUTES_MS = 10 * 60 * 1000 - let intervalId = null + const TEN_MINUTES_MS = 10 * 60 * 1000; + let intervalId = null; const fetchAndSetupInterval = () => { if (window.navigator.onLine && intervalId === null) { @@ -684,25 +689,25 @@ export default class SwapsController { intervalId = setInterval( this._fetchAndSetSwapsLiveness.bind(this), TEN_MINUTES_MS, - ) - this._fetchAndSetSwapsLiveness() + ); + this._fetchAndSetSwapsLiveness(); } - } + }; - window.addEventListener('online', fetchAndSetupInterval) + window.addEventListener('online', fetchAndSetupInterval); window.addEventListener('offline', () => { if (intervalId !== null) { - clearInterval(intervalId) - intervalId = null + clearInterval(intervalId); + intervalId = null; - const { swapsState } = this.store.getState() + const { swapsState } = this.store.getState(); if (swapsState.swapsFeatureIsLive) { - this.setSwapsLiveness(false) + this.setSwapsLiveness(false); } } - }) + }); - fetchAndSetupInterval() + fetchAndSetupInterval(); } /** @@ -716,41 +721,41 @@ export default class SwapsController { * state. */ async _fetchAndSetSwapsLiveness() { - const { swapsState } = this.store.getState() - const { swapsFeatureIsLive: oldSwapsFeatureIsLive } = swapsState - let swapsFeatureIsLive = false - let successfullyFetched = false - let numAttempts = 0 + const { swapsState } = this.store.getState(); + const { swapsFeatureIsLive: oldSwapsFeatureIsLive } = swapsState; + let swapsFeatureIsLive = false; + let successfullyFetched = false; + let numAttempts = 0; const fetchAndIncrementNumAttempts = async () => { try { - swapsFeatureIsLive = Boolean(await this._fetchSwapsFeatureLiveness()) - successfullyFetched = true + swapsFeatureIsLive = Boolean(await this._fetchSwapsFeatureLiveness()); + successfullyFetched = true; } catch (err) { - log.error(err) - numAttempts += 1 + log.error(err); + numAttempts += 1; } - } + }; - await fetchAndIncrementNumAttempts() + await fetchAndIncrementNumAttempts(); // The loop conditions are modified by fetchAndIncrementNumAttempts. // eslint-disable-next-line no-unmodified-loop-condition while (!successfullyFetched && numAttempts < 3) { await new Promise((resolve) => { - setTimeout(resolve, 5000) // 5 seconds - }) - await fetchAndIncrementNumAttempts() + setTimeout(resolve, 5000); // 5 seconds + }); + await fetchAndIncrementNumAttempts(); } if (!successfullyFetched) { log.error( 'Failed to fetch swaps feature flag 3 times. Setting to false and trying again next interval.', - ) + ); } if (swapsFeatureIsLive !== oldSwapsFeatureIsLive) { - this.setSwapsLiveness(swapsFeatureIsLive) + this.setSwapsLiveness(swapsFeatureIsLive); } } } @@ -763,50 +768,50 @@ export default class SwapsController { */ function getMedianEthValueQuote(_quotes) { if (!Array.isArray(_quotes) || _quotes.length === 0) { - throw new Error('Expected non-empty array param.') + throw new Error('Expected non-empty array param.'); } - const quotes = [..._quotes] + const quotes = [..._quotes]; quotes.sort((quoteA, quoteB) => { - const overallValueOfQuoteA = new BigNumber(quoteA.overallValueOfQuote, 10) - const overallValueOfQuoteB = new BigNumber(quoteB.overallValueOfQuote, 10) + const overallValueOfQuoteA = new BigNumber(quoteA.overallValueOfQuote, 10); + const overallValueOfQuoteB = new BigNumber(quoteB.overallValueOfQuote, 10); if (overallValueOfQuoteA.equals(overallValueOfQuoteB)) { - return 0 + return 0; } - return overallValueOfQuoteA.lessThan(overallValueOfQuoteB) ? -1 : 1 - }) + return overallValueOfQuoteA.lessThan(overallValueOfQuoteB) ? -1 : 1; + }); if (quotes.length % 2 === 1) { // return middle values const medianOverallValue = - quotes[(quotes.length - 1) / 2].overallValueOfQuote + quotes[(quotes.length - 1) / 2].overallValueOfQuote; const quotesMatchingMedianQuoteValue = quotes.filter( (quote) => medianOverallValue === quote.overallValueOfQuote, - ) - return meansOfQuotesFeesAndValue(quotesMatchingMedianQuoteValue) + ); + return meansOfQuotesFeesAndValue(quotesMatchingMedianQuoteValue); } // return mean of middle two values - const upperIndex = quotes.length / 2 - const lowerIndex = upperIndex - 1 + const upperIndex = quotes.length / 2; + const lowerIndex = upperIndex - 1; - const overallValueAtUpperIndex = quotes[upperIndex].overallValueOfQuote - const overallValueAtLowerIndex = quotes[lowerIndex].overallValueOfQuote + const overallValueAtUpperIndex = quotes[upperIndex].overallValueOfQuote; + const overallValueAtLowerIndex = quotes[lowerIndex].overallValueOfQuote; const quotesMatchingUpperIndexValue = quotes.filter( (quote) => overallValueAtUpperIndex === quote.overallValueOfQuote, - ) + ); const quotesMatchingLowerIndexValue = quotes.filter( (quote) => overallValueAtLowerIndex === quote.overallValueOfQuote, - ) + ); const feesAndValueAtUpperIndex = meansOfQuotesFeesAndValue( quotesMatchingUpperIndexValue, - ) + ); const feesAndValueAtLowerIndex = meansOfQuotesFeesAndValue( quotesMatchingLowerIndexValue, - ) + ); return { ethFee: new BigNumber(feesAndValueAtUpperIndex.ethFee, 10) @@ -827,7 +832,7 @@ function getMedianEthValueQuote(_quotes) { .plus(feesAndValueAtLowerIndex.ethValueOfTokens, 10) .dividedBy(2) .toString(10), - } + }; } /** @@ -857,7 +862,7 @@ function meansOfQuotesFeesAndValue(quotes) { metaMaskFeeInEth: new BigNumber(0, 10), ethValueOfTokens: new BigNumber(0, 10), }, - ) + ); return { ethFee: feeAndValueSumsAsBigNumbers.ethFee @@ -869,10 +874,10 @@ function meansOfQuotesFeesAndValue(quotes) { ethValueOfTokens: feeAndValueSumsAsBigNumbers.ethValueOfTokens .div(quotes.length, 10) .toString(10), - } + }; } export const utils = { getMedianEthValueQuote, meansOfQuotesFeesAndValue, -} +}; diff --git a/app/scripts/controllers/threebox.js b/app/scripts/controllers/threebox.js index d7503b589..8355fb4fe 100644 --- a/app/scripts/controllers/threebox.js +++ b/app/scripts/controllers/threebox.js @@ -1,21 +1,21 @@ -import { ObservableStore } from '@metamask/obs-store' +import { ObservableStore } from '@metamask/obs-store'; /* eslint-disable import/first,import/order */ const Box = process.env.IN_TEST ? require('../../../development/mock-3box') - : require('3box') + : require('3box'); /* eslint-enable import/order */ -import log from 'loglevel' -import { JsonRpcEngine } from 'json-rpc-engine' -import providerFromEngine from 'eth-json-rpc-middleware/providerFromEngine' -import Migrator from '../lib/migrator' -import migrations from '../migrations' -import createOriginMiddleware from '../lib/createOriginMiddleware' -import createMetamaskMiddleware from './network/createMetamaskMiddleware' +import log from 'loglevel'; +import { JsonRpcEngine } from 'json-rpc-engine'; +import providerFromEngine from 'eth-json-rpc-middleware/providerFromEngine'; +import Migrator from '../lib/migrator'; +import migrations from '../migrations'; +import createOriginMiddleware from '../lib/createOriginMiddleware'; +import createMetamaskMiddleware from './network/createMetamaskMiddleware'; /* eslint-enable import/first */ -const SYNC_TIMEOUT = 60 * 1000 // one minute +const SYNC_TIMEOUT = 60 * 1000; // one minute export default class ThreeBoxController { constructor(opts = {}) { @@ -25,40 +25,40 @@ export default class ThreeBoxController { addressBookController, version, getKeyringControllerState, - } = opts + } = opts; - this.preferencesController = preferencesController - this.addressBookController = addressBookController - this.keyringController = keyringController + this.preferencesController = preferencesController; + this.addressBookController = addressBookController; + this.keyringController = keyringController; this.provider = this._createProvider({ version, getAccounts: async ({ origin }) => { if (origin !== '3Box') { - return [] + return []; } - const { isUnlocked } = getKeyringControllerState() + const { isUnlocked } = getKeyringControllerState(); - const accounts = await this.keyringController.getAccounts() + const accounts = await this.keyringController.getAccounts(); if (isUnlocked && accounts[0]) { const appKeyAddress = await this.keyringController.getAppKeyAddress( accounts[0], 'wallet://3box.metamask.io', - ) - return [appKeyAddress] + ); + return [appKeyAddress]; } - return [] + return []; }, processPersonalMessage: async (msgParams) => { - const accounts = await this.keyringController.getAccounts() + const accounts = await this.keyringController.getAccounts(); return keyringController.signPersonalMessage( { ...msgParams, from: accounts[0] }, { withAppKeyOrigin: 'wallet://3box.metamask.io', }, - ) + ); }, - }) + }); const initState = { threeBoxSyncingAllowed: false, @@ -68,193 +68,196 @@ export default class ThreeBoxController { threeBoxAddress: null, threeBoxSynced: false, threeBoxDisabled: false, - } - this.store = new ObservableStore(initState) - this.registeringUpdates = false + }; + this.store = new ObservableStore(initState); + this.registeringUpdates = false; this.lastMigration = migrations .sort((a, b) => a.version - b.version) - .slice(-1)[0] + .slice(-1)[0]; if (initState.threeBoxSyncingAllowed) { - this.init() + this.init(); } } async init() { - const accounts = await this.keyringController.getAccounts() - this.address = accounts[0] + const accounts = await this.keyringController.getAccounts(); + this.address = accounts[0]; if (this.address && !(this.box && this.store.getState().threeBoxSynced)) { - await this.new3Box() + await this.new3Box(); } } async _update3Box() { try { - const { threeBoxSyncingAllowed, threeBoxSynced } = this.store.getState() + const { threeBoxSyncingAllowed, threeBoxSynced } = this.store.getState(); if (threeBoxSyncingAllowed && threeBoxSynced) { const newState = { preferences: this.preferencesController.store.getState(), addressBook: this.addressBookController.state, lastUpdated: Date.now(), lastMigration: this.lastMigration, - } + }; - await this.space.private.set('metamaskBackup', JSON.stringify(newState)) - await this.setShowRestorePromptToFalse() + await this.space.private.set( + 'metamaskBackup', + JSON.stringify(newState), + ); + await this.setShowRestorePromptToFalse(); } } catch (error) { - console.error(error) + console.error(error); } } _createProvider(providerOpts) { - const metamaskMiddleware = createMetamaskMiddleware(providerOpts) - const engine = new JsonRpcEngine() - engine.push(createOriginMiddleware({ origin: '3Box' })) - engine.push(metamaskMiddleware) - const provider = providerFromEngine(engine) - return provider + const metamaskMiddleware = createMetamaskMiddleware(providerOpts); + const engine = new JsonRpcEngine(); + engine.push(createOriginMiddleware({ origin: '3Box' })); + engine.push(metamaskMiddleware); + const provider = providerFromEngine(engine); + return provider; } _waitForOnSyncDone() { return new Promise((resolve) => { this.box.onSyncDone(() => { - log.debug('3Box box sync done') - return resolve() - }) - }) + log.debug('3Box box sync done'); + return resolve(); + }); + }); } async new3Box() { - const accounts = await this.keyringController.getAccounts() + const accounts = await this.keyringController.getAccounts(); this.address = await this.keyringController.getAppKeyAddress( accounts[0], 'wallet://3box.metamask.io', - ) - let backupExists + ); + let backupExists; try { - const threeBoxConfig = await Box.getConfig(this.address) - backupExists = threeBoxConfig.spaces && threeBoxConfig.spaces.metamask + const threeBoxConfig = await Box.getConfig(this.address); + backupExists = threeBoxConfig.spaces && threeBoxConfig.spaces.metamask; } catch (e) { if (e.message.match(/^Error: Invalid response \(404\)/u)) { - backupExists = false + backupExists = false; } else { - throw e + throw e; } } if (this.getThreeBoxSyncingState() || backupExists) { - this.store.updateState({ threeBoxSynced: false }) + this.store.updateState({ threeBoxSynced: false }); - let timedOut = false + let timedOut = false; const syncTimeout = setTimeout(() => { - log.error(`3Box sync timed out after ${SYNC_TIMEOUT} ms`) - timedOut = true + log.error(`3Box sync timed out after ${SYNC_TIMEOUT} ms`); + timedOut = true; this.store.updateState({ threeBoxDisabled: true, threeBoxSyncingAllowed: false, - }) - }, SYNC_TIMEOUT) + }); + }, SYNC_TIMEOUT); try { - this.box = await Box.openBox(this.address, this.provider) - await this._waitForOnSyncDone() + this.box = await Box.openBox(this.address, this.provider); + await this._waitForOnSyncDone(); this.space = await this.box.openSpace('metamask', { onSyncDone: async () => { const stateUpdate = { threeBoxSynced: true, threeBoxAddress: this.address, - } + }; if (timedOut) { - log.info(`3Box sync completed after timeout; no longer disabled`) - stateUpdate.threeBoxDisabled = false + log.info(`3Box sync completed after timeout; no longer disabled`); + stateUpdate.threeBoxDisabled = false; } - clearTimeout(syncTimeout) - this.store.updateState(stateUpdate) + clearTimeout(syncTimeout); + this.store.updateState(stateUpdate); - log.debug('3Box space sync done') + log.debug('3Box space sync done'); }, - }) + }); } catch (e) { - console.error(e) - throw e + console.error(e); + throw e; } } } async getLastUpdated() { - const res = await this.space.private.get('metamaskBackup') - const parsedRes = JSON.parse(res || '{}') - return parsedRes.lastUpdated + const res = await this.space.private.get('metamaskBackup'); + const parsedRes = JSON.parse(res || '{}'); + return parsedRes.lastUpdated; } async migrateBackedUpState(backedUpState) { - const migrator = new Migrator({ migrations }) - const { preferences, addressBook } = JSON.parse(backedUpState) + const migrator = new Migrator({ migrations }); + const { preferences, addressBook } = JSON.parse(backedUpState); const formattedStateBackup = { PreferencesController: preferences, AddressBookController: addressBook, - } + }; const initialMigrationState = migrator.generateInitialState( formattedStateBackup, - ) - const migratedState = await migrator.migrateData(initialMigrationState) + ); + const migratedState = await migrator.migrateData(initialMigrationState); return { preferences: migratedState.data.PreferencesController, addressBook: migratedState.data.AddressBookController, - } + }; } async restoreFromThreeBox() { - const backedUpState = await this.space.private.get('metamaskBackup') + const backedUpState = await this.space.private.get('metamaskBackup'); const { preferences, addressBook } = await this.migrateBackedUpState( backedUpState, - ) - this.store.updateState({ threeBoxLastUpdated: backedUpState.lastUpdated }) - preferences && this.preferencesController.store.updateState(preferences) - addressBook && this.addressBookController.update(addressBook, true) - this.setShowRestorePromptToFalse() + ); + this.store.updateState({ threeBoxLastUpdated: backedUpState.lastUpdated }); + preferences && this.preferencesController.store.updateState(preferences); + addressBook && this.addressBookController.update(addressBook, true); + this.setShowRestorePromptToFalse(); } turnThreeBoxSyncingOn() { - this._registerUpdates() + this._registerUpdates(); } turnThreeBoxSyncingOff() { - this.box.logout() + this.box.logout(); } setShowRestorePromptToFalse() { - this.store.updateState({ showRestorePrompt: false }) + this.store.updateState({ showRestorePrompt: false }); } setThreeBoxSyncingPermission(newThreeboxSyncingState) { if (this.store.getState().threeBoxDisabled) { - return + return; } this.store.updateState({ threeBoxSyncingAllowed: newThreeboxSyncingState, - }) + }); if (newThreeboxSyncingState && this.box) { - this.turnThreeBoxSyncingOn() + this.turnThreeBoxSyncingOn(); } if (!newThreeboxSyncingState && this.box) { - this.turnThreeBoxSyncingOff() + this.turnThreeBoxSyncingOff(); } } getThreeBoxSyncingState() { - return this.store.getState().threeBoxSyncingAllowed + return this.store.getState().threeBoxSyncingAllowed; } _registerUpdates() { if (!this.registeringUpdates) { - const updatePreferences = this._update3Box.bind(this) - this.preferencesController.store.subscribe(updatePreferences) - const updateAddressBook = this._update3Box.bind(this) - this.addressBookController.subscribe(updateAddressBook) - this.registeringUpdates = true + const updatePreferences = this._update3Box.bind(this); + this.preferencesController.store.subscribe(updatePreferences); + const updateAddressBook = this._update3Box.bind(this); + this.addressBookController.subscribe(updateAddressBook); + this.registeringUpdates = true; } } } diff --git a/app/scripts/controllers/token-rates.js b/app/scripts/controllers/token-rates.js index 031017c83..a3f0f6710 100644 --- a/app/scripts/controllers/token-rates.js +++ b/app/scripts/controllers/token-rates.js @@ -1,13 +1,13 @@ -import { ObservableStore } from '@metamask/obs-store' -import log from 'loglevel' -import { normalize as normalizeAddress } from 'eth-sig-util' -import ethUtil from 'ethereumjs-util' -import getFetchWithTimeout from '../../../shared/modules/fetch-with-timeout' +import { ObservableStore } from '@metamask/obs-store'; +import log from 'loglevel'; +import { normalize as normalizeAddress } from 'eth-sig-util'; +import ethUtil from 'ethereumjs-util'; +import getFetchWithTimeout from '../../../shared/modules/fetch-with-timeout'; -const fetchWithTimeout = getFetchWithTimeout(30000) +const fetchWithTimeout = getFetchWithTimeout(30000); // By default, poll every 3 minutes -const DEFAULT_INTERVAL = 180 * 1000 +const DEFAULT_INTERVAL = 180 * 1000; /** * A controller that polls for token exchange @@ -20,43 +20,43 @@ export default class TokenRatesController { * @param {Object} [config] - Options to configure controller */ constructor({ currency, preferences } = {}) { - this.store = new ObservableStore() - this.currency = currency - this.preferences = preferences + this.store = new ObservableStore(); + this.currency = currency; + this.preferences = preferences; } /** * Updates exchange rates for all tokens */ async updateExchangeRates() { - const contractExchangeRates = {} + const contractExchangeRates = {}; const nativeCurrency = this.currency ? this.currency.state.nativeCurrency.toLowerCase() - : 'eth' - const pairs = this._tokens.map((token) => token.address).join(',') - const query = `contract_addresses=${pairs}&vs_currencies=${nativeCurrency}` + : 'eth'; + const pairs = this._tokens.map((token) => token.address).join(','); + const query = `contract_addresses=${pairs}&vs_currencies=${nativeCurrency}`; if (this._tokens.length > 0) { try { const response = await fetchWithTimeout( `https://api.coingecko.com/api/v3/simple/token_price/ethereum?${query}`, - ) - const prices = await response.json() + ); + const prices = await response.json(); this._tokens.forEach((token) => { const price = prices[token.address.toLowerCase()] || - prices[ethUtil.toChecksumAddress(token.address)] + prices[ethUtil.toChecksumAddress(token.address)]; contractExchangeRates[normalizeAddress(token.address)] = price ? price[nativeCurrency] - : 0 - }) + : 0; + }); } catch (error) { log.warn( `MetaMask - TokenRatesController exchange rate fetch failed.`, error, - ) + ); } } - this.store.putState({ contractExchangeRates }) + this.store.putState({ contractExchangeRates }); } /* eslint-disable accessor-pairs */ @@ -64,38 +64,38 @@ export default class TokenRatesController { * @type {Object} */ set preferences(preferences) { - this._preferences && this._preferences.unsubscribe() + this._preferences && this._preferences.unsubscribe(); if (!preferences) { - return + return; } - this._preferences = preferences - this.tokens = preferences.getState().tokens + this._preferences = preferences; + this.tokens = preferences.getState().tokens; preferences.subscribe(({ tokens = [] }) => { - this.tokens = tokens - }) + this.tokens = tokens; + }); } /** * @type {Array} */ set tokens(tokens) { - this._tokens = tokens - this.updateExchangeRates() + this._tokens = tokens; + this.updateExchangeRates(); } /* eslint-enable accessor-pairs */ start(interval = DEFAULT_INTERVAL) { - this._handle && clearInterval(this._handle) + this._handle && clearInterval(this._handle); if (!interval) { - return + return; } this._handle = setInterval(() => { - this.updateExchangeRates() - }, interval) - this.updateExchangeRates() + this.updateExchangeRates(); + }, interval); + this.updateExchangeRates(); } stop() { - this._handle && clearInterval(this._handle) + this._handle && clearInterval(this._handle); } } diff --git a/app/scripts/controllers/transactions/index.js b/app/scripts/controllers/transactions/index.js index a88cfff64..36864c509 100644 --- a/app/scripts/controllers/transactions/index.js +++ b/app/scripts/controllers/transactions/index.js @@ -1,37 +1,37 @@ -import EventEmitter from 'safe-event-emitter' -import { ObservableStore } from '@metamask/obs-store' -import ethUtil from 'ethereumjs-util' -import Transaction from 'ethereumjs-tx' -import EthQuery from 'ethjs-query' -import { ethErrors } from 'eth-rpc-errors' -import abi from 'human-standard-token-abi' -import { ethers } from 'ethers' -import NonceTracker from 'nonce-tracker' -import log from 'loglevel' -import BigNumber from 'bignumber.js' -import cleanErrorStack from '../../lib/cleanErrorStack' +import EventEmitter from 'safe-event-emitter'; +import { ObservableStore } from '@metamask/obs-store'; +import ethUtil from 'ethereumjs-util'; +import Transaction from 'ethereumjs-tx'; +import EthQuery from 'ethjs-query'; +import { ethErrors } from 'eth-rpc-errors'; +import abi from 'human-standard-token-abi'; +import { ethers } from 'ethers'; +import NonceTracker from 'nonce-tracker'; +import log from 'loglevel'; +import BigNumber from 'bignumber.js'; +import cleanErrorStack from '../../lib/cleanErrorStack'; import { hexToBn, bnToHex, BnMultiplyByFraction, addHexPrefix, -} from '../../lib/util' -import { TRANSACTION_NO_CONTRACT_ERROR_KEY } from '../../../../ui/app/helpers/constants/error-keys' -import { getSwapsTokensReceivedFromTxMeta } from '../../../../ui/app/pages/swaps/swaps.util' +} from '../../lib/util'; +import { TRANSACTION_NO_CONTRACT_ERROR_KEY } from '../../../../ui/app/helpers/constants/error-keys'; +import { getSwapsTokensReceivedFromTxMeta } from '../../../../ui/app/pages/swaps/swaps.util'; import { TRANSACTION_CATEGORIES, TRANSACTION_STATUSES, TRANSACTION_TYPES, -} from '../../../../shared/constants/transaction' -import TransactionStateManager from './tx-state-manager' -import TxGasUtil from './tx-gas-utils' -import PendingTransactionTracker from './pending-tx-tracker' -import * as txUtils from './lib/util' +} from '../../../../shared/constants/transaction'; +import TransactionStateManager from './tx-state-manager'; +import TxGasUtil from './tx-gas-utils'; +import PendingTransactionTracker from './pending-tx-tracker'; +import * as txUtils from './lib/util'; -const hstInterface = new ethers.utils.Interface(abi) +const hstInterface = new ethers.utils.Interface(abi); -const SIMPLE_GAS_COST = '0x5208' // Hex for 21000, cost of a simple send. -const MAX_MEMSTORE_TX_LIST_SIZE = 100 // Number of transactions (by unique nonces) to keep in memory +const SIMPLE_GAS_COST = '0x5208'; // Hex for 21000, cost of a simple send. +const MAX_MEMSTORE_TX_LIST_SIZE = 100; // Number of transactions (by unique nonces) to keep in memory /** Transaction Controller is an aggregate of sub-controllers and trackers @@ -62,31 +62,31 @@ const MAX_MEMSTORE_TX_LIST_SIZE = 100 // Number of transactions (by unique nonce export default class TransactionController extends EventEmitter { constructor(opts) { - super() - this.networkStore = opts.networkStore || new ObservableStore({}) - this._getCurrentChainId = opts.getCurrentChainId - this.preferencesStore = opts.preferencesStore || new ObservableStore({}) - this.provider = opts.provider - this.getPermittedAccounts = opts.getPermittedAccounts - this.blockTracker = opts.blockTracker - this.signEthTx = opts.signTransaction - this.inProcessOfSigning = new Set() - this._trackMetaMetricsEvent = opts.trackMetaMetricsEvent - this._getParticipateInMetrics = opts.getParticipateInMetrics + super(); + this.networkStore = opts.networkStore || new ObservableStore({}); + this._getCurrentChainId = opts.getCurrentChainId; + this.preferencesStore = opts.preferencesStore || new ObservableStore({}); + this.provider = opts.provider; + this.getPermittedAccounts = opts.getPermittedAccounts; + this.blockTracker = opts.blockTracker; + this.signEthTx = opts.signTransaction; + this.inProcessOfSigning = new Set(); + this._trackMetaMetricsEvent = opts.trackMetaMetricsEvent; + this._getParticipateInMetrics = opts.getParticipateInMetrics; - this.memStore = new ObservableStore({}) - this.query = new EthQuery(this.provider) + this.memStore = new ObservableStore({}); + this.query = new EthQuery(this.provider); - this.txGasUtil = new TxGasUtil(this.provider) - this._mapMethods() + this.txGasUtil = new TxGasUtil(this.provider); + this._mapMethods(); this.txStateManager = new TransactionStateManager({ initState: opts.initState, txHistoryLimit: opts.txHistoryLimit, getNetwork: this.getNetwork.bind(this), - }) - this._onBootCleanUp() + }); + this._onBootCleanUp(); - this.store = this.txStateManager.store + this.store = this.txStateManager.store; this.nonceTracker = new NonceTracker({ provider: this.provider, blockTracker: this.blockTracker, @@ -96,35 +96,35 @@ export default class TransactionController extends EventEmitter { getConfirmedTransactions: this.txStateManager.getConfirmedTransactions.bind( this.txStateManager, ), - }) + }); this.pendingTxTracker = new PendingTransactionTracker({ provider: this.provider, nonceTracker: this.nonceTracker, publishTransaction: (rawTx) => this.query.sendRawTransaction(rawTx), getPendingTransactions: () => { - const pending = this.txStateManager.getPendingTransactions() - const approved = this.txStateManager.getApprovedTransactions() - return [...pending, ...approved] + const pending = this.txStateManager.getPendingTransactions(); + const approved = this.txStateManager.getApprovedTransactions(); + return [...pending, ...approved]; }, approveTransaction: this.approveTransaction.bind(this), getCompletedTransactions: this.txStateManager.getConfirmedTransactions.bind( this.txStateManager, ), - }) + }); - this.txStateManager.store.subscribe(() => this.emit('update:badge')) - this._setupListeners() + this.txStateManager.store.subscribe(() => this.emit('update:badge')); + this._setupListeners(); // memstore is computed from a few different stores - this._updateMemstore() - this.txStateManager.store.subscribe(() => this._updateMemstore()) + this._updateMemstore(); + this.txStateManager.store.subscribe(() => this._updateMemstore()); this.networkStore.subscribe(() => { - this._onBootCleanUp() - this._updateMemstore() - }) + this._onBootCleanUp(); + this._updateMemstore(); + }); // request state update to finalize initialization - this._updatePendingTxsAfterFirstBlock() + this._updatePendingTxsAfterFirstBlock(); } /** @@ -134,13 +134,13 @@ export default class TransactionController extends EventEmitter { * @returns {number} The numerical chainId. */ getChainId() { - const networkState = this.networkStore.getState() - const chainId = this._getCurrentChainId() - const integerChainId = parseInt(chainId, 16) + const networkState = this.networkStore.getState(); + const chainId = this._getCurrentChainId(); + const integerChainId = parseInt(chainId, 16); if (networkState === 'loading' || Number.isNaN(integerChainId)) { - return 0 + return 0; } - return integerChainId + return integerChainId; } /** @@ -148,8 +148,8 @@ export default class TransactionController extends EventEmitter { @emits ${txMeta.id}:unapproved */ addTx(txMeta) { - this.txStateManager.addTx(txMeta) - this.emit(`${txMeta.id}:unapproved`, txMeta) + this.txStateManager.addTx(txMeta); + this.emit(`${txMeta.id}:unapproved`, txMeta); } /** @@ -157,7 +157,7 @@ export default class TransactionController extends EventEmitter { @param {string} address - hex string of the from address for txs being removed */ wipeTransactions(address) { - this.txStateManager.wipeTransactions(address) + this.txStateManager.wipeTransactions(address); } /** @@ -170,12 +170,12 @@ export default class TransactionController extends EventEmitter { async newUnapprovedTransaction(txParams, opts = {}) { log.debug( `MetaMaskController newUnapprovedTransaction ${JSON.stringify(txParams)}`, - ) + ); const initialTxMeta = await this.addUnapprovedTransaction( txParams, opts.origin, - ) + ); // listen for tx completion (success, fail) return new Promise((resolve, reject) => { @@ -184,7 +184,7 @@ export default class TransactionController extends EventEmitter { (finishedTxMeta) => { switch (finishedTxMeta.status) { case TRANSACTION_STATUSES.SUBMITTED: - return resolve(finishedTxMeta.hash) + return resolve(finishedTxMeta.hash); case TRANSACTION_STATUSES.REJECTED: return reject( cleanErrorStack( @@ -192,13 +192,13 @@ export default class TransactionController extends EventEmitter { 'MetaMask Tx Signature: User denied transaction signature.', ), ), - ) + ); case TRANSACTION_STATUSES.FAILED: return reject( cleanErrorStack( ethErrors.rpc.internal(finishedTxMeta.err.message), ), - ) + ); default: return reject( cleanErrorStack( @@ -208,11 +208,11 @@ export default class TransactionController extends EventEmitter { )}`, ), ), - ) + ); } }, - ) - }) + ); + }); } /** @@ -223,9 +223,9 @@ export default class TransactionController extends EventEmitter { */ async addUnapprovedTransaction(txParams, origin) { // validate - const normalizedTxParams = txUtils.normalizeTxParams(txParams) + const normalizedTxParams = txUtils.normalizeTxParams(txParams); - txUtils.validateTxParams(normalizedTxParams) + txUtils.validateTxParams(normalizedTxParams); /** `generateTxMeta` adds the default txMeta properties to the passed object. @@ -236,7 +236,7 @@ export default class TransactionController extends EventEmitter { let txMeta = this.txStateManager.generateTxMeta({ txParams: normalizedTxParams, type: TRANSACTION_TYPES.STANDARD, - }) + }); if (origin === 'metamask') { // Assert the from address is the selected address @@ -248,48 +248,48 @@ export default class TransactionController extends EventEmitter { fromAddress: normalizedTxParams.from, selectedAddress: this.getSelectedAddress(), }, - }) + }); } } else { // Assert that the origin has permissions to initiate transactions from // the specified address - const permittedAddresses = await this.getPermittedAccounts(origin) + const permittedAddresses = await this.getPermittedAccounts(origin); if (!permittedAddresses.includes(normalizedTxParams.from)) { - throw ethErrors.provider.unauthorized({ data: { origin } }) + throw ethErrors.provider.unauthorized({ data: { origin } }); } } - txMeta.origin = origin + txMeta.origin = origin; const { transactionCategory, getCodeResponse, - } = await this._determineTransactionCategory(txParams) - txMeta.transactionCategory = transactionCategory + } = await this._determineTransactionCategory(txParams); + txMeta.transactionCategory = transactionCategory; // ensure value txMeta.txParams.value = txMeta.txParams.value ? addHexPrefix(txMeta.txParams.value) - : '0x0' + : '0x0'; - this.addTx(txMeta) - this.emit('newUnapprovedTx', txMeta) + this.addTx(txMeta); + this.emit('newUnapprovedTx', txMeta); try { - txMeta = await this.addTxGasDefaults(txMeta, getCodeResponse) + txMeta = await this.addTxGasDefaults(txMeta, getCodeResponse); } catch (error) { - log.warn(error) - txMeta = this.txStateManager.getTx(txMeta.id) - txMeta.loadingDefaults = false - this.txStateManager.updateTx(txMeta, 'Failed to calculate gas defaults.') - throw error + log.warn(error); + txMeta = this.txStateManager.getTx(txMeta.id); + txMeta.loadingDefaults = false; + this.txStateManager.updateTx(txMeta, 'Failed to calculate gas defaults.'); + throw error; } - txMeta.loadingDefaults = false + txMeta.loadingDefaults = false; // save txMeta - this.txStateManager.updateTx(txMeta, 'Added new unapproved transaction.') + this.txStateManager.updateTx(txMeta, 'Added new unapproved transaction.'); - return txMeta + return txMeta; } /** @@ -298,24 +298,24 @@ export default class TransactionController extends EventEmitter { * @returns {Promise} resolves with txMeta */ async addTxGasDefaults(txMeta, getCodeResponse) { - const defaultGasPrice = await this._getDefaultGasPrice(txMeta) + const defaultGasPrice = await this._getDefaultGasPrice(txMeta); const { gasLimit: defaultGasLimit, simulationFails, - } = await this._getDefaultGasLimit(txMeta, getCodeResponse) + } = await this._getDefaultGasLimit(txMeta, getCodeResponse); // eslint-disable-next-line no-param-reassign - txMeta = this.txStateManager.getTx(txMeta.id) + txMeta = this.txStateManager.getTx(txMeta.id); if (simulationFails) { - txMeta.simulationFails = simulationFails + txMeta.simulationFails = simulationFails; } if (defaultGasPrice && !txMeta.txParams.gasPrice) { - txMeta.txParams.gasPrice = defaultGasPrice + txMeta.txParams.gasPrice = defaultGasPrice; } if (defaultGasLimit && !txMeta.txParams.gas) { - txMeta.txParams.gas = defaultGasLimit + txMeta.txParams.gas = defaultGasLimit; } - return txMeta + return txMeta; } /** @@ -325,11 +325,11 @@ export default class TransactionController extends EventEmitter { */ async _getDefaultGasPrice(txMeta) { if (txMeta.txParams.gasPrice) { - return undefined + return undefined; } - const gasPrice = await this.query.gasPrice() + const gasPrice = await this.query.gasPrice(); - return addHexPrefix(gasPrice.toString(16)) + return addHexPrefix(gasPrice.toString(16)); } /** @@ -340,7 +340,7 @@ export default class TransactionController extends EventEmitter { */ async _getDefaultGasLimit(txMeta, getCodeResponse) { if (txMeta.txParams.gas) { - return {} + return {}; } else if ( txMeta.txParams.to && txMeta.transactionCategory === TRANSACTION_CATEGORIES.SENT_ETHER @@ -349,31 +349,31 @@ export default class TransactionController extends EventEmitter { if (txMeta.txParams.data) { const err = new Error( 'TxGasUtil - Trying to call a function on a non-contract address', - ) + ); // set error key so ui can display localized error message - err.errorKey = TRANSACTION_NO_CONTRACT_ERROR_KEY + err.errorKey = TRANSACTION_NO_CONTRACT_ERROR_KEY; // set the response on the error so that we can see in logs what the actual response was - err.getCodeResponse = getCodeResponse - throw err + err.getCodeResponse = getCodeResponse; + throw err; } // This is a standard ether simple send, gas requirement is exactly 21k - return { gasLimit: SIMPLE_GAS_COST } + return { gasLimit: SIMPLE_GAS_COST }; } const { blockGasLimit, estimatedGasHex, simulationFails, - } = await this.txGasUtil.analyzeGasUsage(txMeta) + } = await this.txGasUtil.analyzeGasUsage(txMeta); // add additional gas buffer to our estimation for safety const gasLimit = this.txGasUtil.addGasBuffer( addHexPrefix(estimatedGasHex), blockGasLimit, - ) - return { gasLimit, simulationFails } + ); + return { gasLimit, simulationFails }; } /** @@ -385,13 +385,13 @@ export default class TransactionController extends EventEmitter { * @returns {txMeta} */ async createCancelTransaction(originalTxId, customGasPrice) { - const originalTxMeta = this.txStateManager.getTx(originalTxId) - const { txParams } = originalTxMeta - const { gasPrice: lastGasPrice, from, nonce } = txParams + const originalTxMeta = this.txStateManager.getTx(originalTxId); + const { txParams } = originalTxMeta; + const { gasPrice: lastGasPrice, from, nonce } = txParams; const newGasPrice = customGasPrice || - bnToHex(BnMultiplyByFraction(hexToBn(lastGasPrice), 11, 10)) + bnToHex(BnMultiplyByFraction(hexToBn(lastGasPrice), 11, 10)); const newTxMeta = this.txStateManager.generateTxMeta({ txParams: { from, @@ -405,11 +405,11 @@ export default class TransactionController extends EventEmitter { loadingDefaults: false, status: TRANSACTION_STATUSES.APPROVED, type: TRANSACTION_TYPES.CANCEL, - }) + }); - this.addTx(newTxMeta) - await this.approveTransaction(newTxMeta.id) - return newTxMeta + this.addTx(newTxMeta); + await this.approveTransaction(newTxMeta.id); + return newTxMeta; } /** @@ -423,13 +423,13 @@ export default class TransactionController extends EventEmitter { * @returns {txMeta} */ async createSpeedUpTransaction(originalTxId, customGasPrice, customGasLimit) { - const originalTxMeta = this.txStateManager.getTx(originalTxId) - const { txParams } = originalTxMeta - const { gasPrice: lastGasPrice } = txParams + const originalTxMeta = this.txStateManager.getTx(originalTxId); + const { txParams } = originalTxMeta; + const { gasPrice: lastGasPrice } = txParams; const newGasPrice = customGasPrice || - bnToHex(BnMultiplyByFraction(hexToBn(lastGasPrice), 11, 10)) + bnToHex(BnMultiplyByFraction(hexToBn(lastGasPrice), 11, 10)); const newTxMeta = this.txStateManager.generateTxMeta({ txParams: { @@ -440,15 +440,15 @@ export default class TransactionController extends EventEmitter { loadingDefaults: false, status: TRANSACTION_STATUSES.APPROVED, type: TRANSACTION_TYPES.RETRY, - }) + }); if (customGasLimit) { - newTxMeta.txParams.gas = customGasLimit + newTxMeta.txParams.gas = customGasLimit; } - this.addTx(newTxMeta) - await this.approveTransaction(newTxMeta.id) - return newTxMeta + this.addTx(newTxMeta); + await this.approveTransaction(newTxMeta.id); + return newTxMeta; } /** @@ -456,7 +456,7 @@ export default class TransactionController extends EventEmitter { @param {Object} txMeta - the updated txMeta */ async updateTransaction(txMeta) { - this.txStateManager.updateTx(txMeta, 'confTx: user updated transaction') + this.txStateManager.updateTx(txMeta, 'confTx: user updated transaction'); } /** @@ -464,8 +464,8 @@ export default class TransactionController extends EventEmitter { @param {Object} txMeta */ async updateAndApproveTransaction(txMeta) { - this.txStateManager.updateTx(txMeta, 'confTx: user approved transaction') - await this.approveTransaction(txMeta.id) + this.txStateManager.updateTx(txMeta, 'confTx: user approved transaction'); + await this.approveTransaction(txMeta.id); } /** @@ -483,56 +483,56 @@ export default class TransactionController extends EventEmitter { // So that we do not increment nonce + resubmit something // that is already being incremented & signed. if (this.inProcessOfSigning.has(txId)) { - return + return; } - this.inProcessOfSigning.add(txId) - let nonceLock + this.inProcessOfSigning.add(txId); + let nonceLock; try { // approve - this.txStateManager.setTxStatusApproved(txId) + this.txStateManager.setTxStatusApproved(txId); // get next nonce - const txMeta = this.txStateManager.getTx(txId) - const fromAddress = txMeta.txParams.from + const txMeta = this.txStateManager.getTx(txId); + const fromAddress = txMeta.txParams.from; // wait for a nonce - let { customNonceValue } = txMeta - customNonceValue = Number(customNonceValue) - nonceLock = await this.nonceTracker.getNonceLock(fromAddress) + let { customNonceValue } = txMeta; + customNonceValue = Number(customNonceValue); + nonceLock = await this.nonceTracker.getNonceLock(fromAddress); // add nonce to txParams // if txMeta has lastGasPrice then it is a retry at same nonce with higher // gas price transaction and their for the nonce should not be calculated const nonce = txMeta.lastGasPrice ? txMeta.txParams.nonce - : nonceLock.nextNonce + : nonceLock.nextNonce; const customOrNonce = - customNonceValue === 0 ? customNonceValue : customNonceValue || nonce + customNonceValue === 0 ? customNonceValue : customNonceValue || nonce; - txMeta.txParams.nonce = addHexPrefix(customOrNonce.toString(16)) + txMeta.txParams.nonce = addHexPrefix(customOrNonce.toString(16)); // add nonce debugging information to txMeta - txMeta.nonceDetails = nonceLock.nonceDetails + txMeta.nonceDetails = nonceLock.nonceDetails; if (customNonceValue) { - txMeta.nonceDetails.customNonceValue = customNonceValue + txMeta.nonceDetails.customNonceValue = customNonceValue; } - this.txStateManager.updateTx(txMeta, 'transactions#approveTransaction') + this.txStateManager.updateTx(txMeta, 'transactions#approveTransaction'); // sign transaction - const rawTx = await this.signTransaction(txId) - await this.publishTransaction(txId, rawTx) + const rawTx = await this.signTransaction(txId); + await this.publishTransaction(txId, rawTx); // must set transaction to submitted/failed before releasing lock - nonceLock.releaseLock() + nonceLock.releaseLock(); } catch (err) { // this is try-catch wrapped so that we can guarantee that the nonceLock is released try { - this.txStateManager.setTxStatusFailed(txId, err) + this.txStateManager.setTxStatusFailed(txId, err); } catch (err2) { - log.error(err2) + log.error(err2); } // must set transaction to submitted/failed before releasing lock if (nonceLock) { - nonceLock.releaseLock() + nonceLock.releaseLock(); } // continue with error chain - throw err + throw err; } finally { - this.inProcessOfSigning.delete(txId) + this.inProcessOfSigning.delete(txId); } } @@ -542,30 +542,30 @@ export default class TransactionController extends EventEmitter { @returns {string} rawTx */ async signTransaction(txId) { - const txMeta = this.txStateManager.getTx(txId) + const txMeta = this.txStateManager.getTx(txId); // add network/chain id - const chainId = this.getChainId() - const txParams = { ...txMeta.txParams, chainId } + const chainId = this.getChainId(); + const txParams = { ...txMeta.txParams, chainId }; // sign tx - const fromAddress = txParams.from - const ethTx = new Transaction(txParams) - await this.signEthTx(ethTx, fromAddress) + const fromAddress = txParams.from; + const ethTx = new Transaction(txParams); + await this.signEthTx(ethTx, fromAddress); // add r,s,v values for provider request purposes see createMetamaskMiddleware // and JSON rpc standard for further explanation - txMeta.r = ethUtil.bufferToHex(ethTx.r) - txMeta.s = ethUtil.bufferToHex(ethTx.s) - txMeta.v = ethUtil.bufferToHex(ethTx.v) + txMeta.r = ethUtil.bufferToHex(ethTx.r); + txMeta.s = ethUtil.bufferToHex(ethTx.s); + txMeta.v = ethUtil.bufferToHex(ethTx.v); this.txStateManager.updateTx( txMeta, 'transactions#signTransaction: add r, s, v values', - ) + ); // set state to signed - this.txStateManager.setTxStatusSigned(txMeta.id) - const rawTx = ethUtil.bufferToHex(ethTx.serialize()) - return rawTx + this.txStateManager.setTxStatusSigned(txMeta.id); + const rawTx = ethUtil.bufferToHex(ethTx.serialize()); + return rawTx; } /** @@ -575,27 +575,27 @@ export default class TransactionController extends EventEmitter { @returns {Promise} */ async publishTransaction(txId, rawTx) { - const txMeta = this.txStateManager.getTx(txId) - txMeta.rawTx = rawTx + const txMeta = this.txStateManager.getTx(txId); + txMeta.rawTx = rawTx; if (txMeta.transactionCategory === TRANSACTION_CATEGORIES.SWAP) { - const preTxBalance = await this.query.getBalance(txMeta.txParams.from) - txMeta.preTxBalance = preTxBalance.toString(16) + const preTxBalance = await this.query.getBalance(txMeta.txParams.from); + txMeta.preTxBalance = preTxBalance.toString(16); } - this.txStateManager.updateTx(txMeta, 'transactions#publishTransaction') - let txHash + this.txStateManager.updateTx(txMeta, 'transactions#publishTransaction'); + let txHash; try { - txHash = await this.query.sendRawTransaction(rawTx) + txHash = await this.query.sendRawTransaction(rawTx); } catch (error) { if (error.message.toLowerCase().includes('known transaction')) { - txHash = ethUtil.sha3(addHexPrefix(rawTx)).toString('hex') - txHash = addHexPrefix(txHash) + txHash = ethUtil.sha3(addHexPrefix(rawTx)).toString('hex'); + txHash = addHexPrefix(txHash); } else { - throw error + throw error; } } - this.setTxHash(txId, txHash) + this.setTxHash(txId, txHash); - this.txStateManager.setTxStatusSubmitted(txId) + this.txStateManager.setTxStatusSubmitted(txId); } /** @@ -607,10 +607,10 @@ export default class TransactionController extends EventEmitter { async confirmTransaction(txId, txReceipt) { // get the txReceipt before marking the transaction confirmed // to ensure the receipt is gotten before the ui revives the tx - const txMeta = this.txStateManager.getTx(txId) + const txMeta = this.txStateManager.getTx(txId); if (!txMeta) { - return + return; } try { @@ -619,39 +619,39 @@ export default class TransactionController extends EventEmitter { const gasUsed = typeof txReceipt.gasUsed === 'string' ? txReceipt.gasUsed - : txReceipt.gasUsed.toString(16) + : txReceipt.gasUsed.toString(16); txMeta.txReceipt = { ...txReceipt, gasUsed, - } - this.txStateManager.setTxStatusConfirmed(txId) - this._markNonceDuplicatesDropped(txId) + }; + this.txStateManager.setTxStatusConfirmed(txId); + this._markNonceDuplicatesDropped(txId); this.txStateManager.updateTx( txMeta, 'transactions#confirmTransaction - add txReceipt', - ) + ); if (txMeta.transactionCategory === TRANSACTION_CATEGORIES.SWAP) { - const postTxBalance = await this.query.getBalance(txMeta.txParams.from) - const latestTxMeta = this.txStateManager.getTx(txId) + const postTxBalance = await this.query.getBalance(txMeta.txParams.from); + const latestTxMeta = this.txStateManager.getTx(txId); const approvalTxMeta = latestTxMeta.approvalTxId ? this.txStateManager.getTx(latestTxMeta.approvalTxId) - : null + : null; - latestTxMeta.postTxBalance = postTxBalance.toString(16) + latestTxMeta.postTxBalance = postTxBalance.toString(16); this.txStateManager.updateTx( latestTxMeta, 'transactions#confirmTransaction - add postTxBalance', - ) + ); - this._trackSwapsMetrics(latestTxMeta, approvalTxMeta) + this._trackSwapsMetrics(latestTxMeta, approvalTxMeta); } } catch (err) { - log.error(err) + log.error(err); } } @@ -661,7 +661,7 @@ export default class TransactionController extends EventEmitter { @returns {Promise} */ async cancelTransaction(txId) { - this.txStateManager.setTxStatusRejected(txId) + this.txStateManager.setTxStatusRejected(txId); } /** @@ -671,9 +671,9 @@ export default class TransactionController extends EventEmitter { */ setTxHash(txId, txHash) { // Add the tx hash to the persisted meta-tx object - const txMeta = this.txStateManager.getTx(txId) - txMeta.hash = txHash - this.txStateManager.updateTx(txMeta, 'transactions#setTxHash') + const txMeta = this.txStateManager.getTx(txId); + txMeta.hash = txHash; + this.txStateManager.updateTx(txMeta, 'transactions#setTxHash'); } // @@ -682,37 +682,37 @@ export default class TransactionController extends EventEmitter { /** maps methods for convenience*/ _mapMethods() { /** @returns {Object} the state in transaction controller */ - this.getState = () => this.memStore.getState() + this.getState = () => this.memStore.getState(); /** @returns {string|number} the network number stored in networkStore */ - this.getNetwork = () => this.networkStore.getState() + this.getNetwork = () => this.networkStore.getState(); /** @returns {string} the user selected address */ this.getSelectedAddress = () => - this.preferencesStore.getState().selectedAddress + this.preferencesStore.getState().selectedAddress; /** @returns {Array} transactions whos status is unapproved */ this.getUnapprovedTxCount = () => - Object.keys(this.txStateManager.getUnapprovedTxList()).length + Object.keys(this.txStateManager.getUnapprovedTxList()).length; /** @returns {number} number of transactions that have the status submitted @param {string} account - hex prefixed account */ this.getPendingTxCount = (account) => - this.txStateManager.getPendingTransactions(account).length + this.txStateManager.getPendingTransactions(account).length; /** see txStateManager */ this.getFilteredTxList = (opts) => - this.txStateManager.getFilteredTxList(opts) + this.txStateManager.getFilteredTxList(opts); } // called once on startup async _updatePendingTxsAfterFirstBlock() { // wait for first block so we know we're ready - await this.blockTracker.getLatestBlock() + await this.blockTracker.getLatestBlock(); // get status update for all pending transactions (for the current network) - await this.pendingTxTracker.updatePendingTxs() + await this.pendingTxTracker.updatePendingTxs(); } /** @@ -730,22 +730,22 @@ export default class TransactionController extends EventEmitter { .forEach((tx) => { this.addTxGasDefaults(tx) .then((txMeta) => { - txMeta.loadingDefaults = false + txMeta.loadingDefaults = false; this.txStateManager.updateTx( txMeta, 'transactions: gas estimation for tx on boot', - ) + ); }) .catch((error) => { - const txMeta = this.txStateManager.getTx(tx.id) - txMeta.loadingDefaults = false + const txMeta = this.txStateManager.getTx(tx.id); + txMeta.loadingDefaults = false; this.txStateManager.updateTx( txMeta, 'failed to estimate gas during boot cleanup.', - ) - this.txStateManager.setTxStatusFailed(txMeta.id, error) - }) - }) + ); + this.txStateManager.setTxStatusFailed(txMeta.id, error); + }); + }); this.txStateManager .getFilteredTxList({ @@ -754,9 +754,9 @@ export default class TransactionController extends EventEmitter { .forEach((txMeta) => { const txSignError = new Error( 'Transaction found as "approved" during boot - possibly stuck during signing', - ) - this.txStateManager.setTxStatusFailed(txMeta.id, txSignError) - }) + ); + this.txStateManager.setTxStatusFailed(txMeta.id, txSignError); + }); } /** @@ -767,44 +767,44 @@ export default class TransactionController extends EventEmitter { this.txStateManager.on( 'tx:status-update', this.emit.bind(this, 'tx:status-update'), - ) - this._setupBlockTrackerListener() + ); + this._setupBlockTrackerListener(); this.pendingTxTracker.on('tx:warning', (txMeta) => { this.txStateManager.updateTx( txMeta, 'transactions/pending-tx-tracker#event: tx:warning', - ) - }) + ); + }); this.pendingTxTracker.on( 'tx:failed', this.txStateManager.setTxStatusFailed.bind(this.txStateManager), - ) + ); this.pendingTxTracker.on('tx:confirmed', (txId, transactionReceipt) => this.confirmTransaction(txId, transactionReceipt), - ) + ); this.pendingTxTracker.on( 'tx:dropped', this.txStateManager.setTxStatusDropped.bind(this.txStateManager), - ) + ); this.pendingTxTracker.on('tx:block-update', (txMeta, latestBlockNumber) => { if (!txMeta.firstRetryBlockNumber) { - txMeta.firstRetryBlockNumber = latestBlockNumber + txMeta.firstRetryBlockNumber = latestBlockNumber; this.txStateManager.updateTx( txMeta, 'transactions/pending-tx-tracker#event: tx:block-update', - ) + ); } - }) + }); this.pendingTxTracker.on('tx:retry', (txMeta) => { if (!('retryCount' in txMeta)) { - txMeta.retryCount = 0 + txMeta.retryCount = 0; } - txMeta.retryCount += 1 + txMeta.retryCount += 1; this.txStateManager.updateTx( txMeta, 'transactions/pending-tx-tracker#event: tx:retry', - ) - }) + ); + }); } /** @@ -812,44 +812,44 @@ export default class TransactionController extends EventEmitter { contractDeployment, contractMethodCall */ async _determineTransactionCategory(txParams) { - const { data, to } = txParams - let name + const { data, to } = txParams; + let name; try { - name = data && hstInterface.parseTransaction({ data }).name + name = data && hstInterface.parseTransaction({ data }).name; } catch (error) { - log.debug('Failed to parse transaction data.', error, data) + log.debug('Failed to parse transaction data.', error, data); } const tokenMethodName = [ TRANSACTION_CATEGORIES.TOKEN_METHOD_APPROVE, TRANSACTION_CATEGORIES.TOKEN_METHOD_TRANSFER, TRANSACTION_CATEGORIES.TOKEN_METHOD_TRANSFER_FROM, - ].find((methodName) => methodName === name && name.toLowerCase()) + ].find((methodName) => methodName === name && name.toLowerCase()); - let result + let result; if (data && tokenMethodName) { - result = tokenMethodName + result = tokenMethodName; } else if (data && !to) { - result = TRANSACTION_CATEGORIES.DEPLOY_CONTRACT + result = TRANSACTION_CATEGORIES.DEPLOY_CONTRACT; } - let code + let code; if (!result) { try { - code = await this.query.getCode(to) + code = await this.query.getCode(to); } catch (e) { - code = null - log.warn(e) + code = null; + log.warn(e); } - const codeIsEmpty = !code || code === '0x' || code === '0x0' + const codeIsEmpty = !code || code === '0x' || code === '0x0'; result = codeIsEmpty ? TRANSACTION_CATEGORIES.SENT_ETHER - : TRANSACTION_CATEGORIES.CONTRACT_INTERACTION + : TRANSACTION_CATEGORIES.CONTRACT_INTERACTION; } - return { transactionCategory: result, getCodeResponse: code } + return { transactionCategory: result, getCodeResponse: code }; } /** @@ -860,56 +860,56 @@ export default class TransactionController extends EventEmitter { */ _markNonceDuplicatesDropped(txId) { // get the confirmed transactions nonce and from address - const txMeta = this.txStateManager.getTx(txId) - const { nonce, from } = txMeta.txParams - const sameNonceTxs = this.txStateManager.getFilteredTxList({ nonce, from }) + const txMeta = this.txStateManager.getTx(txId); + const { nonce, from } = txMeta.txParams; + const sameNonceTxs = this.txStateManager.getFilteredTxList({ nonce, from }); if (!sameNonceTxs.length) { - return + return; } // mark all same nonce transactions as dropped and give i a replacedBy hash sameNonceTxs.forEach((otherTxMeta) => { if (otherTxMeta.id === txId) { - return + return; } - otherTxMeta.replacedBy = txMeta.hash + otherTxMeta.replacedBy = txMeta.hash; this.txStateManager.updateTx( txMeta, 'transactions/pending-tx-tracker#event: tx:confirmed reference to confirmed txHash with same nonce', - ) - this.txStateManager.setTxStatusDropped(otherTxMeta.id) - }) + ); + this.txStateManager.setTxStatusDropped(otherTxMeta.id); + }); } _setupBlockTrackerListener() { - let listenersAreActive = false - const latestBlockHandler = this._onLatestBlock.bind(this) - const { blockTracker, txStateManager } = this + let listenersAreActive = false; + const latestBlockHandler = this._onLatestBlock.bind(this); + const { blockTracker, txStateManager } = this; - txStateManager.on('tx:status-update', updateSubscription) - updateSubscription() + txStateManager.on('tx:status-update', updateSubscription); + updateSubscription(); function updateSubscription() { - const pendingTxs = txStateManager.getPendingTransactions() + const pendingTxs = txStateManager.getPendingTransactions(); if (!listenersAreActive && pendingTxs.length > 0) { - blockTracker.on('latest', latestBlockHandler) - listenersAreActive = true + blockTracker.on('latest', latestBlockHandler); + listenersAreActive = true; } else if (listenersAreActive && !pendingTxs.length) { - blockTracker.removeListener('latest', latestBlockHandler) - listenersAreActive = false + blockTracker.removeListener('latest', latestBlockHandler); + listenersAreActive = false; } } } async _onLatestBlock(blockNumber) { try { - await this.pendingTxTracker.updatePendingTxs() + await this.pendingTxTracker.updatePendingTxs(); } catch (err) { - log.error(err) + log.error(err); } try { - await this.pendingTxTracker.resubmitPendingTxs(blockNumber) + await this.pendingTxTracker.resubmitPendingTxs(blockNumber); } catch (err) { - log.error(err) + log.error(err); } } @@ -917,11 +917,11 @@ export default class TransactionController extends EventEmitter { Updates the memStore in transaction controller */ _updateMemstore() { - const unapprovedTxs = this.txStateManager.getUnapprovedTxList() + const unapprovedTxs = this.txStateManager.getUnapprovedTxList(); const currentNetworkTxList = this.txStateManager.getTxList( MAX_MEMSTORE_TX_LIST_SIZE, - ) - this.memStore.updateState({ unapprovedTxs, currentNetworkTxList }) + ); + this.memStore.updateState({ unapprovedTxs, currentNetworkTxList }); } _trackSwapsMetrics(txMeta, approvalTxMeta) { @@ -931,7 +931,7 @@ export default class TransactionController extends EventEmitter { event: 'Swap Failed', sensitiveProperties: { ...txMeta.swapMetaData }, category: 'swaps', - }) + }); } else { const tokensReceived = getSwapsTokensReceivedFromTxMeta( txMeta.destinationTokenSymbol, @@ -940,12 +940,12 @@ export default class TransactionController extends EventEmitter { txMeta.txParams.from, txMeta.destinationTokenDecimals, approvalTxMeta, - ) + ); const quoteVsExecutionRatio = `${new BigNumber(tokensReceived, 10) .div(txMeta.swapMetaData.token_to_amount, 10) .times(100) - .round(2)}%` + .round(2)}%`; const estimatedVsUsedGasRatio = `${new BigNumber( txMeta.txReceipt.gasUsed, @@ -953,7 +953,7 @@ export default class TransactionController extends EventEmitter { ) .div(txMeta.swapMetaData.estimated_gas, 10) .times(100) - .round(2)}%` + .round(2)}%`; this._trackMetaMetricsEvent({ event: 'Swap Completed', @@ -964,7 +964,7 @@ export default class TransactionController extends EventEmitter { quote_vs_executionRatio: quoteVsExecutionRatio, estimated_vs_used_gasRatio: estimatedVsUsedGasRatio, }, - }) + }); } } } diff --git a/app/scripts/controllers/transactions/lib/tx-state-history-helpers.js b/app/scripts/controllers/transactions/lib/tx-state-history-helpers.js index 4a757c2ff..ea3f91bf1 100644 --- a/app/scripts/controllers/transactions/lib/tx-state-history-helpers.js +++ b/app/scripts/controllers/transactions/lib/tx-state-history-helpers.js @@ -1,5 +1,5 @@ -import jsonDiffer from 'fast-json-patch' -import { cloneDeep } from 'lodash' +import jsonDiffer from 'fast-json-patch'; +import { cloneDeep } from 'lodash'; /** converts non-initial history entries into diffs @@ -12,11 +12,11 @@ export function migrateFromSnapshotsToDiffs(longHistory) { // convert non-initial history entries into diffs .map((entry, index) => { if (index === 0) { - return entry + return entry; } - return generateHistoryEntry(longHistory[index - 1], entry) + return generateHistoryEntry(longHistory[index - 1], entry); }) - ) + ); } /** @@ -32,16 +32,16 @@ export function migrateFromSnapshotsToDiffs(longHistory) { @returns {Array} */ export function generateHistoryEntry(previousState, newState, note) { - const entry = jsonDiffer.compare(previousState, newState) + const entry = jsonDiffer.compare(previousState, newState); // Add a note to the first op, since it breaks if we append it to the entry if (entry[0]) { if (note) { - entry[0].note = note + entry[0].note = note; } - entry[0].timestamp = Date.now() + entry[0].timestamp = Date.now(); } - return entry + return entry; } /** @@ -49,10 +49,10 @@ export function generateHistoryEntry(previousState, newState, note) { @returns {Object} */ export function replayHistory(_shortHistory) { - const shortHistory = cloneDeep(_shortHistory) + const shortHistory = cloneDeep(_shortHistory); return shortHistory.reduce( (val, entry) => jsonDiffer.applyPatch(val, entry).newDocument, - ) + ); } /** @@ -61,7 +61,7 @@ export function replayHistory(_shortHistory) { * @returns {Object} a deep clone without history */ export function snapshotFromTxMeta(txMeta) { - const shallow = { ...txMeta } - delete shallow.history - return cloneDeep(shallow) + const shallow = { ...txMeta }; + delete shallow.history; + return cloneDeep(shallow); } diff --git a/app/scripts/controllers/transactions/lib/util.js b/app/scripts/controllers/transactions/lib/util.js index fbb975c83..f1cb1f661 100644 --- a/app/scripts/controllers/transactions/lib/util.js +++ b/app/scripts/controllers/transactions/lib/util.js @@ -1,7 +1,7 @@ -import { isValidAddress } from 'ethereumjs-util' -import { ethErrors } from 'eth-rpc-errors' -import { addHexPrefix } from '../../../lib/util' -import { TRANSACTION_STATUSES } from '../../../../../shared/constants/transaction' +import { isValidAddress } from 'ethereumjs-util'; +import { ethErrors } from 'eth-rpc-errors'; +import { addHexPrefix } from '../../../lib/util'; +import { TRANSACTION_STATUSES } from '../../../../../shared/constants/transaction'; const normalizers = { from: (from) => addHexPrefix(from), @@ -12,7 +12,7 @@ const normalizers = { data: (data) => addHexPrefix(data), gas: (gas) => addHexPrefix(gas), gasPrice: (gasPrice) => addHexPrefix(gasPrice), -} +}; /** * Normalizes the given txParams @@ -23,13 +23,13 @@ const normalizers = { */ export function normalizeTxParams(txParams, lowerCase = true) { // apply only keys in the normalizers - const normalizedTxParams = {} + const normalizedTxParams = {}; for (const key in normalizers) { if (txParams[key]) { - normalizedTxParams[key] = normalizers[key](txParams[key], lowerCase) + normalizedTxParams[key] = normalizers[key](txParams[key], lowerCase); } } - return normalizedTxParams + return normalizedTxParams; } /** @@ -41,28 +41,28 @@ export function validateTxParams(txParams) { if (!txParams || typeof txParams !== 'object' || Array.isArray(txParams)) { throw ethErrors.rpc.invalidParams( 'Invalid transaction params: must be an object.', - ) + ); } if (!txParams.to && !txParams.data) { throw ethErrors.rpc.invalidParams( 'Invalid transaction params: must specify "data" for contract deployments, or "to" (and optionally "data") for all other types of transactions.', - ) + ); } - validateFrom(txParams) - validateRecipient(txParams) + validateFrom(txParams); + validateRecipient(txParams); if ('value' in txParams) { - const value = txParams.value.toString() + const value = txParams.value.toString(); if (value.includes('-')) { throw ethErrors.rpc.invalidParams( `Invalid transaction value "${txParams.value}": not a positive number.`, - ) + ); } if (value.includes('.')) { throw ethErrors.rpc.invalidParams( `Invalid transaction value of "${txParams.value}": number must be in wei.`, - ) + ); } } } @@ -76,10 +76,10 @@ export function validateFrom(txParams) { if (!(typeof txParams.from === 'string')) { throw ethErrors.rpc.invalidParams( `Invalid "from" address "${txParams.from}": not a string.`, - ) + ); } if (!isValidAddress(txParams.from)) { - throw ethErrors.rpc.invalidParams('Invalid "from" address.') + throw ethErrors.rpc.invalidParams('Invalid "from" address.'); } } @@ -92,14 +92,14 @@ export function validateFrom(txParams) { export function validateRecipient(txParams) { if (txParams.to === '0x' || txParams.to === null) { if (txParams.data) { - delete txParams.to + delete txParams.to; } else { - throw ethErrors.rpc.invalidParams('Invalid "to" address.') + throw ethErrors.rpc.invalidParams('Invalid "to" address.'); } } else if (txParams.to !== undefined && !isValidAddress(txParams.to)) { - throw ethErrors.rpc.invalidParams('Invalid "to" address.') + throw ethErrors.rpc.invalidParams('Invalid "to" address.'); } - return txParams + return txParams; } /** @@ -112,5 +112,5 @@ export function getFinalStates() { TRANSACTION_STATUSES.CONFIRMED, // the tx has been included in a block. TRANSACTION_STATUSES.FAILED, // the tx failed for some reason, included on tx data. TRANSACTION_STATUSES.DROPPED, // the tx nonce was already used - ] + ]; } diff --git a/app/scripts/controllers/transactions/pending-tx-tracker.js b/app/scripts/controllers/transactions/pending-tx-tracker.js index 2194ca495..cb0067445 100644 --- a/app/scripts/controllers/transactions/pending-tx-tracker.js +++ b/app/scripts/controllers/transactions/pending-tx-tracker.js @@ -1,7 +1,7 @@ -import EventEmitter from 'safe-event-emitter' -import log from 'loglevel' -import EthQuery from 'ethjs-query' -import { TRANSACTION_STATUSES } from '../../../../shared/constants/transaction' +import EventEmitter from 'safe-event-emitter'; +import log from 'loglevel'; +import EthQuery from 'ethjs-query'; +import { TRANSACTION_STATUSES } from '../../../../shared/constants/transaction'; /** @@ -27,7 +27,7 @@ export default class PendingTransactionTracker extends EventEmitter { * * @type {number} */ - DROPPED_BUFFER_COUNT = 3 + DROPPED_BUFFER_COUNT = 3; /** * A map of transaction hashes to the number of blocks we've seen @@ -35,17 +35,17 @@ export default class PendingTransactionTracker extends EventEmitter { * * @type {Map} */ - droppedBlocksBufferByHash = new Map() + droppedBlocksBufferByHash = new Map(); constructor(config) { - super() - this.query = config.query || new EthQuery(config.provider) - this.nonceTracker = config.nonceTracker - this.getPendingTransactions = config.getPendingTransactions - this.getCompletedTransactions = config.getCompletedTransactions - this.publishTransaction = config.publishTransaction - this.approveTransaction = config.approveTransaction - this.confirmTransaction = config.confirmTransaction + super(); + this.query = config.query || new EthQuery(config.provider); + this.nonceTracker = config.nonceTracker; + this.getPendingTransactions = config.getPendingTransactions; + this.getCompletedTransactions = config.getCompletedTransactions; + this.publishTransaction = config.publishTransaction; + this.approveTransaction = config.approveTransaction; + this.confirmTransaction = config.confirmTransaction; } /** @@ -53,19 +53,19 @@ export default class PendingTransactionTracker extends EventEmitter { */ async updatePendingTxs() { // in order to keep the nonceTracker accurate we block it while updating pending transactions - const nonceGlobalLock = await this.nonceTracker.getGlobalLock() + const nonceGlobalLock = await this.nonceTracker.getGlobalLock(); try { - const pendingTxs = this.getPendingTransactions() + const pendingTxs = this.getPendingTransactions(); await Promise.all( pendingTxs.map((txMeta) => this._checkPendingTx(txMeta)), - ) + ); } catch (err) { log.error( 'PendingTransactionTracker - Error updating pending transactions', - ) - log.error(err) + ); + log.error(err); } - nonceGlobalLock.releaseLock() + nonceGlobalLock.releaseLock(); } /** @@ -75,16 +75,16 @@ export default class PendingTransactionTracker extends EventEmitter { * @returns {Promise} */ async resubmitPendingTxs(blockNumber) { - const pending = this.getPendingTransactions() + const pending = this.getPendingTransactions(); if (!pending.length) { - return + return; } for (const txMeta of pending) { try { - await this._resubmitTx(txMeta, blockNumber) + await this._resubmitTx(txMeta, blockNumber); } catch (err) { const errorMessage = - err.value?.message?.toLowerCase() || err.message.toLowerCase() + err.value?.message?.toLowerCase() || err.message.toLowerCase(); const isKnownTx = // geth errorMessage.includes('replacement transaction underpriced') || @@ -96,17 +96,17 @@ export default class PendingTransactionTracker extends EventEmitter { ) || // other errorMessage.includes('gateway timeout') || - errorMessage.includes('nonce too low') + errorMessage.includes('nonce too low'); // ignore resubmit warnings, return early if (isKnownTx) { - return + return; } // encountered real error - transition to error state txMeta.warning = { error: errorMessage, message: 'There was an error when resubmitting this transaction.', - } - this.emit('tx:warning', txMeta, err) + }; + this.emit('tx:warning', txMeta, err); } } } @@ -125,33 +125,33 @@ export default class PendingTransactionTracker extends EventEmitter { */ async _resubmitTx(txMeta, latestBlockNumber) { if (!txMeta.firstRetryBlockNumber) { - this.emit('tx:block-update', txMeta, latestBlockNumber) + this.emit('tx:block-update', txMeta, latestBlockNumber); } const firstRetryBlockNumber = - txMeta.firstRetryBlockNumber || latestBlockNumber + txMeta.firstRetryBlockNumber || latestBlockNumber; const txBlockDistance = Number.parseInt(latestBlockNumber, 16) - - Number.parseInt(firstRetryBlockNumber, 16) + Number.parseInt(firstRetryBlockNumber, 16); - const retryCount = txMeta.retryCount || 0 + const retryCount = txMeta.retryCount || 0; // Exponential backoff to limit retries at publishing if (txBlockDistance <= Math.pow(2, retryCount) - 1) { - return undefined + return undefined; } // Only auto-submit already-signed txs: if (!('rawTx' in txMeta)) { - return this.approveTransaction(txMeta.id) + return this.approveTransaction(txMeta.id); } - const { rawTx } = txMeta - const txHash = await this.publishTransaction(rawTx) + const { rawTx } = txMeta; + const txHash = await this.publishTransaction(rawTx); // Increment successful tries: - this.emit('tx:retry', txMeta) - return txHash + this.emit('tx:retry', txMeta); + return txHash; } /** @@ -165,12 +165,12 @@ export default class PendingTransactionTracker extends EventEmitter { * @private */ async _checkPendingTx(txMeta) { - const txHash = txMeta.hash - const txId = txMeta.id + const txHash = txMeta.hash; + const txId = txMeta.id; // Only check submitted txs if (txMeta.status !== TRANSACTION_STATUSES.SUBMITTED) { - return + return; } // extra check in case there was an uncaught error during the @@ -178,35 +178,35 @@ export default class PendingTransactionTracker extends EventEmitter { if (!txHash) { const noTxHashErr = new Error( 'We had an error while submitting this transaction, please try again.', - ) - noTxHashErr.name = 'NoTxHashError' - this.emit('tx:failed', txId, noTxHashErr) + ); + noTxHashErr.name = 'NoTxHashError'; + this.emit('tx:failed', txId, noTxHashErr); - return + return; } if (await this._checkIfNonceIsTaken(txMeta)) { - this.emit('tx:dropped', txId) - return + this.emit('tx:dropped', txId); + return; } try { - const transactionReceipt = await this.query.getTransactionReceipt(txHash) + const transactionReceipt = await this.query.getTransactionReceipt(txHash); if (transactionReceipt?.blockNumber) { - this.emit('tx:confirmed', txId, transactionReceipt) - return + this.emit('tx:confirmed', txId, transactionReceipt); + return; } } catch (err) { txMeta.warning = { error: err.message, message: 'There was a problem loading this transaction.', - } - this.emit('tx:warning', txMeta, err) - return + }; + this.emit('tx:warning', txMeta, err); + return; } if (await this._checkIfTxWasDropped(txMeta)) { - this.emit('tx:dropped', txId) + this.emit('tx:dropped', txId); } } @@ -221,26 +221,26 @@ export default class PendingTransactionTracker extends EventEmitter { const { hash: txHash, txParams: { nonce, from }, - } = txMeta - const networkNextNonce = await this.query.getTransactionCount(from) + } = txMeta; + const networkNextNonce = await this.query.getTransactionCount(from); if (parseInt(nonce, 16) >= networkNextNonce.toNumber()) { - return false + return false; } if (!this.droppedBlocksBufferByHash.has(txHash)) { - this.droppedBlocksBufferByHash.set(txHash, 0) + this.droppedBlocksBufferByHash.set(txHash, 0); } - const currentBlockBuffer = this.droppedBlocksBufferByHash.get(txHash) + const currentBlockBuffer = this.droppedBlocksBufferByHash.get(txHash); if (currentBlockBuffer < this.DROPPED_BUFFER_COUNT) { - this.droppedBlocksBufferByHash.set(txHash, currentBlockBuffer + 1) - return false + this.droppedBlocksBufferByHash.set(txHash, currentBlockBuffer + 1); + return false; } - this.droppedBlocksBufferByHash.delete(txHash) - return true + this.droppedBlocksBufferByHash.delete(txHash); + return true; } /** @@ -250,8 +250,8 @@ export default class PendingTransactionTracker extends EventEmitter { * @private */ async _checkIfNonceIsTaken(txMeta) { - const address = txMeta.txParams.from - const completed = this.getCompletedTransactions(address) + const address = txMeta.txParams.from; + const completed = this.getCompletedTransactions(address); return completed.some( // This is called while the transaction is in-flight, so it is possible that the // list of completed transactions now includes the transaction we were looking at @@ -259,6 +259,6 @@ export default class PendingTransactionTracker extends EventEmitter { (other) => !(other.id === txMeta.id) && other.txParams.nonce === txMeta.txParams.nonce, - ) + ); } } diff --git a/app/scripts/controllers/transactions/tx-gas-utils.js b/app/scripts/controllers/transactions/tx-gas-utils.js index cf75d8919..75eb60d83 100644 --- a/app/scripts/controllers/transactions/tx-gas-utils.js +++ b/app/scripts/controllers/transactions/tx-gas-utils.js @@ -1,8 +1,8 @@ -import EthQuery from 'ethjs-query' -import log from 'loglevel' -import ethUtil from 'ethereumjs-util' -import { cloneDeep } from 'lodash' -import { hexToBn, BnMultiplyByFraction, bnToHex } from '../../lib/util' +import EthQuery from 'ethjs-query'; +import log from 'loglevel'; +import ethUtil from 'ethereumjs-util'; +import { cloneDeep } from 'lodash'; +import { hexToBn, BnMultiplyByFraction, bnToHex } from '../../lib/util'; /** * Result of gas analysis, including either a gas estimate for a successful analysis, or @@ -22,7 +22,7 @@ and used to do things like calculate gas of a tx. export default class TxGasUtil { constructor(provider) { - this.query = new EthQuery(provider) + this.query = new EthQuery(provider); } /** @@ -30,25 +30,25 @@ export default class TxGasUtil { @returns {GasAnalysisResult} The result of the gas analysis */ async analyzeGasUsage(txMeta) { - const block = await this.query.getBlockByNumber('latest', false) + const block = await this.query.getBlockByNumber('latest', false); // fallback to block gasLimit - const blockGasLimitBN = hexToBn(block.gasLimit) - const saferGasLimitBN = BnMultiplyByFraction(blockGasLimitBN, 19, 20) - let estimatedGasHex = bnToHex(saferGasLimitBN) - let simulationFails + const blockGasLimitBN = hexToBn(block.gasLimit); + const saferGasLimitBN = BnMultiplyByFraction(blockGasLimitBN, 19, 20); + let estimatedGasHex = bnToHex(saferGasLimitBN); + let simulationFails; try { - estimatedGasHex = await this.estimateTxGas(txMeta) + estimatedGasHex = await this.estimateTxGas(txMeta); } catch (error) { - log.warn(error) + log.warn(error); simulationFails = { reason: error.message, errorKey: error.errorKey, debug: { blockNumber: block.number, blockGasLimit: block.gasLimit }, - } + }; } - return { blockGasLimit: block.gasLimit, estimatedGasHex, simulationFails } + return { blockGasLimit: block.gasLimit, estimatedGasHex, simulationFails }; } /** @@ -57,16 +57,16 @@ export default class TxGasUtil { @returns {string} the estimated gas limit as a hex string */ async estimateTxGas(txMeta) { - const txParams = cloneDeep(txMeta.txParams) + const txParams = cloneDeep(txMeta.txParams); // `eth_estimateGas` can fail if the user has insufficient balance for the // value being sent, or for the gas cost. We don't want to check their // balance here, we just want the gas estimate. The gas price is removed // to skip those balance checks. We check balance elsewhere. - delete txParams.gasPrice + delete txParams.gasPrice; // estimate tx gas requirements - return await this.query.estimateGas(txParams) + return await this.query.estimateGas(txParams); } /** @@ -77,21 +77,21 @@ export default class TxGasUtil { @returns {string} the buffered gas limit as a hex string */ addGasBuffer(initialGasLimitHex, blockGasLimitHex, multiplier = 1.5) { - const initialGasLimitBn = hexToBn(initialGasLimitHex) - const blockGasLimitBn = hexToBn(blockGasLimitHex) - const upperGasLimitBn = blockGasLimitBn.muln(0.9) - const bufferedGasLimitBn = initialGasLimitBn.muln(multiplier) + const initialGasLimitBn = hexToBn(initialGasLimitHex); + const blockGasLimitBn = hexToBn(blockGasLimitHex); + const upperGasLimitBn = blockGasLimitBn.muln(0.9); + const bufferedGasLimitBn = initialGasLimitBn.muln(multiplier); // if initialGasLimit is above blockGasLimit, dont modify it if (initialGasLimitBn.gt(upperGasLimitBn)) { - return bnToHex(initialGasLimitBn) + return bnToHex(initialGasLimitBn); } // if bufferedGasLimit is below blockGasLimit, use bufferedGasLimit if (bufferedGasLimitBn.lt(upperGasLimitBn)) { - return bnToHex(bufferedGasLimitBn) + return bnToHex(bufferedGasLimitBn); } // otherwise use blockGasLimit - return bnToHex(upperGasLimitBn) + return bnToHex(upperGasLimitBn); } async getBufferedGasLimit(txMeta, multiplier) { @@ -99,14 +99,14 @@ export default class TxGasUtil { blockGasLimit, estimatedGasHex, simulationFails, - } = await this.analyzeGasUsage(txMeta) + } = await this.analyzeGasUsage(txMeta); // add additional gas buffer to our estimation for safety const gasLimit = this.addGasBuffer( ethUtil.addHexPrefix(estimatedGasHex), blockGasLimit, multiplier, - ) - return { gasLimit, simulationFails } + ); + return { gasLimit, simulationFails }; } } diff --git a/app/scripts/controllers/transactions/tx-state-manager.js b/app/scripts/controllers/transactions/tx-state-manager.js index 0c94bd270..492ea4dde 100644 --- a/app/scripts/controllers/transactions/tx-state-manager.js +++ b/app/scripts/controllers/transactions/tx-state-manager.js @@ -1,14 +1,14 @@ -import EventEmitter from 'safe-event-emitter' -import { ObservableStore } from '@metamask/obs-store' -import log from 'loglevel' -import createId from '../../lib/random-id' -import { TRANSACTION_STATUSES } from '../../../../shared/constants/transaction' +import EventEmitter from 'safe-event-emitter'; +import { ObservableStore } from '@metamask/obs-store'; +import log from 'loglevel'; +import createId from '../../lib/random-id'; +import { TRANSACTION_STATUSES } from '../../../../shared/constants/transaction'; import { generateHistoryEntry, replayHistory, snapshotFromTxMeta, -} from './lib/tx-state-history-helpers' -import { getFinalStates, normalizeTxParams } from './lib/util' +} from './lib/tx-state-history-helpers'; +import { getFinalStates, normalizeTxParams } from './lib/util'; /** * TransactionStatuses reimported from the shared transaction constants file @@ -28,11 +28,11 @@ import { getFinalStates, normalizeTxParams } from './lib/util' */ export default class TransactionStateManager extends EventEmitter { constructor({ initState, txHistoryLimit, getNetwork }) { - super() + super(); - this.store = new ObservableStore({ transactions: [], ...initState }) - this.txHistoryLimit = txHistoryLimit - this.getNetwork = getNetwork + this.store = new ObservableStore({ transactions: [], ...initState }); + this.txHistoryLimit = txHistoryLimit; + this.getNetwork = getNetwork; } /** @@ -40,9 +40,9 @@ export default class TransactionStateManager extends EventEmitter { * @returns {txMeta} the default txMeta object */ generateTxMeta(opts) { - const netId = this.getNetwork() + const netId = this.getNetwork(); if (netId === 'loading') { - throw new Error('MetaMask is having trouble connecting to the network') + throw new Error('MetaMask is having trouble connecting to the network'); } return { id: createId(), @@ -51,7 +51,7 @@ export default class TransactionStateManager extends EventEmitter { metamaskNetworkId: netId, loadingDefaults: true, ...opts, - } + }; } /** @@ -63,38 +63,38 @@ export default class TransactionStateManager extends EventEmitter { * @returns {Object[]} The {@code txMeta}s, filtered to the current network */ getTxList(limit) { - const network = this.getNetwork() - const fullTxList = this.getFullTxList() + const network = this.getNetwork(); + const fullTxList = this.getFullTxList(); - const nonces = new Set() - const txs = [] + const nonces = new Set(); + const txs = []; for (let i = fullTxList.length - 1; i > -1; i--) { - const txMeta = fullTxList[i] + const txMeta = fullTxList[i]; if (txMeta.metamaskNetworkId !== network) { - continue + continue; } if (limit !== undefined) { - const { nonce } = txMeta.txParams + const { nonce } = txMeta.txParams; if (!nonces.has(nonce)) { if (nonces.size < limit) { - nonces.add(nonce) + nonces.add(nonce); } else { - continue + continue; } } } - txs.unshift(txMeta) + txs.unshift(txMeta); } - return txs + return txs; } /** * @returns {Array} of all the txMetas in store */ getFullTxList() { - return this.store.getState().transactions + return this.store.getState().transactions; } /** @@ -104,11 +104,11 @@ export default class TransactionStateManager extends EventEmitter { const txList = this.getTxsByMetaData( 'status', TRANSACTION_STATUSES.UNAPPROVED, - ) + ); return txList.reduce((result, tx) => { - result[tx.id] = tx - return result - }, {}) + result[tx.id] = tx; + return result; + }, {}); } /** @@ -117,11 +117,11 @@ export default class TransactionStateManager extends EventEmitter { * returns all txMetas with approved statuses for the current network */ getApprovedTransactions(address) { - const opts = { status: TRANSACTION_STATUSES.APPROVED } + const opts = { status: TRANSACTION_STATUSES.APPROVED }; if (address) { - opts.from = address + opts.from = address; } - return this.getFilteredTxList(opts) + return this.getFilteredTxList(opts); } /** @@ -130,11 +130,11 @@ export default class TransactionStateManager extends EventEmitter { * returns all txMetas with submitted statuses for the current network */ getPendingTransactions(address) { - const opts = { status: TRANSACTION_STATUSES.SUBMITTED } + const opts = { status: TRANSACTION_STATUSES.SUBMITTED }; if (address) { - opts.from = address + opts.from = address; } - return this.getFilteredTxList(opts) + return this.getFilteredTxList(opts); } /** @@ -143,11 +143,11 @@ export default class TransactionStateManager extends EventEmitter { returns all txMetas who's status is confirmed for the current network */ getConfirmedTransactions(address) { - const opts = { status: TRANSACTION_STATUSES.CONFIRMED } + const opts = { status: TRANSACTION_STATUSES.CONFIRMED }; if (address) { - opts.from = address + opts.from = address; } - return this.getFilteredTxList(opts) + return this.getFilteredTxList(opts); } /** @@ -162,24 +162,24 @@ export default class TransactionStateManager extends EventEmitter { addTx(txMeta) { // normalize and validate txParams if present if (txMeta.txParams) { - txMeta.txParams = this.normalizeAndValidateTxParams(txMeta.txParams) + txMeta.txParams = this.normalizeAndValidateTxParams(txMeta.txParams); } this.once(`${txMeta.id}:signed`, () => { - this.removeAllListeners(`${txMeta.id}:rejected`) - }) + this.removeAllListeners(`${txMeta.id}:rejected`); + }); this.once(`${txMeta.id}:rejected`, () => { - this.removeAllListeners(`${txMeta.id}:signed`) - }) + this.removeAllListeners(`${txMeta.id}:signed`); + }); // initialize history - txMeta.history = [] + txMeta.history = []; // capture initial snapshot of txMeta for history - const snapshot = snapshotFromTxMeta(txMeta) - txMeta.history.push(snapshot) + const snapshot = snapshotFromTxMeta(txMeta); + txMeta.history.push(snapshot); - const transactions = this.getFullTxList() - const txCount = transactions.length - const { txHistoryLimit } = this + const transactions = this.getFullTxList(); + const txCount = transactions.length; + const { txHistoryLimit } = this; // checks if the length of the tx history is // longer then desired persistence limit @@ -188,21 +188,21 @@ export default class TransactionStateManager extends EventEmitter { // not tx's that are pending or unapproved if (txCount > txHistoryLimit - 1) { const index = transactions.findIndex((metaTx) => { - return getFinalStates().includes(metaTx.status) - }) + return getFinalStates().includes(metaTx.status); + }); if (index !== -1) { - transactions.splice(index, 1) + transactions.splice(index, 1); } } const newTxIndex = transactions.findIndex( (currentTxMeta) => currentTxMeta.time > txMeta.time, - ) + ); newTxIndex === -1 ? transactions.push(txMeta) - : transactions.splice(newTxIndex, 0, txMeta) - this._saveTxList(transactions) - return txMeta + : transactions.splice(newTxIndex, 0, txMeta); + this._saveTxList(transactions); + return txMeta; } /** @@ -211,8 +211,8 @@ export default class TransactionStateManager extends EventEmitter { * for the network returns undefined */ getTx(txId) { - const txMeta = this.getTxsByMetaData('id', txId)[0] - return txMeta + const txMeta = this.getTxsByMetaData('id', txId)[0]; + return txMeta; } /** @@ -223,25 +223,25 @@ export default class TransactionStateManager extends EventEmitter { updateTx(txMeta, note) { // normalize and validate txParams if present if (txMeta.txParams) { - txMeta.txParams = this.normalizeAndValidateTxParams(txMeta.txParams) + txMeta.txParams = this.normalizeAndValidateTxParams(txMeta.txParams); } // create txMeta snapshot for history - const currentState = snapshotFromTxMeta(txMeta) + const currentState = snapshotFromTxMeta(txMeta); // recover previous tx state obj - const previousState = replayHistory(txMeta.history) + const previousState = replayHistory(txMeta.history); // generate history entry and add to history - const entry = generateHistoryEntry(previousState, currentState, note) + const entry = generateHistoryEntry(previousState, currentState, note); if (entry.length) { - txMeta.history.push(entry) + txMeta.history.push(entry); } // commit txMeta to state - const txId = txMeta.id - const txList = this.getFullTxList() - const index = txList.findIndex((txData) => txData.id === txId) - txList[index] = txMeta - this._saveTxList(txList) + const txId = txMeta.id; + const txList = this.getFullTxList(); + const index = txList.findIndex((txData) => txData.id === txId); + txList[index] = txMeta; + this._saveTxList(txList); } /** @@ -251,9 +251,9 @@ export default class TransactionStateManager extends EventEmitter { * @param {Object} txParams - the updated txParams */ updateTxParams(txId, txParams) { - const txMeta = this.getTx(txId) - txMeta.txParams = { ...txMeta.txParams, ...txParams } - this.updateTx(txMeta, `txStateManager#updateTxParams`) + const txMeta = this.getTx(txId); + txMeta.txParams = { ...txMeta.txParams, ...txParams }; + this.updateTx(txMeta, `txStateManager#updateTxParams`); } /** @@ -262,12 +262,12 @@ export default class TransactionStateManager extends EventEmitter { */ normalizeAndValidateTxParams(txParams) { if (typeof txParams.data === 'undefined') { - delete txParams.data + delete txParams.data; } // eslint-disable-next-line no-param-reassign - txParams = normalizeTxParams(txParams, false) - this.validateTxParams(txParams) - return txParams + txParams = normalizeTxParams(txParams, false); + this.validateTxParams(txParams); + return txParams; } /** @@ -276,25 +276,25 @@ export default class TransactionStateManager extends EventEmitter { */ validateTxParams(txParams) { Object.keys(txParams).forEach((key) => { - const value = txParams[key] + const value = txParams[key]; // validate types switch (key) { case 'chainId': if (typeof value !== 'number' && typeof value !== 'string') { throw new Error( `${key} in txParams is not a Number or hex string. got: (${value})`, - ) + ); } - break + break; default: if (typeof value !== 'string') { throw new Error( `${key} in txParams is not a string. got: (${value})`, - ) + ); } - break + break; } - }) + }); } /** @@ -326,11 +326,11 @@ export default class TransactionStateManager extends EventEmitter { and that have been 'confirmed' */ getFilteredTxList(opts, initialList) { - let filteredTxList = initialList + let filteredTxList = initialList; Object.keys(opts).forEach((key) => { - filteredTxList = this.getTxsByMetaData(key, opts[key], filteredTxList) - }) - return filteredTxList + filteredTxList = this.getTxsByMetaData(key, opts[key], filteredTxList); + }); + return filteredTxList; } /** @@ -341,14 +341,14 @@ export default class TransactionStateManager extends EventEmitter { * @returns {Array} a list of txMetas who matches the search params */ getTxsByMetaData(key, value, txList = this.getTxList()) { - const filter = typeof value === 'function' ? value : (v) => v === value + const filter = typeof value === 'function' ? value : (v) => v === value; return txList.filter((txMeta) => { if (key in txMeta.txParams) { - return filter(txMeta.txParams[key]) + return filter(txMeta.txParams[key]); } - return filter(txMeta[key]) - }) + return filter(txMeta[key]); + }); } // get::set status @@ -358,8 +358,8 @@ export default class TransactionStateManager extends EventEmitter { * @returns {string} the status of the tx. */ getTxStatus(txId) { - const txMeta = this.getTx(txId) - return txMeta.status + const txMeta = this.getTx(txId); + return txMeta.status; } /** @@ -367,8 +367,8 @@ export default class TransactionStateManager extends EventEmitter { * @param {number} txId - the txMeta Id */ setTxStatusRejected(txId) { - this._setTxStatus(txId, 'rejected') - this._removeTx(txId) + this._setTxStatus(txId, 'rejected'); + this._removeTx(txId); } /** @@ -376,7 +376,7 @@ export default class TransactionStateManager extends EventEmitter { * @param {number} txId - the txMeta Id */ setTxStatusUnapproved(txId) { - this._setTxStatus(txId, TRANSACTION_STATUSES.UNAPPROVED) + this._setTxStatus(txId, TRANSACTION_STATUSES.UNAPPROVED); } /** @@ -384,7 +384,7 @@ export default class TransactionStateManager extends EventEmitter { * @param {number} txId - the txMeta Id */ setTxStatusApproved(txId) { - this._setTxStatus(txId, TRANSACTION_STATUSES.APPROVED) + this._setTxStatus(txId, TRANSACTION_STATUSES.APPROVED); } /** @@ -392,7 +392,7 @@ export default class TransactionStateManager extends EventEmitter { * @param {number} txId - the txMeta Id */ setTxStatusSigned(txId) { - this._setTxStatus(txId, TRANSACTION_STATUSES.SIGNED) + this._setTxStatus(txId, TRANSACTION_STATUSES.SIGNED); } /** @@ -401,10 +401,10 @@ export default class TransactionStateManager extends EventEmitter { * @param {number} txId - the txMeta Id */ setTxStatusSubmitted(txId) { - const txMeta = this.getTx(txId) - txMeta.submittedTime = new Date().getTime() - this.updateTx(txMeta, 'txStateManager - add submitted time stamp') - this._setTxStatus(txId, TRANSACTION_STATUSES.SUBMITTED) + const txMeta = this.getTx(txId); + txMeta.submittedTime = new Date().getTime(); + this.updateTx(txMeta, 'txStateManager - add submitted time stamp'); + this._setTxStatus(txId, TRANSACTION_STATUSES.SUBMITTED); } /** @@ -412,7 +412,7 @@ export default class TransactionStateManager extends EventEmitter { * @param {number} txId - the txMeta Id */ setTxStatusConfirmed(txId) { - this._setTxStatus(txId, TRANSACTION_STATUSES.CONFIRMED) + this._setTxStatus(txId, TRANSACTION_STATUSES.CONFIRMED); } /** @@ -420,7 +420,7 @@ export default class TransactionStateManager extends EventEmitter { * @param {number} txId - the txMeta Id */ setTxStatusDropped(txId) { - this._setTxStatus(txId, TRANSACTION_STATUSES.DROPPED) + this._setTxStatus(txId, TRANSACTION_STATUSES.DROPPED); } /** @@ -429,16 +429,16 @@ export default class TransactionStateManager extends EventEmitter { * @param {erroObject} err - error object */ setTxStatusFailed(txId, err) { - const error = err || new Error('Internal metamask failure') + const error = err || new Error('Internal metamask failure'); - const txMeta = this.getTx(txId) + const txMeta = this.getTx(txId); txMeta.err = { message: error.toString(), rpc: error.value, stack: error.stack, - } - this.updateTx(txMeta, 'transactions:tx-state-manager#fail - add error') - this._setTxStatus(txId, TRANSACTION_STATUSES.FAILED) + }; + this.updateTx(txMeta, 'transactions:tx-state-manager#fail - add error'); + this._setTxStatus(txId, TRANSACTION_STATUSES.FAILED); } /** @@ -449,8 +449,8 @@ export default class TransactionStateManager extends EventEmitter { */ wipeTransactions(address) { // network only tx - const txs = this.getFullTxList() - const network = this.getNetwork() + const txs = this.getFullTxList(); + const network = this.getNetwork(); // Filter out the ones from the current account and network const otherAccountTxs = txs.filter( @@ -459,10 +459,10 @@ export default class TransactionStateManager extends EventEmitter { txMeta.txParams.from === address && txMeta.metamaskNetworkId === network ), - ) + ); // Update state - this._saveTxList(otherAccountTxs) + this._saveTxList(otherAccountTxs); } // @@ -477,17 +477,17 @@ export default class TransactionStateManager extends EventEmitter { * @emits update:badge */ _setTxStatus(txId, status) { - const txMeta = this.getTx(txId) + const txMeta = this.getTx(txId); if (!txMeta) { - return + return; } - txMeta.status = status + txMeta.status = status; try { - this.updateTx(txMeta, `txStateManager: setting status to ${status}`) - this.emit(`${txMeta.id}:${status}`, txId) - this.emit(`tx:status-update`, txId, status) + this.updateTx(txMeta, `txStateManager: setting status to ${status}`); + this.emit(`${txMeta.id}:${status}`, txId); + this.emit(`tx:status-update`, txId, status); if ( [ TRANSACTION_STATUSES.SUBMITTED, @@ -495,11 +495,11 @@ export default class TransactionStateManager extends EventEmitter { TRANSACTION_STATUSES.FAILED, ].includes(status) ) { - this.emit(`${txMeta.id}:finished`, txMeta) + this.emit(`${txMeta.id}:finished`, txMeta); } - this.emit('update:badge') + this.emit('update:badge'); } catch (error) { - log.error(error) + log.error(error); } } @@ -508,22 +508,22 @@ export default class TransactionStateManager extends EventEmitter { * @param {Array} transactions - the list of transactions to save */ _saveTxList(transactions) { - this.store.updateState({ transactions }) + this.store.updateState({ transactions }); } _removeTx(txId) { - const transactionList = this.getFullTxList() - this._saveTxList(transactionList.filter((txMeta) => txMeta.id !== txId)) + const transactionList = this.getFullTxList(); + this._saveTxList(transactionList.filter((txMeta) => txMeta.id !== txId)); } /** * Filters out the unapproved transactions */ clearUnapprovedTxs() { - const transactions = this.getFullTxList() + const transactions = this.getFullTxList(); const nonUnapprovedTxs = transactions.filter( (tx) => tx.status !== TRANSACTION_STATUSES.UNAPPROVED, - ) - this._saveTxList(nonUnapprovedTxs) + ); + this._saveTxList(nonUnapprovedTxs); } } diff --git a/app/scripts/disable-console.js b/app/scripts/disable-console.js index 7416b36f5..d1ba36d57 100644 --- a/app/scripts/disable-console.js +++ b/app/scripts/disable-console.js @@ -4,10 +4,10 @@ if ( !(typeof process !== 'undefined' && process.env.METAMASK_DEBUG) && typeof console !== undefined ) { - console.log = noop - console.info = noop + console.log = noop; + console.info = noop; } function noop() { - return undefined + return undefined; } diff --git a/app/scripts/first-time-state.js b/app/scripts/first-time-state.js index b5b498694..857921889 100644 --- a/app/scripts/first-time-state.js +++ b/app/scripts/first-time-state.js @@ -20,6 +20,6 @@ const initialState = { }, ], }, -} +}; -export default initialState +export default initialState; diff --git a/app/scripts/initSentry.js b/app/scripts/initSentry.js index 70ea7b936..d959997e0 100644 --- a/app/scripts/initSentry.js +++ b/app/scripts/initSentry.js @@ -1,7 +1,7 @@ -import setupSentry from './lib/setupSentry' +import setupSentry from './lib/setupSentry'; // setup sentry error reporting global.sentry = setupSentry({ release: process.env.METAMASK_VERSION, getState: () => global.getSentryState?.() || {}, -}) +}); diff --git a/app/scripts/inpage.js b/app/scripts/inpage.js index c7619f77e..72bbf7901 100644 --- a/app/scripts/inpage.js +++ b/app/scripts/inpage.js @@ -1,7 +1,7 @@ // need to make sure we aren't affected by overlapping namespaces // and that we dont affect the app with our namespace // mostly a fix for web3's BigNumber if AMD's "define" is defined... -let __define +let __define; /** * Caches reference to global define object and deletes it to @@ -9,35 +9,35 @@ let __define * AMD's define function */ const cleanContextForImports = () => { - __define = global.define + __define = global.define; try { - global.define = undefined + global.define = undefined; } catch (_) { - console.warn('MetaMask - global.define could not be deleted.') + console.warn('MetaMask - global.define could not be deleted.'); } -} +}; /** * Restores global define object from cached reference */ const restoreContextAfterImports = () => { try { - global.define = __define + global.define = __define; } catch (_) { - console.warn('MetaMask - global.define could not be overwritten.') + console.warn('MetaMask - global.define could not be overwritten.'); } -} +}; -cleanContextForImports() +cleanContextForImports(); /* eslint-disable import/first */ -import log from 'loglevel' -import LocalMessageDuplexStream from 'post-message-stream' -import { initializeProvider } from '@metamask/inpage-provider' +import log from 'loglevel'; +import LocalMessageDuplexStream from 'post-message-stream'; +import { initializeProvider } from '@metamask/inpage-provider'; -restoreContextAfterImports() +restoreContextAfterImports(); -log.setDefaultLevel(process.env.METAMASK_DEBUG ? 'debug' : 'warn') +log.setDefaultLevel(process.env.METAMASK_DEBUG ? 'debug' : 'warn'); // // setup plugin communication @@ -47,10 +47,10 @@ log.setDefaultLevel(process.env.METAMASK_DEBUG ? 'debug' : 'warn') const metamaskStream = new LocalMessageDuplexStream({ name: 'metamask-inpage', target: 'metamask-contentscript', -}) +}); initializeProvider({ connectionStream: metamaskStream, logger: log, shouldShimWeb3: true, -}) +}); diff --git a/app/scripts/lib/ComposableObservableStore.js b/app/scripts/lib/ComposableObservableStore.js index 3661259bd..68ce42d08 100644 --- a/app/scripts/lib/ComposableObservableStore.js +++ b/app/scripts/lib/ComposableObservableStore.js @@ -1,4 +1,4 @@ -import { ObservableStore } from '@metamask/obs-store' +import { ObservableStore } from '@metamask/obs-store'; /** * An ObservableStore that can composes a flat @@ -12,8 +12,8 @@ export default class ComposableObservableStore extends ObservableStore { * @param {Object} [config] - Map of internal state keys to child stores */ constructor(initState, config) { - super(initState) - this.updateStructure(config) + super(initState); + this.updateStructure(config); } /** @@ -22,13 +22,13 @@ export default class ComposableObservableStore extends ObservableStore { * @param {Object} [config] - Map of internal state keys to child stores */ updateStructure(config) { - this.config = config - this.removeAllListeners() + this.config = config; + this.removeAllListeners(); for (const key in config) { if (Object.prototype.hasOwnProperty.call(config, key)) { config[key].subscribe((state) => { - this.updateState({ [key]: state }) - }) + this.updateState({ [key]: state }); + }); } } } @@ -40,16 +40,16 @@ export default class ComposableObservableStore extends ObservableStore { * @returns {Object} Object containing merged child store state */ getFlatState() { - let flatState = {} + let flatState = {}; for (const key in this.config) { if (Object.prototype.hasOwnProperty.call(this.config, key)) { - const controller = this.config[key] + const controller = this.config[key]; const state = controller.getState ? controller.getState() - : controller.state - flatState = { ...flatState, ...state } + : controller.state; + flatState = { ...flatState, ...state }; } } - return flatState + return flatState; } } diff --git a/app/scripts/lib/account-tracker.js b/app/scripts/lib/account-tracker.js index 6b78081f0..53c6a5c8d 100644 --- a/app/scripts/lib/account-tracker.js +++ b/app/scripts/lib/account-tracker.js @@ -7,27 +7,27 @@ * on each new block. */ -import EthQuery from 'eth-query' +import EthQuery from 'eth-query'; -import { ObservableStore } from '@metamask/obs-store' -import log from 'loglevel' -import pify from 'pify' -import Web3 from 'web3' -import SINGLE_CALL_BALANCES_ABI from 'single-call-balance-checker-abi' +import { ObservableStore } from '@metamask/obs-store'; +import log from 'loglevel'; +import pify from 'pify'; +import Web3 from 'web3'; +import SINGLE_CALL_BALANCES_ABI from 'single-call-balance-checker-abi'; import { MAINNET_CHAIN_ID, RINKEBY_CHAIN_ID, ROPSTEN_CHAIN_ID, KOVAN_CHAIN_ID, -} from '../../../shared/constants/network' +} from '../../../shared/constants/network'; import { SINGLE_CALL_BALANCES_ADDRESS, SINGLE_CALL_BALANCES_ADDRESS_RINKEBY, SINGLE_CALL_BALANCES_ADDRESS_ROPSTEN, SINGLE_CALL_BALANCES_ADDRESS_KOVAN, -} from '../constants/contracts' -import { bnToHex } from './util' +} from '../constants/contracts'; +import { bnToHex } from './util'; /** * This module is responsible for tracking any number of accounts and caching their current balances & transaction @@ -57,36 +57,36 @@ export default class AccountTracker { const initState = { accounts: {}, currentBlockGasLimit: '', - } - this.store = new ObservableStore(initState) + }; + this.store = new ObservableStore(initState); - this._provider = opts.provider - this._query = pify(new EthQuery(this._provider)) - this._blockTracker = opts.blockTracker + this._provider = opts.provider; + this._query = pify(new EthQuery(this._provider)); + this._blockTracker = opts.blockTracker; // blockTracker.currentBlock may be null - this._currentBlockNumber = this._blockTracker.getCurrentBlock() + this._currentBlockNumber = this._blockTracker.getCurrentBlock(); this._blockTracker.once('latest', (blockNumber) => { - this._currentBlockNumber = blockNumber - }) + this._currentBlockNumber = blockNumber; + }); // bind function for easier listener syntax - this._updateForBlock = this._updateForBlock.bind(this) - this.getCurrentChainId = opts.getCurrentChainId + this._updateForBlock = this._updateForBlock.bind(this); + this.getCurrentChainId = opts.getCurrentChainId; - this.web3 = new Web3(this._provider) + this.web3 = new Web3(this._provider); } start() { // remove first to avoid double add - this._blockTracker.removeListener('latest', this._updateForBlock) + this._blockTracker.removeListener('latest', this._updateForBlock); // add listener - this._blockTracker.addListener('latest', this._updateForBlock) + this._blockTracker.addListener('latest', this._updateForBlock); // fetch account balances - this._updateAccounts() + this._updateAccounts(); } stop() { // remove listener - this._blockTracker.removeListener('latest', this._updateForBlock) + this._blockTracker.removeListener('latest', this._updateForBlock); } /** @@ -101,25 +101,25 @@ export default class AccountTracker { * */ syncWithAddresses(addresses) { - const { accounts } = this.store.getState() - const locals = Object.keys(accounts) + const { accounts } = this.store.getState(); + const locals = Object.keys(accounts); - const accountsToAdd = [] + const accountsToAdd = []; addresses.forEach((upstream) => { if (!locals.includes(upstream)) { - accountsToAdd.push(upstream) + accountsToAdd.push(upstream); } - }) + }); - const accountsToRemove = [] + const accountsToRemove = []; locals.forEach((local) => { if (!addresses.includes(local)) { - accountsToRemove.push(local) + accountsToRemove.push(local); } - }) + }); - this.addAccounts(accountsToAdd) - this.removeAccount(accountsToRemove) + this.addAccounts(accountsToAdd); + this.removeAccount(accountsToRemove); } /** @@ -130,18 +130,18 @@ export default class AccountTracker { * */ addAccounts(addresses) { - const { accounts } = this.store.getState() + const { accounts } = this.store.getState(); // add initial state for addresses addresses.forEach((address) => { - accounts[address] = {} - }) + accounts[address] = {}; + }); // save accounts state - this.store.updateState({ accounts }) + this.store.updateState({ accounts }); // fetch balances for the accounts if there is block number ready if (!this._currentBlockNumber) { - return + return; } - this._updateAccounts() + this._updateAccounts(); } /** @@ -151,13 +151,13 @@ export default class AccountTracker { * */ removeAccount(addresses) { - const { accounts } = this.store.getState() + const { accounts } = this.store.getState(); // remove each state object addresses.forEach((address) => { - delete accounts[address] - }) + delete accounts[address]; + }); // save accounts state - this.store.updateState({ accounts }) + this.store.updateState({ accounts }); } /** @@ -165,7 +165,7 @@ export default class AccountTracker { */ clearAccounts() { - this.store.updateState({ accounts: {} }) + this.store.updateState({ accounts: {} }); } /** @@ -178,20 +178,20 @@ export default class AccountTracker { * */ async _updateForBlock(blockNumber) { - this._currentBlockNumber = blockNumber + this._currentBlockNumber = blockNumber; // block gasLimit polling shouldn't be in account-tracker shouldn't be here... - const currentBlock = await this._query.getBlockByNumber(blockNumber, false) + const currentBlock = await this._query.getBlockByNumber(blockNumber, false); if (!currentBlock) { - return + return; } - const currentBlockGasLimit = currentBlock.gasLimit - this.store.updateState({ currentBlockGasLimit }) + const currentBlockGasLimit = currentBlock.gasLimit; + this.store.updateState({ currentBlockGasLimit }); try { - await this._updateAccounts() + await this._updateAccounts(); } catch (err) { - log.error(err) + log.error(err); } } @@ -203,41 +203,41 @@ export default class AccountTracker { * */ async _updateAccounts() { - const { accounts } = this.store.getState() - const addresses = Object.keys(accounts) - const chainId = this.getCurrentChainId() + const { accounts } = this.store.getState(); + const addresses = Object.keys(accounts); + const chainId = this.getCurrentChainId(); switch (chainId) { case MAINNET_CHAIN_ID: await this._updateAccountsViaBalanceChecker( addresses, SINGLE_CALL_BALANCES_ADDRESS, - ) - break + ); + break; case RINKEBY_CHAIN_ID: await this._updateAccountsViaBalanceChecker( addresses, SINGLE_CALL_BALANCES_ADDRESS_RINKEBY, - ) - break + ); + break; case ROPSTEN_CHAIN_ID: await this._updateAccountsViaBalanceChecker( addresses, SINGLE_CALL_BALANCES_ADDRESS_ROPSTEN, - ) - break + ); + break; case KOVAN_CHAIN_ID: await this._updateAccountsViaBalanceChecker( addresses, SINGLE_CALL_BALANCES_ADDRESS_KOVAN, - ) - break + ); + break; default: - await Promise.all(addresses.map(this._updateAccount.bind(this))) + await Promise.all(addresses.map(this._updateAccount.bind(this))); } } @@ -251,16 +251,16 @@ export default class AccountTracker { */ async _updateAccount(address) { // query balance - const balance = await this._query.getBalance(address) - const result = { address, balance } + const balance = await this._query.getBalance(address); + const result = { address, balance }; // update accounts state - const { accounts } = this.store.getState() + const { accounts } = this.store.getState(); // only populate if the entry is still present if (!accounts[address]) { - return + return; } - accounts[address] = result - this.store.updateState({ accounts }) + accounts[address] = result; + this.store.updateState({ accounts }); } /** @@ -269,27 +269,27 @@ export default class AccountTracker { * @param {*} deployedContractAddress */ async _updateAccountsViaBalanceChecker(addresses, deployedContractAddress) { - const { accounts } = this.store.getState() - this.web3.setProvider(this._provider) + const { accounts } = this.store.getState(); + this.web3.setProvider(this._provider); const ethContract = this.web3.eth .contract(SINGLE_CALL_BALANCES_ABI) - .at(deployedContractAddress) - const ethBalance = ['0x0'] + .at(deployedContractAddress); + const ethBalance = ['0x0']; ethContract.balances(addresses, ethBalance, (error, result) => { if (error) { log.warn( `MetaMask - Account Tracker single call balance fetch failed`, error, - ) - Promise.all(addresses.map(this._updateAccount.bind(this))) - return + ); + Promise.all(addresses.map(this._updateAccount.bind(this))); + return; } addresses.forEach((address, index) => { - const balance = bnToHex(result[index]) - accounts[address] = { address, balance } - }) - this.store.updateState({ accounts }) - }) + const balance = bnToHex(result[index]); + accounts[address] = { address, balance }; + }); + this.store.updateState({ accounts }); + }); } } diff --git a/app/scripts/lib/buy-eth-url.js b/app/scripts/lib/buy-eth-url.js index 9c2e1c522..bf1b131f0 100644 --- a/app/scripts/lib/buy-eth-url.js +++ b/app/scripts/lib/buy-eth-url.js @@ -12,40 +12,42 @@ export default function getBuyEthUrl({ network, address, service }) { // default service by network if not specified if (!service) { // eslint-disable-next-line no-param-reassign - service = getDefaultServiceForNetwork(network) + service = getDefaultServiceForNetwork(network); } switch (service) { case 'wyre': - return `https://pay.sendwyre.com/purchase?dest=ethereum:${address}&destCurrency=ETH&accountId=AC-7AG3W4XH4N2&paymentMethod=debit-card` + return `https://pay.sendwyre.com/purchase?dest=ethereum:${address}&destCurrency=ETH&accountId=AC-7AG3W4XH4N2&paymentMethod=debit-card`; case 'metamask-faucet': - return 'https://faucet.metamask.io/' + return 'https://faucet.metamask.io/'; case 'rinkeby-faucet': - return 'https://www.rinkeby.io/' + return 'https://www.rinkeby.io/'; case 'kovan-faucet': - return 'https://github.com/kovan-testnet/faucet' + return 'https://github.com/kovan-testnet/faucet'; case 'goerli-faucet': - return 'https://goerli-faucet.slock.it/' + return 'https://goerli-faucet.slock.it/'; default: - throw new Error(`Unknown cryptocurrency exchange or faucet: "${service}"`) + throw new Error( + `Unknown cryptocurrency exchange or faucet: "${service}"`, + ); } } function getDefaultServiceForNetwork(network) { switch (network) { case '1': - return 'wyre' + return 'wyre'; case '3': - return 'metamask-faucet' + return 'metamask-faucet'; case '4': - return 'rinkeby-faucet' + return 'rinkeby-faucet'; case '42': - return 'kovan-faucet' + return 'kovan-faucet'; case '5': - return 'goerli-faucet' + return 'goerli-faucet'; default: throw new Error( `No default cryptocurrency exchange or faucet for networkId: "${network}"`, - ) + ); } } diff --git a/app/scripts/lib/cleanErrorStack.js b/app/scripts/lib/cleanErrorStack.js index a7bf607ad..16fb96109 100644 --- a/app/scripts/lib/cleanErrorStack.js +++ b/app/scripts/lib/cleanErrorStack.js @@ -4,19 +4,19 @@ * @returns {Error} Error with clean stack trace. */ export default function cleanErrorStack(err) { - let { name } = err - name = name === undefined ? 'Error' : String(name) + let { name } = err; + name = name === undefined ? 'Error' : String(name); - let msg = err.message - msg = msg === undefined ? '' : String(msg) + let msg = err.message; + msg = msg === undefined ? '' : String(msg); if (name === '') { - err.stack = err.message + err.stack = err.message; } else if (msg === '') { - err.stack = err.name + err.stack = err.name; } else { - err.stack = `${err.name}: ${err.message}` + err.stack = `${err.name}: ${err.message}`; } - return err + return err; } diff --git a/app/scripts/lib/createLoggerMiddleware.js b/app/scripts/lib/createLoggerMiddleware.js index 18a128cba..89a7696dd 100644 --- a/app/scripts/lib/createLoggerMiddleware.js +++ b/app/scripts/lib/createLoggerMiddleware.js @@ -1,4 +1,4 @@ -import log from 'loglevel' +import log from 'loglevel'; /** * Returns a middleware that logs RPC activity @@ -13,13 +13,13 @@ export default function createLoggerMiddleware(opts) { ) { next((/** @type {Function} */ cb) => { if (res.error) { - log.error('Error in RPC response:\n', res) + log.error('Error in RPC response:\n', res); } if (req.isMetamaskInternal) { - return + return; } - log.info(`RPC (${opts.origin}):`, req, '->', res) - cb() - }) - } + log.info(`RPC (${opts.origin}):`, req, '->', res); + cb(); + }); + }; } diff --git a/app/scripts/lib/createOnboardingMiddleware.js b/app/scripts/lib/createOnboardingMiddleware.js index cef41deb6..7f79da8d6 100644 --- a/app/scripts/lib/createOnboardingMiddleware.js +++ b/app/scripts/lib/createOnboardingMiddleware.js @@ -1,5 +1,5 @@ -import log from 'loglevel' -import extension from 'extensionizer' +import log from 'loglevel'; +import extension from 'extensionizer'; /** * Returns a middleware that intercepts `wallet_registerOnboarding` messages @@ -13,20 +13,20 @@ export default function createOnboardingMiddleware({ return async function originMiddleware(req, res, next, end) { try { if (req.method !== 'wallet_registerOnboarding') { - next() - return + next(); + return; } if (req.tabId && req.tabId !== extension.tabs.TAB_ID_NONE) { - await registerOnboarding(location, req.tabId) + await registerOnboarding(location, req.tabId); } else { log.debug( `'wallet_registerOnboarding' message from ${location} ignored due to missing tabId`, - ) + ); } - res.result = true - end() + res.result = true; + end(); } catch (error) { - end(error) + end(error); } - } + }; } diff --git a/app/scripts/lib/createOriginMiddleware.js b/app/scripts/lib/createOriginMiddleware.js index 031ba84d5..0e3c14add 100644 --- a/app/scripts/lib/createOriginMiddleware.js +++ b/app/scripts/lib/createOriginMiddleware.js @@ -9,7 +9,7 @@ export default function createOriginMiddleware(opts) { /** @type {any} */ _, /** @type {Function} */ next, ) { - req.origin = opts.origin - next() - } + req.origin = opts.origin; + next(); + }; } diff --git a/app/scripts/lib/createStreamSink.js b/app/scripts/lib/createStreamSink.js index 648e745dd..84ad69db1 100644 --- a/app/scripts/lib/createStreamSink.js +++ b/app/scripts/lib/createStreamSink.js @@ -1,19 +1,19 @@ -import { Writable as WritableStream } from 'readable-stream' -import promiseToCallback from 'promise-to-callback' +import { Writable as WritableStream } from 'readable-stream'; +import promiseToCallback from 'promise-to-callback'; class AsyncWritableStream extends WritableStream { constructor(asyncWriteFn, _opts) { - const opts = { objectMode: true, ..._opts } - super(opts) - this._asyncWriteFn = asyncWriteFn + const opts = { objectMode: true, ..._opts }; + super(opts); + this._asyncWriteFn = asyncWriteFn; } // write from incoming stream to state _write(chunk, encoding, callback) { - promiseToCallback(this._asyncWriteFn(chunk, encoding))(callback) + promiseToCallback(this._asyncWriteFn(chunk, encoding))(callback); } } export default function createStreamSink(asyncWriteFn, _opts) { - return new AsyncWritableStream(asyncWriteFn, _opts) + return new AsyncWritableStream(asyncWriteFn, _opts); } diff --git a/app/scripts/lib/createTabIdMiddleware.js b/app/scripts/lib/createTabIdMiddleware.js index 9848b68c9..abce443c9 100644 --- a/app/scripts/lib/createTabIdMiddleware.js +++ b/app/scripts/lib/createTabIdMiddleware.js @@ -9,7 +9,7 @@ export default function createTabIdMiddleware(opts) { /** @type {any} */ _, /** @type {Function} */ next, ) { - req.tabId = opts.tabId - next() - } + req.tabId = opts.tabId; + next(); + }; } diff --git a/app/scripts/lib/decrypt-message-manager.js b/app/scripts/lib/decrypt-message-manager.js index caa2970f6..39f2a0e42 100644 --- a/app/scripts/lib/decrypt-message-manager.js +++ b/app/scripts/lib/decrypt-message-manager.js @@ -1,13 +1,13 @@ -import EventEmitter from 'events' -import { ObservableStore } from '@metamask/obs-store' -import ethUtil from 'ethereumjs-util' -import { ethErrors } from 'eth-rpc-errors' -import log from 'loglevel' -import { MESSAGE_TYPE } from '../../../shared/constants/app' -import { addHexPrefix } from './util' -import createId from './random-id' +import EventEmitter from 'events'; +import { ObservableStore } from '@metamask/obs-store'; +import ethUtil from 'ethereumjs-util'; +import { ethErrors } from 'eth-rpc-errors'; +import log from 'loglevel'; +import { MESSAGE_TYPE } from '../../../shared/constants/app'; +import { addHexPrefix } from './util'; +import createId from './random-id'; -const hexRe = /^[0-9A-Fa-f]+$/gu +const hexRe = /^[0-9A-Fa-f]+$/gu; /** * Represents, and contains data about, an 'eth_decrypt' type decryption request. These are created when a @@ -38,12 +38,12 @@ export default class DecryptMessageManager extends EventEmitter { * */ constructor() { - super() + super(); this.memStore = new ObservableStore({ unapprovedDecryptMsgs: {}, unapprovedDecryptMsgCount: 0, - }) - this.messages = [] + }); + this.messages = []; } /** @@ -53,7 +53,7 @@ export default class DecryptMessageManager extends EventEmitter { * */ get unapprovedDecryptMsgCount() { - return Object.keys(this.getUnapprovedMsgs()).length + return Object.keys(this.getUnapprovedMsgs()).length; } /** @@ -67,9 +67,9 @@ export default class DecryptMessageManager extends EventEmitter { return this.messages .filter((msg) => msg.status === 'unapproved') .reduce((result, msg) => { - result[msg.id] = msg - return result - }, {}) + result[msg.id] = msg; + return result; + }, {}); } /** @@ -85,25 +85,25 @@ export default class DecryptMessageManager extends EventEmitter { addUnapprovedMessageAsync(msgParams, req) { return new Promise((resolve, reject) => { if (!msgParams.from) { - reject(new Error('MetaMask Decryption: from field is required.')) - return + reject(new Error('MetaMask Decryption: from field is required.')); + return; } - const msgId = this.addUnapprovedMessage(msgParams, req) + const msgId = this.addUnapprovedMessage(msgParams, req); this.once(`${msgId}:finished`, (data) => { switch (data.status) { case 'decrypted': - resolve(data.rawData) - return + resolve(data.rawData); + return; case 'rejected': reject( ethErrors.provider.userRejectedRequest( 'MetaMask Decryption: User denied message decryption.', ), - ) - return + ); + return; case 'errored': - reject(new Error('This message cannot be decrypted')) - return + reject(new Error('This message cannot be decrypted')); + return; default: reject( new Error( @@ -111,10 +111,10 @@ export default class DecryptMessageManager extends EventEmitter { msgParams, )}`, ), - ) + ); } - }) - }) + }); + }); } /** @@ -132,27 +132,27 @@ export default class DecryptMessageManager extends EventEmitter { `DecryptMessageManager addUnapprovedMessage: ${JSON.stringify( msgParams, )}`, - ) + ); // add origin from request if (req) { - msgParams.origin = req.origin + msgParams.origin = req.origin; } - msgParams.data = this.normalizeMsgData(msgParams.data) + msgParams.data = this.normalizeMsgData(msgParams.data); // create txData obj with parameters and meta data - const time = new Date().getTime() - const msgId = createId() + const time = new Date().getTime(); + const msgId = createId(); const msgData = { id: msgId, msgParams, time, status: 'unapproved', type: MESSAGE_TYPE.ETH_DECRYPT, - } - this.addMsg(msgData) + }; + this.addMsg(msgData); // signal update - this.emit('update') - return msgId + this.emit('update'); + return msgId; } /** @@ -163,8 +163,8 @@ export default class DecryptMessageManager extends EventEmitter { * */ addMsg(msg) { - this.messages.push(msg) - this._saveMsgList() + this.messages.push(msg); + this._saveMsgList(); } /** @@ -176,7 +176,7 @@ export default class DecryptMessageManager extends EventEmitter { * */ getMsg(msgId) { - return this.messages.find((msg) => msg.id === msgId) + return this.messages.find((msg) => msg.id === msgId); } /** @@ -189,8 +189,8 @@ export default class DecryptMessageManager extends EventEmitter { * */ approveMessage(msgParams) { - this.setMsgStatusApproved(msgParams.metamaskId) - return this.prepMsgForDecryption(msgParams) + this.setMsgStatusApproved(msgParams.metamaskId); + return this.prepMsgForDecryption(msgParams); } /** @@ -200,7 +200,7 @@ export default class DecryptMessageManager extends EventEmitter { * */ setMsgStatusApproved(msgId) { - this._setMsgStatus(msgId, 'approved') + this._setMsgStatus(msgId, 'approved'); } /** @@ -212,10 +212,10 @@ export default class DecryptMessageManager extends EventEmitter { * */ setMsgStatusDecrypted(msgId, rawData) { - const msg = this.getMsg(msgId) - msg.rawData = rawData - this._updateMsg(msg) - this._setMsgStatus(msgId, 'decrypted') + const msg = this.getMsg(msgId); + msg.rawData = rawData; + this._updateMsg(msg); + this._setMsgStatus(msgId, 'decrypted'); } /** @@ -226,8 +226,8 @@ export default class DecryptMessageManager extends EventEmitter { * */ prepMsgForDecryption(msgParams) { - delete msgParams.metamaskId - return Promise.resolve(msgParams) + delete msgParams.metamaskId; + return Promise.resolve(msgParams); } /** @@ -237,7 +237,7 @@ export default class DecryptMessageManager extends EventEmitter { * */ rejectMsg(msgId) { - this._setMsgStatus(msgId, 'rejected') + this._setMsgStatus(msgId, 'rejected'); } /** @@ -247,10 +247,10 @@ export default class DecryptMessageManager extends EventEmitter { * */ errorMessage(msgId, error) { - const msg = this.getMsg(msgId) - msg.error = error - this._updateMsg(msg) - this._setMsgStatus(msgId, 'errored') + const msg = this.getMsg(msgId); + msg.error = error; + this._updateMsg(msg); + this._setMsgStatus(msgId, 'errored'); } /** @@ -267,21 +267,21 @@ export default class DecryptMessageManager extends EventEmitter { * */ _setMsgStatus(msgId, status) { - const msg = this.getMsg(msgId) + const msg = this.getMsg(msgId); if (!msg) { throw new Error( `DecryptMessageManager - Message not found for id: "${msgId}".`, - ) + ); } - msg.status = status - this._updateMsg(msg) - this.emit(`${msgId}:${status}`, msg) + msg.status = status; + this._updateMsg(msg); + this.emit(`${msgId}:${status}`, msg); if ( status === 'rejected' || status === 'decrypted' || status === 'errored' ) { - this.emit(`${msgId}:finished`, msg) + this.emit(`${msgId}:finished`, msg); } } @@ -295,11 +295,11 @@ export default class DecryptMessageManager extends EventEmitter { * */ _updateMsg(msg) { - const index = this.messages.findIndex((message) => message.id === msg.id) + const index = this.messages.findIndex((message) => message.id === msg.id); if (index !== -1) { - this.messages[index] = msg + this.messages[index] = msg; } - this._saveMsgList() + this._saveMsgList(); } /** @@ -310,13 +310,13 @@ export default class DecryptMessageManager extends EventEmitter { * */ _saveMsgList() { - const unapprovedDecryptMsgs = this.getUnapprovedMsgs() - const unapprovedDecryptMsgCount = Object.keys(unapprovedDecryptMsgs).length + const unapprovedDecryptMsgs = this.getUnapprovedMsgs(); + const unapprovedDecryptMsgCount = Object.keys(unapprovedDecryptMsgs).length; this.memStore.updateState({ unapprovedDecryptMsgs, unapprovedDecryptMsgCount, - }) - this.emit('updateBadge') + }); + this.emit('updateBadge'); } /** @@ -328,14 +328,14 @@ export default class DecryptMessageManager extends EventEmitter { */ normalizeMsgData(data) { try { - const stripped = ethUtil.stripHexPrefix(data) + const stripped = ethUtil.stripHexPrefix(data); if (stripped.match(hexRe)) { - return addHexPrefix(stripped) + return addHexPrefix(stripped); } } catch (e) { - log.debug(`Message was not hex encoded, interpreting as utf8.`) + log.debug(`Message was not hex encoded, interpreting as utf8.`); } - return ethUtil.bufferToHex(Buffer.from(data, 'utf8')) + return ethUtil.bufferToHex(Buffer.from(data, 'utf8')); } } diff --git a/app/scripts/lib/encryption-public-key-manager.js b/app/scripts/lib/encryption-public-key-manager.js index 54504fd62..6fc213b19 100644 --- a/app/scripts/lib/encryption-public-key-manager.js +++ b/app/scripts/lib/encryption-public-key-manager.js @@ -1,9 +1,9 @@ -import EventEmitter from 'events' -import { ObservableStore } from '@metamask/obs-store' -import { ethErrors } from 'eth-rpc-errors' -import log from 'loglevel' -import { MESSAGE_TYPE } from '../../../shared/constants/app' -import createId from './random-id' +import EventEmitter from 'events'; +import { ObservableStore } from '@metamask/obs-store'; +import { ethErrors } from 'eth-rpc-errors'; +import log from 'loglevel'; +import { MESSAGE_TYPE } from '../../../shared/constants/app'; +import createId from './random-id'; /** * Represents, and contains data about, an 'eth_getEncryptionPublicKey' type request. These are created when @@ -34,12 +34,12 @@ export default class EncryptionPublicKeyManager extends EventEmitter { * */ constructor() { - super() + super(); this.memStore = new ObservableStore({ unapprovedEncryptionPublicKeyMsgs: {}, unapprovedEncryptionPublicKeyMsgCount: 0, - }) - this.messages = [] + }); + this.messages = []; } /** @@ -49,7 +49,7 @@ export default class EncryptionPublicKeyManager extends EventEmitter { * */ get unapprovedEncryptionPublicKeyMsgCount() { - return Object.keys(this.getUnapprovedMsgs()).length + return Object.keys(this.getUnapprovedMsgs()).length; } /** @@ -63,9 +63,9 @@ export default class EncryptionPublicKeyManager extends EventEmitter { return this.messages .filter((msg) => msg.status === 'unapproved') .reduce((result, msg) => { - result[msg.id] = msg - return result - }, {}) + result[msg.id] = msg; + return result; + }, {}); } /** @@ -81,22 +81,22 @@ export default class EncryptionPublicKeyManager extends EventEmitter { addUnapprovedMessageAsync(address, req) { return new Promise((resolve, reject) => { if (!address) { - reject(new Error('MetaMask Message: address field is required.')) - return + reject(new Error('MetaMask Message: address field is required.')); + return; } - const msgId = this.addUnapprovedMessage(address, req) + const msgId = this.addUnapprovedMessage(address, req); this.once(`${msgId}:finished`, (data) => { switch (data.status) { case 'received': - resolve(data.rawData) - return + resolve(data.rawData); + return; case 'rejected': reject( ethErrors.provider.userRejectedRequest( 'MetaMask EncryptionPublicKey: User denied message EncryptionPublicKey.', ), - ) - return + ); + return; default: reject( new Error( @@ -104,10 +104,10 @@ export default class EncryptionPublicKeyManager extends EventEmitter { address, )}`, ), - ) + ); } - }) - }) + }); + }); } /** @@ -121,27 +121,27 @@ export default class EncryptionPublicKeyManager extends EventEmitter { * */ addUnapprovedMessage(address, req) { - log.debug(`EncryptionPublicKeyManager addUnapprovedMessage: address`) + log.debug(`EncryptionPublicKeyManager addUnapprovedMessage: address`); // create txData obj with parameters and meta data - const time = new Date().getTime() - const msgId = createId() + const time = new Date().getTime(); + const msgId = createId(); const msgData = { id: msgId, msgParams: address, time, status: 'unapproved', type: MESSAGE_TYPE.ETH_GET_ENCRYPTION_PUBLIC_KEY, - } + }; if (req) { - msgData.origin = req.origin + msgData.origin = req.origin; } - this.addMsg(msgData) + this.addMsg(msgData); // signal update - this.emit('update') - return msgId + this.emit('update'); + return msgId; } /** @@ -152,8 +152,8 @@ export default class EncryptionPublicKeyManager extends EventEmitter { * */ addMsg(msg) { - this.messages.push(msg) - this._saveMsgList() + this.messages.push(msg); + this._saveMsgList(); } /** @@ -165,7 +165,7 @@ export default class EncryptionPublicKeyManager extends EventEmitter { * */ getMsg(msgId) { - return this.messages.find((msg) => msg.id === msgId) + return this.messages.find((msg) => msg.id === msgId); } /** @@ -178,8 +178,8 @@ export default class EncryptionPublicKeyManager extends EventEmitter { * */ approveMessage(msgParams) { - this.setMsgStatusApproved(msgParams.metamaskId) - return this.prepMsgForEncryptionPublicKey(msgParams) + this.setMsgStatusApproved(msgParams.metamaskId); + return this.prepMsgForEncryptionPublicKey(msgParams); } /** @@ -189,7 +189,7 @@ export default class EncryptionPublicKeyManager extends EventEmitter { * */ setMsgStatusApproved(msgId) { - this._setMsgStatus(msgId, 'approved') + this._setMsgStatus(msgId, 'approved'); } /** @@ -201,10 +201,10 @@ export default class EncryptionPublicKeyManager extends EventEmitter { * */ setMsgStatusReceived(msgId, rawData) { - const msg = this.getMsg(msgId) - msg.rawData = rawData - this._updateMsg(msg) - this._setMsgStatus(msgId, 'received') + const msg = this.getMsg(msgId); + msg.rawData = rawData; + this._updateMsg(msg); + this._setMsgStatus(msgId, 'received'); } /** @@ -215,8 +215,8 @@ export default class EncryptionPublicKeyManager extends EventEmitter { * */ prepMsgForEncryptionPublicKey(msgParams) { - delete msgParams.metamaskId - return Promise.resolve(msgParams) + delete msgParams.metamaskId; + return Promise.resolve(msgParams); } /** @@ -226,7 +226,7 @@ export default class EncryptionPublicKeyManager extends EventEmitter { * */ rejectMsg(msgId) { - this._setMsgStatus(msgId, 'rejected') + this._setMsgStatus(msgId, 'rejected'); } /** @@ -236,10 +236,10 @@ export default class EncryptionPublicKeyManager extends EventEmitter { * */ errorMessage(msgId, error) { - const msg = this.getMsg(msgId) - msg.error = error - this._updateMsg(msg) - this._setMsgStatus(msgId, 'errored') + const msg = this.getMsg(msgId); + msg.error = error; + this._updateMsg(msg); + this._setMsgStatus(msgId, 'errored'); } /** @@ -256,17 +256,17 @@ export default class EncryptionPublicKeyManager extends EventEmitter { * */ _setMsgStatus(msgId, status) { - const msg = this.getMsg(msgId) + const msg = this.getMsg(msgId); if (!msg) { throw new Error( `EncryptionPublicKeyManager - Message not found for id: "${msgId}".`, - ) + ); } - msg.status = status - this._updateMsg(msg) - this.emit(`${msgId}:${status}`, msg) + msg.status = status; + this._updateMsg(msg); + this.emit(`${msgId}:${status}`, msg); if (status === 'rejected' || status === 'received') { - this.emit(`${msgId}:finished`, msg) + this.emit(`${msgId}:finished`, msg); } } @@ -280,11 +280,11 @@ export default class EncryptionPublicKeyManager extends EventEmitter { * */ _updateMsg(msg) { - const index = this.messages.findIndex((message) => message.id === msg.id) + const index = this.messages.findIndex((message) => message.id === msg.id); if (index !== -1) { - this.messages[index] = msg + this.messages[index] = msg; } - this._saveMsgList() + this._saveMsgList(); } /** @@ -295,14 +295,14 @@ export default class EncryptionPublicKeyManager extends EventEmitter { * */ _saveMsgList() { - const unapprovedEncryptionPublicKeyMsgs = this.getUnapprovedMsgs() + const unapprovedEncryptionPublicKeyMsgs = this.getUnapprovedMsgs(); const unapprovedEncryptionPublicKeyMsgCount = Object.keys( unapprovedEncryptionPublicKeyMsgs, - ).length + ).length; this.memStore.updateState({ unapprovedEncryptionPublicKeyMsgs, unapprovedEncryptionPublicKeyMsgCount, - }) - this.emit('updateBadge') + }); + this.emit('updateBadge'); } } diff --git a/app/scripts/lib/ens-ipfs/contracts/registry.js b/app/scripts/lib/ens-ipfs/contracts/registry.js index 4eab80287..07342ac37 100644 --- a/app/scripts/lib/ens-ipfs/contracts/registry.js +++ b/app/scripts/lib/ens-ipfs/contracts/registry.js @@ -105,5 +105,5 @@ const abi = [ name: 'NewTTL', type: 'event', }, -] -export default abi +]; +export default abi; diff --git a/app/scripts/lib/ens-ipfs/contracts/resolver.js b/app/scripts/lib/ens-ipfs/contracts/resolver.js index a392bcfe8..af1f0e544 100644 --- a/app/scripts/lib/ens-ipfs/contracts/resolver.js +++ b/app/scripts/lib/ens-ipfs/contracts/resolver.js @@ -232,5 +232,5 @@ const abi = [ name: 'ContenthashChanged', type: 'event', }, -] -export default abi +]; +export default abi; diff --git a/app/scripts/lib/ens-ipfs/resolver.js b/app/scripts/lib/ens-ipfs/resolver.js index 5a4b29043..ff61f00e6 100644 --- a/app/scripts/lib/ens-ipfs/resolver.js +++ b/app/scripts/lib/ens-ipfs/resolver.js @@ -1,61 +1,61 @@ -import namehash from 'eth-ens-namehash' -import Eth from 'ethjs-query' -import EthContract from 'ethjs-contract' -import contentHash from 'content-hash' -import registryAbi from './contracts/registry' -import resolverAbi from './contracts/resolver' +import namehash from 'eth-ens-namehash'; +import Eth from 'ethjs-query'; +import EthContract from 'ethjs-contract'; +import contentHash from 'content-hash'; +import registryAbi from './contracts/registry'; +import resolverAbi from './contracts/resolver'; export default async function resolveEnsToIpfsContentId({ provider, name }) { - const eth = new Eth(provider) - const hash = namehash.hash(name) - const contract = new EthContract(eth) + const eth = new Eth(provider); + const hash = namehash.hash(name); + const contract = new EthContract(eth); // lookup registry - const chainId = Number.parseInt(await eth.net_version(), 10) - const registryAddress = getRegistryForChainId(chainId) + const chainId = Number.parseInt(await eth.net_version(), 10); + const registryAddress = getRegistryForChainId(chainId); if (!registryAddress) { throw new Error( `EnsIpfsResolver - no known ens-ipfs registry for chainId "${chainId}"`, - ) + ); } - const Registry = contract(registryAbi).at(registryAddress) + const Registry = contract(registryAbi).at(registryAddress); // lookup resolver - const resolverLookupResult = await Registry.resolver(hash) - const resolverAddress = resolverLookupResult[0] + const resolverLookupResult = await Registry.resolver(hash); + const resolverAddress = resolverLookupResult[0]; if (hexValueIsEmpty(resolverAddress)) { - throw new Error(`EnsIpfsResolver - no resolver found for name "${name}"`) + throw new Error(`EnsIpfsResolver - no resolver found for name "${name}"`); } - const Resolver = contract(resolverAbi).at(resolverAddress) + const Resolver = contract(resolverAbi).at(resolverAddress); - const isEIP1577Compliant = await Resolver.supportsInterface('0xbc1c58d1') - const isLegacyResolver = await Resolver.supportsInterface('0xd8389dc5') + const isEIP1577Compliant = await Resolver.supportsInterface('0xbc1c58d1'); + const isLegacyResolver = await Resolver.supportsInterface('0xd8389dc5'); if (isEIP1577Compliant[0]) { - const contentLookupResult = await Resolver.contenthash(hash) - const rawContentHash = contentLookupResult[0] - let decodedContentHash = contentHash.decode(rawContentHash) - const type = contentHash.getCodec(rawContentHash) + const contentLookupResult = await Resolver.contenthash(hash); + const rawContentHash = contentLookupResult[0]; + let decodedContentHash = contentHash.decode(rawContentHash); + const type = contentHash.getCodec(rawContentHash); if (type === 'ipfs-ns' || type === 'ipns-ns') { decodedContentHash = contentHash.helpers.cidV0ToV1Base32( decodedContentHash, - ) + ); } - return { type, hash: decodedContentHash } + return { type, hash: decodedContentHash }; } if (isLegacyResolver[0]) { // lookup content id - const contentLookupResult = await Resolver.content(hash) - const content = contentLookupResult[0] + const contentLookupResult = await Resolver.content(hash); + const content = contentLookupResult[0]; if (hexValueIsEmpty(content)) { throw new Error( `EnsIpfsResolver - no content ID found for name "${name}"`, - ) + ); } - return { type: 'swarm-ns', hash: content.slice(2) } + return { type: 'swarm-ns', hash: content.slice(2) }; } throw new Error( `EnsIpfsResolver - the resolver for name "${name}" is not standard, it should either supports contenthash() or content()`, - ) + ); } function hexValueIsEmpty(value) { @@ -65,7 +65,7 @@ function hexValueIsEmpty(value) { '0x', '0x0', '0x0000000000000000000000000000000000000000000000000000000000000000', - ].includes(value) + ].includes(value); } /** @@ -80,8 +80,8 @@ function getRegistryForChainId(chainId) { case 4: case 5: // Mainnet, Ropsten, Rinkeby, and Goerli, respectively, use the same address - return '0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e' + return '0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e'; default: - return null + return null; } } diff --git a/app/scripts/lib/ens-ipfs/setup.js b/app/scripts/lib/ens-ipfs/setup.js index 9ec6e1492..51b740301 100644 --- a/app/scripts/lib/ens-ipfs/setup.js +++ b/app/scripts/lib/ens-ipfs/setup.js @@ -1,10 +1,10 @@ -import extension from 'extensionizer' -import getFetchWithTimeout from '../../../../shared/modules/fetch-with-timeout' -import resolveEnsToIpfsContentId from './resolver' +import extension from 'extensionizer'; +import getFetchWithTimeout from '../../../../shared/modules/fetch-with-timeout'; +import resolveEnsToIpfsContentId from './resolver'; -const fetchWithTimeout = getFetchWithTimeout(30000) +const fetchWithTimeout = getFetchWithTimeout(30000); -const supportedTopLevelDomains = ['eth'] +const supportedTopLevelDomains = ['eth']; export default function setupEnsIpfsResolver({ provider, @@ -12,76 +12,79 @@ export default function setupEnsIpfsResolver({ getIpfsGateway, }) { // install listener - const urlPatterns = supportedTopLevelDomains.map((tld) => `*://*.${tld}/*`) + const urlPatterns = supportedTopLevelDomains.map((tld) => `*://*.${tld}/*`); extension.webRequest.onErrorOccurred.addListener(webRequestDidFail, { urls: urlPatterns, types: ['main_frame'], - }) + }); // return api object return { // uninstall listener remove() { - extension.webRequest.onErrorOccurred.removeListener(webRequestDidFail) + extension.webRequest.onErrorOccurred.removeListener(webRequestDidFail); }, - } + }; async function webRequestDidFail(details) { - const { tabId, url } = details + const { tabId, url } = details; // ignore requests that are not associated with tabs // only attempt ENS resolution on mainnet if (tabId === -1 || getCurrentNetwork() !== '1') { - return + return; } // parse ens name - const { hostname: name, pathname, search, hash: fragment } = new URL(url) - const domainParts = name.split('.') - const topLevelDomain = domainParts[domainParts.length - 1] + const { hostname: name, pathname, search, hash: fragment } = new URL(url); + const domainParts = name.split('.'); + const topLevelDomain = domainParts[domainParts.length - 1]; // if unsupported TLD, abort if (!supportedTopLevelDomains.includes(topLevelDomain)) { - return + return; } // otherwise attempt resolve - attemptResolve({ tabId, name, pathname, search, fragment }) + attemptResolve({ tabId, name, pathname, search, fragment }); } async function attemptResolve({ tabId, name, pathname, search, fragment }) { - const ipfsGateway = getIpfsGateway() - extension.tabs.update(tabId, { url: `loading.html` }) - let url = `https://app.ens.domains/name/${name}` + const ipfsGateway = getIpfsGateway(); + extension.tabs.update(tabId, { url: `loading.html` }); + let url = `https://app.ens.domains/name/${name}`; try { - const { type, hash } = await resolveEnsToIpfsContentId({ provider, name }) + const { type, hash } = await resolveEnsToIpfsContentId({ + provider, + name, + }); if (type === 'ipfs-ns' || type === 'ipns-ns') { const resolvedUrl = `https://${hash}.${type.slice( 0, 4, - )}.${ipfsGateway}${pathname}${search || ''}${fragment || ''}` + )}.${ipfsGateway}${pathname}${search || ''}${fragment || ''}`; try { // check if ipfs gateway has result const response = await fetchWithTimeout(resolvedUrl, { method: 'HEAD', - }) + }); if (response.status === 200) { - url = resolvedUrl + url = resolvedUrl; } } catch (err) { - console.warn(err) + console.warn(err); } } else if (type === 'swarm-ns') { url = `https://swarm-gateways.net/bzz:/${hash}${pathname}${ search || '' - }${fragment || ''}` + }${fragment || ''}`; } else if (type === 'onion' || type === 'onion3') { - url = `http://${hash}.onion${pathname}${search || ''}${fragment || ''}` + url = `http://${hash}.onion${pathname}${search || ''}${fragment || ''}`; } else if (type === 'zeronet') { url = `http://127.0.0.1:43110/${hash}${pathname}${search || ''}${ fragment || '' - }` + }`; } } catch (err) { - console.warn(err) + console.warn(err); } finally { - extension.tabs.update(tabId, { url }) + extension.tabs.update(tabId, { url }); } } } diff --git a/app/scripts/lib/extractEthjsErrorMessage.js b/app/scripts/lib/extractEthjsErrorMessage.js index 621e22195..d17d581a0 100644 --- a/app/scripts/lib/extractEthjsErrorMessage.js +++ b/app/scripts/lib/extractEthjsErrorMessage.js @@ -1,5 +1,5 @@ -const ethJsRpcSlug = 'Error: [ethjs-rpc] rpc error with payload ' -const errorLabelPrefix = 'Error: ' +const ethJsRpcSlug = 'Error: [ethjs-rpc] rpc error with payload '; +const errorLabelPrefix = 'Error: '; /** * Extracts the important part of an ethjs-rpc error message. If the passed error is not an isEthjsRpcError, the error @@ -14,13 +14,13 @@ const errorLabelPrefix = 'Error: ' * */ export default function extractEthjsErrorMessage(errorMessage) { - const isEthjsRpcError = errorMessage.includes(ethJsRpcSlug) + const isEthjsRpcError = errorMessage.includes(ethJsRpcSlug); if (isEthjsRpcError) { - const payloadAndError = errorMessage.slice(ethJsRpcSlug.length) + const payloadAndError = errorMessage.slice(ethJsRpcSlug.length); const originalError = payloadAndError.slice( payloadAndError.indexOf(errorLabelPrefix) + errorLabelPrefix.length, - ) - return originalError + ); + return originalError; } - return errorMessage + return errorMessage; } diff --git a/app/scripts/lib/get-first-preferred-lang-code.js b/app/scripts/lib/get-first-preferred-lang-code.js index d37ac6d0d..4639d6dc9 100644 --- a/app/scripts/lib/get-first-preferred-lang-code.js +++ b/app/scripts/lib/get-first-preferred-lang-code.js @@ -1,19 +1,19 @@ -import extension from 'extensionizer' -import promisify from 'pify' -import allLocales from '../../_locales/index.json' +import extension from 'extensionizer'; +import promisify from 'pify'; +import allLocales from '../../_locales/index.json'; const getPreferredLocales = extension.i18n ? promisify(extension.i18n.getAcceptLanguages, { errorFirst: false }) - : async () => [] + : async () => []; // mapping some browsers return hyphen instead underscore in locale codes (e.g. zh_TW -> zh-tw) -const existingLocaleCodes = {} +const existingLocaleCodes = {}; allLocales.forEach((locale) => { if (locale && locale.code) { existingLocaleCodes[locale.code.toLowerCase().replace('_', '-')] = - locale.code + locale.code; } -}) +}); /** * Returns a preferred language code, based on settings within the user's browser. If we have no translations for the @@ -23,26 +23,26 @@ allLocales.forEach((locale) => { * */ export default async function getFirstPreferredLangCode() { - let userPreferredLocaleCodes + let userPreferredLocaleCodes; try { - userPreferredLocaleCodes = await getPreferredLocales() + userPreferredLocaleCodes = await getPreferredLocales(); } catch (e) { // Brave currently throws when calling getAcceptLanguages, so this handles that. - userPreferredLocaleCodes = [] + userPreferredLocaleCodes = []; } // safeguard for Brave Browser until they implement chrome.i18n.getAcceptLanguages // https://github.com/MetaMask/metamask-extension/issues/4270 if (!userPreferredLocaleCodes) { - userPreferredLocaleCodes = [] + userPreferredLocaleCodes = []; } const firstPreferredLangCode = userPreferredLocaleCodes .map((code) => code.toLowerCase().replace('_', '-')) .find((code) => Object.prototype.hasOwnProperty.call(existingLocaleCodes, code), - ) + ); - return existingLocaleCodes[firstPreferredLangCode] || 'en' + return existingLocaleCodes[firstPreferredLangCode] || 'en'; } diff --git a/app/scripts/lib/getObjStructure.js b/app/scripts/lib/getObjStructure.js index b96351912..8ac90f9fe 100644 --- a/app/scripts/lib/getObjStructure.js +++ b/app/scripts/lib/getObjStructure.js @@ -1,4 +1,4 @@ -import { cloneDeep } from 'lodash' +import { cloneDeep } from 'lodash'; // This will create an object that represents the structure of the given object // it replaces all values with the result of their type @@ -22,10 +22,10 @@ import { cloneDeep } from 'lodash' * */ export default function getObjStructure(obj) { - const structure = cloneDeep(obj) + const structure = cloneDeep(obj); return deepMap(structure, (value) => { - return value === null ? 'null' : typeof value - }) + return value === null ? 'null' : typeof value; + }); } /** @@ -39,10 +39,10 @@ export default function getObjStructure(obj) { function deepMap(target = {}, visit) { Object.entries(target).forEach(([key, value]) => { if (typeof value === 'object' && value !== null) { - target[key] = deepMap(value, visit) + target[key] = deepMap(value, visit); } else { - target[key] = visit(value) + target[key] = visit(value); } - }) - return target + }); + return target; } diff --git a/app/scripts/lib/local-store.js b/app/scripts/lib/local-store.js index aa12b50f8..4157a3990 100644 --- a/app/scripts/lib/local-store.js +++ b/app/scripts/lib/local-store.js @@ -1,6 +1,6 @@ -import extension from 'extensionizer' -import log from 'loglevel' -import { checkForError } from './util' +import extension from 'extensionizer'; +import log from 'loglevel'; +import { checkForError } from './util'; /** * A wrapper around the extension's storage local API @@ -10,9 +10,9 @@ export default class ExtensionStore { * @constructor */ constructor() { - this.isSupported = Boolean(extension.storage.local) + this.isSupported = Boolean(extension.storage.local); if (!this.isSupported) { - log.error('Storage local API not available.') + log.error('Storage local API not available.'); } } @@ -22,15 +22,15 @@ export default class ExtensionStore { */ async get() { if (!this.isSupported) { - return undefined + return undefined; } - const result = await this._get() + const result = await this._get(); // extension.storage.local always returns an obj // if the object is empty, treat it as undefined if (isEmpty(result)) { - return undefined + return undefined; } - return result + return result; } /** @@ -39,7 +39,7 @@ export default class ExtensionStore { * @returns {Promise} */ async set(state) { - return this._set(state) + return this._set(state); } /** @@ -48,17 +48,17 @@ export default class ExtensionStore { * @returns {Object} the key-value map from local storage */ _get() { - const { local } = extension.storage + const { local } = extension.storage; return new Promise((resolve, reject) => { local.get(null, (/** @type {any} */ result) => { - const err = checkForError() + const err = checkForError(); if (err) { - reject(err) + reject(err); } else { - resolve(result) + resolve(result); } - }) - }) + }); + }); } /** @@ -68,17 +68,17 @@ export default class ExtensionStore { * @private */ _set(obj) { - const { local } = extension.storage + const { local } = extension.storage; return new Promise((resolve, reject) => { local.set(obj, () => { - const err = checkForError() + const err = checkForError(); if (err) { - reject(err) + reject(err); } else { - resolve() + resolve(); } - }) - }) + }); + }); } } @@ -88,5 +88,5 @@ export default class ExtensionStore { * @returns {boolean} */ function isEmpty(obj) { - return Object.keys(obj).length === 0 + return Object.keys(obj).length === 0; } diff --git a/app/scripts/lib/message-manager.js b/app/scripts/lib/message-manager.js index 0e19c3560..796971208 100644 --- a/app/scripts/lib/message-manager.js +++ b/app/scripts/lib/message-manager.js @@ -1,9 +1,9 @@ -import EventEmitter from 'events' -import { ObservableStore } from '@metamask/obs-store' -import ethUtil from 'ethereumjs-util' -import { ethErrors } from 'eth-rpc-errors' -import { MESSAGE_TYPE } from '../../../shared/constants/app' -import createId from './random-id' +import EventEmitter from 'events'; +import { ObservableStore } from '@metamask/obs-store'; +import ethUtil from 'ethereumjs-util'; +import { ethErrors } from 'eth-rpc-errors'; +import { MESSAGE_TYPE } from '../../../shared/constants/app'; +import createId from './random-id'; /** * Represents, and contains data about, an 'eth_sign' type signature request. These are created when a signature for @@ -35,12 +35,12 @@ export default class MessageManager extends EventEmitter { * */ constructor() { - super() + super(); this.memStore = new ObservableStore({ unapprovedMsgs: {}, unapprovedMsgCount: 0, - }) - this.messages = [] + }); + this.messages = []; } /** @@ -50,7 +50,7 @@ export default class MessageManager extends EventEmitter { * */ get unapprovedMsgCount() { - return Object.keys(this.getUnapprovedMsgs()).length + return Object.keys(this.getUnapprovedMsgs()).length; } /** @@ -63,9 +63,9 @@ export default class MessageManager extends EventEmitter { return this.messages .filter((msg) => msg.status === 'unapproved') .reduce((result, msg) => { - result[msg.id] = msg - return result - }, {}) + result[msg.id] = msg; + return result; + }, {}); } /** @@ -79,18 +79,18 @@ export default class MessageManager extends EventEmitter { */ addUnapprovedMessageAsync(msgParams, req) { return new Promise((resolve, reject) => { - const msgId = this.addUnapprovedMessage(msgParams, req) + const msgId = this.addUnapprovedMessage(msgParams, req); // await finished this.once(`${msgId}:finished`, (data) => { switch (data.status) { case 'signed': - return resolve(data.rawSig) + return resolve(data.rawSig); case 'rejected': return reject( ethErrors.provider.userRejectedRequest( 'MetaMask Message Signature: User denied message signature.', ), - ) + ); default: return reject( new Error( @@ -98,10 +98,10 @@ export default class MessageManager extends EventEmitter { msgParams, )}`, ), - ) + ); } - }) - }) + }); + }); } /** @@ -116,24 +116,24 @@ export default class MessageManager extends EventEmitter { addUnapprovedMessage(msgParams, req) { // add origin from request if (req) { - msgParams.origin = req.origin + msgParams.origin = req.origin; } - msgParams.data = normalizeMsgData(msgParams.data) + msgParams.data = normalizeMsgData(msgParams.data); // create txData obj with parameters and meta data - const time = new Date().getTime() - const msgId = createId() + const time = new Date().getTime(); + const msgId = createId(); const msgData = { id: msgId, msgParams, time, status: 'unapproved', type: MESSAGE_TYPE.ETH_SIGN, - } - this.addMsg(msgData) + }; + this.addMsg(msgData); // signal update - this.emit('update') - return msgId + this.emit('update'); + return msgId; } /** @@ -144,8 +144,8 @@ export default class MessageManager extends EventEmitter { * */ addMsg(msg) { - this.messages.push(msg) - this._saveMsgList() + this.messages.push(msg); + this._saveMsgList(); } /** @@ -156,7 +156,7 @@ export default class MessageManager extends EventEmitter { * */ getMsg(msgId) { - return this.messages.find((msg) => msg.id === msgId) + return this.messages.find((msg) => msg.id === msgId); } /** @@ -169,8 +169,8 @@ export default class MessageManager extends EventEmitter { * */ approveMessage(msgParams) { - this.setMsgStatusApproved(msgParams.metamaskId) - return this.prepMsgForSigning(msgParams) + this.setMsgStatusApproved(msgParams.metamaskId); + return this.prepMsgForSigning(msgParams); } /** @@ -180,7 +180,7 @@ export default class MessageManager extends EventEmitter { * */ setMsgStatusApproved(msgId) { - this._setMsgStatus(msgId, 'approved') + this._setMsgStatus(msgId, 'approved'); } /** @@ -192,10 +192,10 @@ export default class MessageManager extends EventEmitter { * */ setMsgStatusSigned(msgId, rawSig) { - const msg = this.getMsg(msgId) - msg.rawSig = rawSig - this._updateMsg(msg) - this._setMsgStatus(msgId, 'signed') + const msg = this.getMsg(msgId); + msg.rawSig = rawSig; + this._updateMsg(msg); + this._setMsgStatus(msgId, 'signed'); } /** @@ -206,8 +206,8 @@ export default class MessageManager extends EventEmitter { * */ prepMsgForSigning(msgParams) { - delete msgParams.metamaskId - return Promise.resolve(msgParams) + delete msgParams.metamaskId; + return Promise.resolve(msgParams); } /** @@ -217,7 +217,7 @@ export default class MessageManager extends EventEmitter { * */ rejectMsg(msgId) { - this._setMsgStatus(msgId, 'rejected') + this._setMsgStatus(msgId, 'rejected'); } /** @@ -233,15 +233,15 @@ export default class MessageManager extends EventEmitter { * */ _setMsgStatus(msgId, status) { - const msg = this.getMsg(msgId) + const msg = this.getMsg(msgId); if (!msg) { - throw new Error(`MessageManager - Message not found for id: "${msgId}".`) + throw new Error(`MessageManager - Message not found for id: "${msgId}".`); } - msg.status = status - this._updateMsg(msg) - this.emit(`${msgId}:${status}`, msg) + msg.status = status; + this._updateMsg(msg); + this.emit(`${msgId}:${status}`, msg); if (status === 'rejected' || status === 'signed') { - this.emit(`${msgId}:finished`, msg) + this.emit(`${msgId}:finished`, msg); } } @@ -254,11 +254,11 @@ export default class MessageManager extends EventEmitter { * */ _updateMsg(msg) { - const index = this.messages.findIndex((message) => message.id === msg.id) + const index = this.messages.findIndex((message) => message.id === msg.id); if (index !== -1) { - this.messages[index] = msg + this.messages[index] = msg; } - this._saveMsgList() + this._saveMsgList(); } /** @@ -269,10 +269,10 @@ export default class MessageManager extends EventEmitter { * */ _saveMsgList() { - const unapprovedMsgs = this.getUnapprovedMsgs() - const unapprovedMsgCount = Object.keys(unapprovedMsgs).length - this.memStore.updateState({ unapprovedMsgs, unapprovedMsgCount }) - this.emit('updateBadge') + const unapprovedMsgs = this.getUnapprovedMsgs(); + const unapprovedMsgCount = Object.keys(unapprovedMsgs).length; + this.memStore.updateState({ unapprovedMsgs, unapprovedMsgCount }); + this.emit('updateBadge'); } } @@ -286,8 +286,8 @@ export default class MessageManager extends EventEmitter { function normalizeMsgData(data) { if (data.slice(0, 2) === '0x') { // data is already hex - return data + return data; } // data is unicode, convert to hex - return ethUtil.bufferToHex(Buffer.from(data, 'utf8')) + return ethUtil.bufferToHex(Buffer.from(data, 'utf8')); } diff --git a/app/scripts/lib/migrator/index.js b/app/scripts/lib/migrator/index.js index 711acb7c5..258632747 100644 --- a/app/scripts/lib/migrator/index.js +++ b/app/scripts/lib/migrator/index.js @@ -1,4 +1,4 @@ -import EventEmitter from 'events' +import EventEmitter from 'events'; /** * @typedef {Object} Migration @@ -18,29 +18,29 @@ export default class Migrator extends EventEmitter { * @param {MigratorOptions} opts */ constructor(opts = {}) { - super() - const migrations = opts.migrations || [] + super(); + const migrations = opts.migrations || []; // sort migrations by version - this.migrations = migrations.sort((a, b) => a.version - b.version) + this.migrations = migrations.sort((a, b) => a.version - b.version); // grab migration with highest version - const lastMigration = this.migrations.slice(-1)[0] + const lastMigration = this.migrations.slice(-1)[0]; // use specified defaultVersion or highest migration version this.defaultVersion = - opts.defaultVersion || (lastMigration && lastMigration.version) || 0 + opts.defaultVersion || (lastMigration && lastMigration.version) || 0; } // run all pending migrations on meta in place async migrateData(versionedData = this.generateInitialState()) { // get all migrations that have not yet been run - const pendingMigrations = this.migrations.filter(migrationIsPending) + const pendingMigrations = this.migrations.filter(migrationIsPending); // perform each migration for (const migration of pendingMigrations) { try { // attempt migration and validate - const migratedData = await migration.migrate(versionedData) + const migratedData = await migration.migrate(versionedData); if (!migratedData.data) { - throw new Error('Migrator - migration returned empty data') + throw new Error('Migrator - migration returned empty data'); } if ( migratedData.version !== undefined && @@ -48,23 +48,23 @@ export default class Migrator extends EventEmitter { ) { throw new Error( 'Migrator - Migration did not update version number correctly', - ) + ); } // accept the migration as good // eslint-disable-next-line no-param-reassign - versionedData = migratedData + versionedData = migratedData; } catch (err) { // rewrite error message to add context without clobbering stack - const originalErrorMessage = err.message - err.message = `MetaMask Migration Error #${migration.version}: ${originalErrorMessage}` + const originalErrorMessage = err.message; + err.message = `MetaMask Migration Error #${migration.version}: ${originalErrorMessage}`; // emit error instead of throw so as to not break the run (gracefully fail) - this.emit('error', err) + this.emit('error', err); // stop migrating and use state as is - return versionedData + return versionedData; } } - return versionedData + return versionedData; /** * Returns whether or not the migration is pending @@ -75,7 +75,7 @@ export default class Migrator extends EventEmitter { * @returns {boolean} */ function migrationIsPending(migration) { - return migration.version > versionedData.meta.version + return migration.version > versionedData.meta.version; } } @@ -90,6 +90,6 @@ export default class Migrator extends EventEmitter { version: this.defaultVersion, }, data, - } + }; } } diff --git a/app/scripts/lib/network-store.js b/app/scripts/lib/network-store.js index bfa7a8ba4..eddba5fa2 100644 --- a/app/scripts/lib/network-store.js +++ b/app/scripts/lib/network-store.js @@ -1,40 +1,40 @@ -import log from 'loglevel' -import getFetchWithTimeout from '../../../shared/modules/fetch-with-timeout' +import log from 'loglevel'; +import getFetchWithTimeout from '../../../shared/modules/fetch-with-timeout'; -const fetchWithTimeout = getFetchWithTimeout(30000) +const fetchWithTimeout = getFetchWithTimeout(30000); -const FIXTURE_SERVER_HOST = 'localhost' -const FIXTURE_SERVER_PORT = 12345 -const FIXTURE_SERVER_URL = `http://${FIXTURE_SERVER_HOST}:${FIXTURE_SERVER_PORT}/state.json` +const FIXTURE_SERVER_HOST = 'localhost'; +const FIXTURE_SERVER_PORT = 12345; +const FIXTURE_SERVER_URL = `http://${FIXTURE_SERVER_HOST}:${FIXTURE_SERVER_PORT}/state.json`; /** * A read-only network-based storage wrapper */ export default class ReadOnlyNetworkStore { constructor() { - this._initialized = false - this._initializing = this._init() - this._state = undefined + this._initialized = false; + this._initializing = this._init(); + this._state = undefined; } /** * Declares this store as compatible with the current browser */ - isSupported = true + isSupported = true; /** * Initializes by loading state from the network */ async _init() { try { - const response = await fetchWithTimeout(FIXTURE_SERVER_URL) + const response = await fetchWithTimeout(FIXTURE_SERVER_URL); if (response.ok) { - this._state = await response.json() + this._state = await response.json(); } } catch (error) { - log.debug(`Error loading network state: '${error.message}'`) + log.debug(`Error loading network state: '${error.message}'`); } finally { - this._initialized = true + this._initialized = true; } } @@ -44,9 +44,9 @@ export default class ReadOnlyNetworkStore { */ async get() { if (!this._initialized) { - await this._initializing + await this._initializing; } - return this._state + return this._state; } /** @@ -56,8 +56,8 @@ export default class ReadOnlyNetworkStore { */ async set(state) { if (!this._initialized) { - await this._initializing + await this._initializing; } - this._state = state + this._state = state; } } diff --git a/app/scripts/lib/nodeify.js b/app/scripts/lib/nodeify.js index 5e6f46309..ab222e437 100644 --- a/app/scripts/lib/nodeify.js +++ b/app/scripts/lib/nodeify.js @@ -1,10 +1,10 @@ -import promiseToCallback from 'promise-to-callback' +import promiseToCallback from 'promise-to-callback'; const callbackNoop = function (err) { if (err) { - throw err + throw err; } -} +}; /** * A generator that returns a function which, when passed a promise, can treat that promise as a node style callback. @@ -16,23 +16,23 @@ const callbackNoop = function (err) { */ export default function nodeify(fn, context) { return function (...args) { - const lastArg = args[args.length - 1] - const lastArgIsCallback = typeof lastArg === 'function' - let callback + const lastArg = args[args.length - 1]; + const lastArgIsCallback = typeof lastArg === 'function'; + let callback; if (lastArgIsCallback) { - callback = lastArg - args.pop() + callback = lastArg; + args.pop(); } else { - callback = callbackNoop + callback = callbackNoop; } // call the provided function and ensure result is a promise - let result + let result; try { - result = Promise.resolve(fn.apply(context, args)) + result = Promise.resolve(fn.apply(context, args)); } catch (err) { - result = Promise.reject(err) + result = Promise.reject(err); } // wire up promise resolution to callback - promiseToCallback(result)(callback) - } + promiseToCallback(result)(callback); + }; } diff --git a/app/scripts/lib/notification-manager.js b/app/scripts/lib/notification-manager.js index eab217083..d7a7a89e0 100644 --- a/app/scripts/lib/notification-manager.js +++ b/app/scripts/lib/notification-manager.js @@ -1,7 +1,7 @@ -import ExtensionPlatform from '../platforms/extension' +import ExtensionPlatform from '../platforms/extension'; -const NOTIFICATION_HEIGHT = 620 -const NOTIFICATION_WIDTH = 360 +const NOTIFICATION_HEIGHT = 620; +const NOTIFICATION_WIDTH = 360; export default class NotificationManager { /** @@ -12,7 +12,7 @@ export default class NotificationManager { */ constructor() { - this.platform = new ExtensionPlatform() + this.platform = new ExtensionPlatform(); } /** @@ -21,27 +21,27 @@ export default class NotificationManager { * */ async showPopup() { - const popup = await this._getPopup() + const popup = await this._getPopup(); // Bring focus to chrome popup if (popup) { // bring focus to existing chrome popup - await this.platform.focusWindow(popup.id) + await this.platform.focusWindow(popup.id); } else { - let left = 0 - let top = 0 + let left = 0; + let top = 0; try { - const lastFocused = await this.platform.getLastFocusedWindow() + const lastFocused = await this.platform.getLastFocusedWindow(); // Position window in top right corner of lastFocused window. - top = lastFocused.top - left = lastFocused.left + (lastFocused.width - NOTIFICATION_WIDTH) + top = lastFocused.top; + left = lastFocused.left + (lastFocused.width - NOTIFICATION_WIDTH); } catch (_) { // The following properties are more than likely 0, due to being // opened from the background chrome process for the extension that // has no physical dimensions - const { screenX, screenY, outerWidth } = window - top = Math.max(screenY, 0) - left = Math.max(screenX + (outerWidth - NOTIFICATION_WIDTH), 0) + const { screenX, screenY, outerWidth } = window; + top = Math.max(screenY, 0); + left = Math.max(screenX + (outerWidth - NOTIFICATION_WIDTH), 0); } // create new notification popup @@ -52,13 +52,13 @@ export default class NotificationManager { height: NOTIFICATION_HEIGHT, left, top, - }) + }); // Firefox currently ignores left/top for create, but it works for update if (popupWindow.left !== left && popupWindow.state !== 'fullscreen') { - await this.platform.updateWindowPosition(popupWindow.id, left, top) + await this.platform.updateWindowPosition(popupWindow.id, left, top); } - this._popupId = popupWindow.id + this._popupId = popupWindow.id; } } @@ -71,8 +71,8 @@ export default class NotificationManager { * */ async _getPopup() { - const windows = await this.platform.getAllWindows() - return this._getPopupIn(windows) + const windows = await this.platform.getAllWindows(); + return this._getPopupIn(windows); } /** @@ -86,8 +86,8 @@ export default class NotificationManager { return windows ? windows.find((win) => { // Returns notification popup - return win && win.type === 'popup' && win.id === this._popupId + return win && win.type === 'popup' && win.id === this._popupId; }) - : null + : null; } } diff --git a/app/scripts/lib/personal-message-manager.js b/app/scripts/lib/personal-message-manager.js index c0a7fe4bf..66474c8c4 100644 --- a/app/scripts/lib/personal-message-manager.js +++ b/app/scripts/lib/personal-message-manager.js @@ -1,13 +1,13 @@ -import EventEmitter from 'events' -import { ObservableStore } from '@metamask/obs-store' -import ethUtil from 'ethereumjs-util' -import { ethErrors } from 'eth-rpc-errors' -import log from 'loglevel' -import { MESSAGE_TYPE } from '../../../shared/constants/app' -import { addHexPrefix } from './util' -import createId from './random-id' +import EventEmitter from 'events'; +import { ObservableStore } from '@metamask/obs-store'; +import ethUtil from 'ethereumjs-util'; +import { ethErrors } from 'eth-rpc-errors'; +import log from 'loglevel'; +import { MESSAGE_TYPE } from '../../../shared/constants/app'; +import { addHexPrefix } from './util'; +import createId from './random-id'; -const hexRe = /^[0-9A-Fa-f]+$/gu +const hexRe = /^[0-9A-Fa-f]+$/gu; /** * Represents, and contains data about, an 'personal_sign' type signature request. These are created when a @@ -40,12 +40,12 @@ export default class PersonalMessageManager extends EventEmitter { * */ constructor() { - super() + super(); this.memStore = new ObservableStore({ unapprovedPersonalMsgs: {}, unapprovedPersonalMsgCount: 0, - }) - this.messages = [] + }); + this.messages = []; } /** @@ -55,7 +55,7 @@ export default class PersonalMessageManager extends EventEmitter { * */ get unapprovedPersonalMsgCount() { - return Object.keys(this.getUnapprovedMsgs()).length + return Object.keys(this.getUnapprovedMsgs()).length; } /** @@ -69,9 +69,9 @@ export default class PersonalMessageManager extends EventEmitter { return this.messages .filter((msg) => msg.status === 'unapproved') .reduce((result, msg) => { - result[msg.id] = msg - return result - }, {}) + result[msg.id] = msg; + return result; + }, {}); } /** @@ -87,22 +87,24 @@ export default class PersonalMessageManager extends EventEmitter { addUnapprovedMessageAsync(msgParams, req) { return new Promise((resolve, reject) => { if (!msgParams.from) { - reject(new Error('MetaMask Message Signature: from field is required.')) - return + reject( + new Error('MetaMask Message Signature: from field is required.'), + ); + return; } - const msgId = this.addUnapprovedMessage(msgParams, req) + const msgId = this.addUnapprovedMessage(msgParams, req); this.once(`${msgId}:finished`, (data) => { switch (data.status) { case 'signed': - resolve(data.rawSig) - return + resolve(data.rawSig); + return; case 'rejected': reject( ethErrors.provider.userRejectedRequest( 'MetaMask Message Signature: User denied message signature.', ), - ) - return + ); + return; default: reject( new Error( @@ -110,10 +112,10 @@ export default class PersonalMessageManager extends EventEmitter { msgParams, )}`, ), - ) + ); } - }) - }) + }); + }); } /** @@ -131,27 +133,27 @@ export default class PersonalMessageManager extends EventEmitter { `PersonalMessageManager addUnapprovedMessage: ${JSON.stringify( msgParams, )}`, - ) + ); // add origin from request if (req) { - msgParams.origin = req.origin + msgParams.origin = req.origin; } - msgParams.data = this.normalizeMsgData(msgParams.data) + msgParams.data = this.normalizeMsgData(msgParams.data); // create txData obj with parameters and meta data - const time = new Date().getTime() - const msgId = createId() + const time = new Date().getTime(); + const msgId = createId(); const msgData = { id: msgId, msgParams, time, status: 'unapproved', type: MESSAGE_TYPE.PERSONAL_SIGN, - } - this.addMsg(msgData) + }; + this.addMsg(msgData); // signal update - this.emit('update') - return msgId + this.emit('update'); + return msgId; } /** @@ -162,8 +164,8 @@ export default class PersonalMessageManager extends EventEmitter { * */ addMsg(msg) { - this.messages.push(msg) - this._saveMsgList() + this.messages.push(msg); + this._saveMsgList(); } /** @@ -175,7 +177,7 @@ export default class PersonalMessageManager extends EventEmitter { * */ getMsg(msgId) { - return this.messages.find((msg) => msg.id === msgId) + return this.messages.find((msg) => msg.id === msgId); } /** @@ -188,8 +190,8 @@ export default class PersonalMessageManager extends EventEmitter { * */ approveMessage(msgParams) { - this.setMsgStatusApproved(msgParams.metamaskId) - return this.prepMsgForSigning(msgParams) + this.setMsgStatusApproved(msgParams.metamaskId); + return this.prepMsgForSigning(msgParams); } /** @@ -199,7 +201,7 @@ export default class PersonalMessageManager extends EventEmitter { * */ setMsgStatusApproved(msgId) { - this._setMsgStatus(msgId, 'approved') + this._setMsgStatus(msgId, 'approved'); } /** @@ -211,10 +213,10 @@ export default class PersonalMessageManager extends EventEmitter { * */ setMsgStatusSigned(msgId, rawSig) { - const msg = this.getMsg(msgId) - msg.rawSig = rawSig - this._updateMsg(msg) - this._setMsgStatus(msgId, 'signed') + const msg = this.getMsg(msgId); + msg.rawSig = rawSig; + this._updateMsg(msg); + this._setMsgStatus(msgId, 'signed'); } /** @@ -225,8 +227,8 @@ export default class PersonalMessageManager extends EventEmitter { * */ prepMsgForSigning(msgParams) { - delete msgParams.metamaskId - return Promise.resolve(msgParams) + delete msgParams.metamaskId; + return Promise.resolve(msgParams); } /** @@ -236,7 +238,7 @@ export default class PersonalMessageManager extends EventEmitter { * */ rejectMsg(msgId) { - this._setMsgStatus(msgId, 'rejected') + this._setMsgStatus(msgId, 'rejected'); } /** @@ -253,17 +255,17 @@ export default class PersonalMessageManager extends EventEmitter { * */ _setMsgStatus(msgId, status) { - const msg = this.getMsg(msgId) + const msg = this.getMsg(msgId); if (!msg) { throw new Error( `PersonalMessageManager - Message not found for id: "${msgId}".`, - ) + ); } - msg.status = status - this._updateMsg(msg) - this.emit(`${msgId}:${status}`, msg) + msg.status = status; + this._updateMsg(msg); + this.emit(`${msgId}:${status}`, msg); if (status === 'rejected' || status === 'signed') { - this.emit(`${msgId}:finished`, msg) + this.emit(`${msgId}:finished`, msg); } } @@ -277,11 +279,11 @@ export default class PersonalMessageManager extends EventEmitter { * */ _updateMsg(msg) { - const index = this.messages.findIndex((message) => message.id === msg.id) + const index = this.messages.findIndex((message) => message.id === msg.id); if (index !== -1) { - this.messages[index] = msg + this.messages[index] = msg; } - this._saveMsgList() + this._saveMsgList(); } /** @@ -292,14 +294,14 @@ export default class PersonalMessageManager extends EventEmitter { * */ _saveMsgList() { - const unapprovedPersonalMsgs = this.getUnapprovedMsgs() + const unapprovedPersonalMsgs = this.getUnapprovedMsgs(); const unapprovedPersonalMsgCount = Object.keys(unapprovedPersonalMsgs) - .length + .length; this.memStore.updateState({ unapprovedPersonalMsgs, unapprovedPersonalMsgCount, - }) - this.emit('updateBadge') + }); + this.emit('updateBadge'); } /** @@ -311,14 +313,14 @@ export default class PersonalMessageManager extends EventEmitter { */ normalizeMsgData(data) { try { - const stripped = ethUtil.stripHexPrefix(data) + const stripped = ethUtil.stripHexPrefix(data); if (stripped.match(hexRe)) { - return addHexPrefix(stripped) + return addHexPrefix(stripped); } } catch (e) { - log.debug(`Message was not hex encoded, interpreting as utf8.`) + log.debug(`Message was not hex encoded, interpreting as utf8.`); } - return ethUtil.bufferToHex(Buffer.from(data, 'utf8')) + return ethUtil.bufferToHex(Buffer.from(data, 'utf8')); } } diff --git a/app/scripts/lib/random-id.js b/app/scripts/lib/random-id.js index a21717a2b..7bc70b0e9 100644 --- a/app/scripts/lib/random-id.js +++ b/app/scripts/lib/random-id.js @@ -1,8 +1,8 @@ -const MAX = Number.MAX_SAFE_INTEGER +const MAX = Number.MAX_SAFE_INTEGER; -let idCounter = Math.round(Math.random() * MAX) +let idCounter = Math.round(Math.random() * MAX); export default function createRandomId() { - idCounter %= MAX + idCounter %= MAX; // eslint-disable-next-line no-plusplus - return idCounter++ + return idCounter++; } diff --git a/app/scripts/lib/rpc-method-middleware/createMethodMiddleware.js b/app/scripts/lib/rpc-method-middleware/createMethodMiddleware.js index fdbc265e9..ea2370217 100644 --- a/app/scripts/lib/rpc-method-middleware/createMethodMiddleware.js +++ b/app/scripts/lib/rpc-method-middleware/createMethodMiddleware.js @@ -1,11 +1,11 @@ -import handlers from './handlers' +import handlers from './handlers'; const handlerMap = handlers.reduce((map, handler) => { for (const methodName of handler.methodNames) { - map.set(methodName, handler.implementation) + map.set(methodName, handler.implementation); } - return map -}, new Map()) + return map; +}, new Map()); /** * Returns a middleware that implements the RPC methods defined in the handlers @@ -27,8 +27,8 @@ const handlerMap = handlers.reduce((map, handler) => { export default function createMethodMiddleware(opts) { return function methodMiddleware(req, res, next, end) { if (handlerMap.has(req.method)) { - return handlerMap.get(req.method)(req, res, next, end, opts) + return handlerMap.get(req.method)(req, res, next, end, opts); } - return next() - } + return next(); + }; } diff --git a/app/scripts/lib/rpc-method-middleware/handlers/get-provider-state.js b/app/scripts/lib/rpc-method-middleware/handlers/get-provider-state.js index 760517e10..c38933b0d 100644 --- a/app/scripts/lib/rpc-method-middleware/handlers/get-provider-state.js +++ b/app/scripts/lib/rpc-method-middleware/handlers/get-provider-state.js @@ -1,4 +1,4 @@ -import { MESSAGE_TYPE } from '../../../../../shared/constants/app' +import { MESSAGE_TYPE } from '../../../../../shared/constants/app'; /** * This RPC method gets background state relevant to the provider. @@ -9,8 +9,8 @@ import { MESSAGE_TYPE } from '../../../../../shared/constants/app' const getProviderState = { methodNames: [MESSAGE_TYPE.GET_PROVIDER_STATE], implementation: getProviderStateHandler, -} -export default getProviderState +}; +export default getProviderState; /** * @typedef {Object} ProviderStateHandlerResult @@ -41,6 +41,6 @@ async function getProviderStateHandler( ) { res.result = { ...(await _getProviderState(req.origin)), - } - return end() + }; + return end(); } diff --git a/app/scripts/lib/rpc-method-middleware/handlers/index.js b/app/scripts/lib/rpc-method-middleware/handlers/index.js index 41011778a..e292e0cdd 100644 --- a/app/scripts/lib/rpc-method-middleware/handlers/index.js +++ b/app/scripts/lib/rpc-method-middleware/handlers/index.js @@ -1,6 +1,6 @@ -import getProviderState from './get-provider-state' -import logWeb3ShimUsage from './log-web3-shim-usage' -import watchAsset from './watch-asset' +import getProviderState from './get-provider-state'; +import logWeb3ShimUsage from './log-web3-shim-usage'; +import watchAsset from './watch-asset'; -const handlers = [getProviderState, logWeb3ShimUsage, watchAsset] -export default handlers +const handlers = [getProviderState, logWeb3ShimUsage, watchAsset]; +export default handlers; diff --git a/app/scripts/lib/rpc-method-middleware/handlers/log-web3-shim-usage.js b/app/scripts/lib/rpc-method-middleware/handlers/log-web3-shim-usage.js index 8dd1551fd..973d03f61 100644 --- a/app/scripts/lib/rpc-method-middleware/handlers/log-web3-shim-usage.js +++ b/app/scripts/lib/rpc-method-middleware/handlers/log-web3-shim-usage.js @@ -1,4 +1,4 @@ -import { MESSAGE_TYPE } from '../../../../../shared/constants/app' +import { MESSAGE_TYPE } from '../../../../../shared/constants/app'; /** * This RPC method is called by the inpage provider whenever it detects the @@ -10,8 +10,8 @@ import { MESSAGE_TYPE } from '../../../../../shared/constants/app' const logWeb3ShimUsage = { methodNames: [MESSAGE_TYPE.LOG_WEB3_SHIM_USAGE], implementation: logWeb3ShimUsageHandler, -} -export default logWeb3ShimUsage +}; +export default logWeb3ShimUsage; /** * @typedef {Object} LogWeb3ShimUsageOptions @@ -36,9 +36,9 @@ function logWeb3ShimUsageHandler( end, { sendMetrics, getWeb3ShimUsageState, setWeb3ShimUsageRecorded }, ) { - const { origin } = req + const { origin } = req; if (getWeb3ShimUsageState(origin) === undefined) { - setWeb3ShimUsageRecorded(origin) + setWeb3ShimUsageRecorded(origin); sendMetrics( { @@ -51,9 +51,9 @@ function logWeb3ShimUsageHandler( { excludeMetaMetricsId: true, }, - ) + ); } - res.result = true - return end() + res.result = true; + return end(); } diff --git a/app/scripts/lib/rpc-method-middleware/handlers/watch-asset.js b/app/scripts/lib/rpc-method-middleware/handlers/watch-asset.js index 60c8ad6da..aebcae891 100644 --- a/app/scripts/lib/rpc-method-middleware/handlers/watch-asset.js +++ b/app/scripts/lib/rpc-method-middleware/handlers/watch-asset.js @@ -1,10 +1,10 @@ -import { MESSAGE_TYPE } from '../../../../../shared/constants/app' +import { MESSAGE_TYPE } from '../../../../../shared/constants/app'; const watchAsset = { methodNames: [MESSAGE_TYPE.WATCH_ASSET, MESSAGE_TYPE.WATCH_ASSET_LEGACY], implementation: watchAssetHandler, -} -export default watchAsset +}; +export default watchAsset; /** * @typedef {Object} WatchAssetOptions @@ -32,9 +32,9 @@ async function watchAssetHandler( { handleWatchAssetRequest }, ) { try { - res.result = await handleWatchAssetRequest(req) - return end() + res.result = await handleWatchAssetRequest(req); + return end(); } catch (error) { - return end(error) + return end(error); } } diff --git a/app/scripts/lib/rpc-method-middleware/index.js b/app/scripts/lib/rpc-method-middleware/index.js index 224e060bd..b0f813570 100644 --- a/app/scripts/lib/rpc-method-middleware/index.js +++ b/app/scripts/lib/rpc-method-middleware/index.js @@ -1 +1 @@ -export { default } from './createMethodMiddleware' +export { default } from './createMethodMiddleware'; diff --git a/app/scripts/lib/seed-phrase-verifier.js b/app/scripts/lib/seed-phrase-verifier.js index 8c3e778a0..35b6980a5 100644 --- a/app/scripts/lib/seed-phrase-verifier.js +++ b/app/scripts/lib/seed-phrase-verifier.js @@ -1,5 +1,5 @@ -import KeyringController from 'eth-keyring-controller' -import log from 'loglevel' +import KeyringController from 'eth-keyring-controller'; +import log from 'loglevel'; const seedPhraseVerifier = { /** @@ -17,24 +17,24 @@ const seedPhraseVerifier = { */ async verifyAccounts(createdAccounts, seedWords) { if (!createdAccounts || createdAccounts.length < 1) { - throw new Error('No created accounts defined.') + throw new Error('No created accounts defined.'); } - const keyringController = new KeyringController({}) - const Keyring = keyringController.getKeyringClassForType('HD Key Tree') + const keyringController = new KeyringController({}); + const Keyring = keyringController.getKeyringClassForType('HD Key Tree'); const opts = { mnemonic: seedWords, numberOfAccounts: createdAccounts.length, - } + }; - const keyring = new Keyring(opts) - const restoredAccounts = await keyring.getAccounts() - log.debug(`Created accounts: ${JSON.stringify(createdAccounts)}`) - log.debug(`Restored accounts: ${JSON.stringify(restoredAccounts)}`) + const keyring = new Keyring(opts); + const restoredAccounts = await keyring.getAccounts(); + log.debug(`Created accounts: ${JSON.stringify(createdAccounts)}`); + log.debug(`Restored accounts: ${JSON.stringify(restoredAccounts)}`); if (restoredAccounts.length !== createdAccounts.length) { // this should not happen... - throw new Error('Wrong number of accounts') + throw new Error('Wrong number of accounts'); } for (let i = 0; i < restoredAccounts.length; i++) { @@ -43,10 +43,10 @@ const seedPhraseVerifier = { ) { throw new Error( `Not identical accounts! Original: ${createdAccounts[i]}, Restored: ${restoredAccounts[i]}`, - ) + ); } } }, -} +}; -export default seedPhraseVerifier +export default seedPhraseVerifier; diff --git a/app/scripts/lib/segment.js b/app/scripts/lib/segment.js index e5b67ab18..fa88128c8 100644 --- a/app/scripts/lib/segment.js +++ b/app/scripts/lib/segment.js @@ -1,11 +1,11 @@ -import Analytics from 'analytics-node' +import Analytics from 'analytics-node'; const isDevOrTestEnvironment = Boolean( process.env.METAMASK_DEBUG || process.env.IN_TEST, -) -const SEGMENT_WRITE_KEY = process.env.SEGMENT_WRITE_KEY ?? null -const SEGMENT_LEGACY_WRITE_KEY = process.env.SEGMENT_LEGACY_WRITE_KEY ?? null -const SEGMENT_HOST = process.env.SEGMENT_HOST ?? null +); +const SEGMENT_WRITE_KEY = process.env.SEGMENT_WRITE_KEY ?? null; +const SEGMENT_LEGACY_WRITE_KEY = process.env.SEGMENT_LEGACY_WRITE_KEY ?? null; +const SEGMENT_HOST = process.env.SEGMENT_HOST ?? null; // flushAt controls how many events are sent to segment at once. Segment will // hold onto a queue of events until it hits this number, then it sends them as @@ -13,7 +13,7 @@ const SEGMENT_HOST = process.env.SEGMENT_HOST ?? null // see events in real time for debugging, so this is set to 1 to disable the // queueing mechanism. const SEGMENT_FLUSH_AT = - process.env.METAMASK_ENVIRONMENT === 'production' ? undefined : 1 + process.env.METAMASK_ENVIRONMENT === 'production' ? undefined : 1; // flushInterval controls how frequently the queue is flushed to segment. // This happens regardless of the size of the queue. The default setting is @@ -22,7 +22,7 @@ const SEGMENT_FLUSH_AT = // deal with short lived sessions that happen faster than the interval // e.g confirmations. This is set to 5,000ms (5 seconds) arbitrarily with the // intent of having a value less than 10 seconds. -const SEGMENT_FLUSH_INTERVAL = 5000 +const SEGMENT_FLUSH_INTERVAL = 5000; /** * Creates a mock segment module for usage in test environments. This is used @@ -49,9 +49,9 @@ export const createSegmentMock = ( */ flush() { segmentMock.queue.forEach(([_, callback]) => { - callback() - }) - segmentMock.queue = [] + callback(); + }); + segmentMock.queue = []; }, /** @@ -59,10 +59,10 @@ export const createSegmentMock = ( * flushAt threshold, flush the queue. */ track(payload, callback = () => undefined) { - segmentMock.queue.push([payload, callback]) + segmentMock.queue.push([payload, callback]); if (segmentMock.queue.length >= flushAt) { - segmentMock.flush() + segmentMock.flush(); } }, @@ -76,11 +76,11 @@ export const createSegmentMock = ( identify() { // noop }, - } + }; // Mimic the flushInterval behavior with an interval - setInterval(segmentMock.flush, flushInterval) - return segmentMock -} + setInterval(segmentMock.flush, flushInterval); + return segmentMock; +}; export const segment = !SEGMENT_WRITE_KEY || (isDevOrTestEnvironment && !SEGMENT_HOST) @@ -89,7 +89,7 @@ export const segment = host: SEGMENT_HOST, flushAt: SEGMENT_FLUSH_AT, flushInterval: SEGMENT_FLUSH_INTERVAL, - }) + }); export const segmentLegacy = !SEGMENT_LEGACY_WRITE_KEY || (isDevOrTestEnvironment && !SEGMENT_HOST) @@ -98,4 +98,4 @@ export const segmentLegacy = host: SEGMENT_HOST, flushAt: SEGMENT_FLUSH_AT, flushInterval: SEGMENT_FLUSH_INTERVAL, - }) + }); diff --git a/app/scripts/lib/setupFetchDebugging.js b/app/scripts/lib/setupFetchDebugging.js index 8b566c31d..724500b9b 100644 --- a/app/scripts/lib/setupFetchDebugging.js +++ b/app/scripts/lib/setupFetchDebugging.js @@ -6,36 +6,36 @@ export default function setupFetchDebugging() { if (!window.fetch) { - return + return; } - const originalFetch = window.fetch + const originalFetch = window.fetch; - window.fetch = wrappedFetch + window.fetch = wrappedFetch; async function wrappedFetch(...args) { - const initialStack = getCurrentStack() + const initialStack = getCurrentStack(); try { - return await originalFetch.call(window, ...args) + return await originalFetch.call(window, ...args); } catch (err) { if (!err.stack) { console.warn( 'FetchDebugger - fetch encountered an Error without a stack', err, - ) + ); console.warn( 'FetchDebugger - overriding stack to point of original call', - ) - err.stack = initialStack + ); + err.stack = initialStack; } - throw err + throw err; } } } function getCurrentStack() { try { - throw new Error('Fake error for generating stack trace') + throw new Error('Fake error for generating stack trace'); } catch (err) { - return err.stack + return err.stack; } } diff --git a/app/scripts/lib/setupSentry.js b/app/scripts/lib/setupSentry.js index 1deb4c94b..eace3f918 100644 --- a/app/scripts/lib/setupSentry.js +++ b/app/scripts/lib/setupSentry.js @@ -1,15 +1,15 @@ -import * as Sentry from '@sentry/browser' -import { Dedupe, ExtraErrorData } from '@sentry/integrations' +import * as Sentry from '@sentry/browser'; +import { Dedupe, ExtraErrorData } from '@sentry/integrations'; -import extractEthjsErrorMessage from './extractEthjsErrorMessage' +import extractEthjsErrorMessage from './extractEthjsErrorMessage'; /* eslint-disable prefer-destructuring */ // Destructuring breaks the inlining of the environment variables -const METAMASK_DEBUG = process.env.METAMASK_DEBUG -const METAMASK_ENVIRONMENT = process.env.METAMASK_ENVIRONMENT +const METAMASK_DEBUG = process.env.METAMASK_DEBUG; +const METAMASK_ENVIRONMENT = process.env.METAMASK_ENVIRONMENT; /* eslint-enable prefer-destructuring */ const SENTRY_DSN_DEV = - 'https://f59f3dd640d2429d9d0e2445a87ea8e1@sentry.io/273496' + 'https://f59f3dd640d2429d9d0e2445a87ea8e1@sentry.io/273496'; // This describes the subset of Redux state attached to errors sent to Sentry // These properties have some potential to be useful for debugging, and they do @@ -65,28 +65,28 @@ export const SENTRY_STATE = { welcomeScreenSeen: true, }, unconnectedAccount: true, -} +}; export default function setupSentry({ release, getState }) { - let sentryTarget + let sentryTarget; if (METAMASK_DEBUG) { - return undefined + return undefined; } else if (METAMASK_ENVIRONMENT === 'production') { if (!process.env.SENTRY_DSN) { throw new Error( `Missing SENTRY_DSN environment variable in production environment`, - ) + ); } console.log( `Setting up Sentry Remote Error Reporting for '${METAMASK_ENVIRONMENT}': SENTRY_DSN`, - ) - sentryTarget = process.env.SENTRY_DSN + ); + sentryTarget = process.env.SENTRY_DSN; } else { console.log( `Setting up Sentry Remote Error Reporting for '${METAMASK_ENVIRONMENT}': SENTRY_DSN_DEV`, - ) - sentryTarget = SENTRY_DSN_DEV + ); + sentryTarget = SENTRY_DSN_DEV; } Sentry.init({ @@ -96,35 +96,35 @@ export default function setupSentry({ release, getState }) { integrations: [new Dedupe(), new ExtraErrorData()], release, beforeSend: (report) => rewriteReport(report), - }) + }); function rewriteReport(report) { try { // simplify certain complex error messages (e.g. Ethjs) - simplifyErrorMessages(report) + simplifyErrorMessages(report); // modify report urls - rewriteReportUrls(report) + rewriteReportUrls(report); // append app state if (getState) { - const appState = getState() + const appState = getState(); if (!report.extra) { - report.extra = {} + report.extra = {}; } - report.extra.appState = appState + report.extra.appState = appState; } } catch (err) { - console.warn(err) + console.warn(err); } - return report + return report; } - return Sentry + return Sentry; } function simplifyErrorMessages(report) { rewriteErrorMessages(report, (errorMessage) => { // simplify ethjs error messages - let simplifiedErrorMessage = extractEthjsErrorMessage(errorMessage) + let simplifiedErrorMessage = extractEthjsErrorMessage(errorMessage); // simplify 'Transaction Failed: known transaction' if ( simplifiedErrorMessage.indexOf( @@ -132,47 +132,47 @@ function simplifyErrorMessages(report) { ) === 0 ) { // cut the hash from the error message - simplifiedErrorMessage = 'Transaction Failed: known transaction' + simplifiedErrorMessage = 'Transaction Failed: known transaction'; } - return simplifiedErrorMessage - }) + return simplifiedErrorMessage; + }); } function rewriteErrorMessages(report, rewriteFn) { // rewrite top level message if (typeof report.message === 'string') { - report.message = rewriteFn(report.message) + report.message = rewriteFn(report.message); } // rewrite each exception message if (report.exception && report.exception.values) { report.exception.values.forEach((item) => { if (typeof item.value === 'string') { - item.value = rewriteFn(item.value) + item.value = rewriteFn(item.value); } - }) + }); } } function rewriteReportUrls(report) { // update request url - report.request.url = toMetamaskUrl(report.request.url) + report.request.url = toMetamaskUrl(report.request.url); // update exception stack trace if (report.exception && report.exception.values) { report.exception.values.forEach((item) => { if (item.stacktrace) { item.stacktrace.frames.forEach((frame) => { - frame.filename = toMetamaskUrl(frame.filename) - }) + frame.filename = toMetamaskUrl(frame.filename); + }); } - }) + }); } } function toMetamaskUrl(origUrl) { - const filePath = origUrl.split(window.location.origin)[1] + const filePath = origUrl.split(window.location.origin)[1]; if (!filePath) { - return origUrl + return origUrl; } - const metamaskUrl = `metamask${filePath}` - return metamaskUrl + const metamaskUrl = `metamask${filePath}`; + return metamaskUrl; } diff --git a/app/scripts/lib/stream-utils.js b/app/scripts/lib/stream-utils.js index a34245ae4..80b228e17 100644 --- a/app/scripts/lib/stream-utils.js +++ b/app/scripts/lib/stream-utils.js @@ -1,5 +1,5 @@ -import ObjectMultiplex from 'obj-multiplex' -import pump from 'pump' +import ObjectMultiplex from 'obj-multiplex'; +import pump from 'pump'; /** * Sets up stream multiplexing for the given stream @@ -7,11 +7,11 @@ import pump from 'pump' * @returns {stream.Stream} the multiplexed stream */ export function setupMultiplex(connectionStream) { - const mux = new ObjectMultiplex() + const mux = new ObjectMultiplex(); pump(connectionStream, mux, connectionStream, (err) => { if (err) { - console.error(err) + console.error(err); } - }) - return mux + }); + return mux; } diff --git a/app/scripts/lib/typed-message-manager.js b/app/scripts/lib/typed-message-manager.js index 858c945b0..630e6029c 100644 --- a/app/scripts/lib/typed-message-manager.js +++ b/app/scripts/lib/typed-message-manager.js @@ -1,13 +1,13 @@ -import EventEmitter from 'events' -import assert from 'assert' -import { ObservableStore } from '@metamask/obs-store' -import { ethErrors } from 'eth-rpc-errors' -import { typedSignatureHash, TYPED_MESSAGE_SCHEMA } from 'eth-sig-util' -import { isValidAddress } from 'ethereumjs-util' -import log from 'loglevel' -import jsonschema from 'jsonschema' -import { MESSAGE_TYPE } from '../../../shared/constants/app' -import createId from './random-id' +import EventEmitter from 'events'; +import assert from 'assert'; +import { ObservableStore } from '@metamask/obs-store'; +import { ethErrors } from 'eth-rpc-errors'; +import { typedSignatureHash, TYPED_MESSAGE_SCHEMA } from 'eth-sig-util'; +import { isValidAddress } from 'ethereumjs-util'; +import log from 'loglevel'; +import jsonschema from 'jsonschema'; +import { MESSAGE_TYPE } from '../../../shared/constants/app'; +import createId from './random-id'; /** * Represents, and contains data about, an 'eth_signTypedData' type signature request. These are created when a @@ -32,13 +32,13 @@ export default class TypedMessageManager extends EventEmitter { * Controller in charge of managing - storing, adding, removing, updating - TypedMessage. */ constructor({ getCurrentChainId }) { - super() - this._getCurrentChainId = getCurrentChainId + super(); + this._getCurrentChainId = getCurrentChainId; this.memStore = new ObservableStore({ unapprovedTypedMessages: {}, unapprovedTypedMessagesCount: 0, - }) - this.messages = [] + }); + this.messages = []; } /** @@ -48,7 +48,7 @@ export default class TypedMessageManager extends EventEmitter { * */ get unapprovedTypedMessagesCount() { - return Object.keys(this.getUnapprovedMsgs()).length + return Object.keys(this.getUnapprovedMsgs()).length; } /** @@ -62,9 +62,9 @@ export default class TypedMessageManager extends EventEmitter { return this.messages .filter((msg) => msg.status === 'unapproved') .reduce((result, msg) => { - result[msg.id] = msg - return result - }, {}) + result[msg.id] = msg; + return result; + }, {}); } /** @@ -79,21 +79,21 @@ export default class TypedMessageManager extends EventEmitter { */ addUnapprovedMessageAsync(msgParams, req, version) { return new Promise((resolve, reject) => { - const msgId = this.addUnapprovedMessage(msgParams, req, version) + const msgId = this.addUnapprovedMessage(msgParams, req, version); this.once(`${msgId}:finished`, (data) => { switch (data.status) { case 'signed': - return resolve(data.rawSig) + return resolve(data.rawSig); case 'rejected': return reject( ethErrors.provider.userRejectedRequest( 'MetaMask Message Signature: User denied message signature.', ), - ) + ); case 'errored': return reject( new Error(`MetaMask Message Signature: ${data.error}`), - ) + ); default: return reject( new Error( @@ -101,10 +101,10 @@ export default class TypedMessageManager extends EventEmitter { msgParams, )}`, ), - ) + ); } - }) - }) + }); + }); } /** @@ -118,31 +118,31 @@ export default class TypedMessageManager extends EventEmitter { * */ addUnapprovedMessage(msgParams, req, version) { - msgParams.version = version + msgParams.version = version; if (req) { - msgParams.origin = req.origin + msgParams.origin = req.origin; } - this.validateParams(msgParams) + this.validateParams(msgParams); log.debug( `TypedMessageManager addUnapprovedMessage: ${JSON.stringify(msgParams)}`, - ) + ); // create txData obj with parameters and meta data - const time = new Date().getTime() - const msgId = createId() + const time = new Date().getTime(); + const msgId = createId(); const msgData = { id: msgId, msgParams, time, status: 'unapproved', type: MESSAGE_TYPE.ETH_SIGN_TYPED_DATA, - } - this.addMsg(msgData) + }; + this.addMsg(msgData); // signal update - this.emit('update') - return msgId + this.emit('update'); + return msgId; } /** @@ -152,59 +152,65 @@ export default class TypedMessageManager extends EventEmitter { * */ validateParams(params) { - assert.ok(params && typeof params === 'object', 'Params must be an object.') - assert.ok('data' in params, 'Params must include a "data" field.') - assert.ok('from' in params, 'Params must include a "from" field.') + assert.ok( + params && typeof params === 'object', + 'Params must be an object.', + ); + assert.ok('data' in params, 'Params must include a "data" field.'); + assert.ok('from' in params, 'Params must include a "from" field.'); assert.ok( typeof params.from === 'string' && isValidAddress(params.from), '"from" field must be a valid, lowercase, hexadecimal Ethereum address string.', - ) + ); switch (params.version) { case 'V1': - assert.ok(Array.isArray(params.data), '"params.data" must be an array.') + assert.ok( + Array.isArray(params.data), + '"params.data" must be an array.', + ); assert.doesNotThrow(() => { - typedSignatureHash(params.data) - }, 'Signing data must be valid EIP-712 typed data.') - break + typedSignatureHash(params.data); + }, 'Signing data must be valid EIP-712 typed data.'); + break; case 'V3': case 'V4': { assert.equal( typeof params.data, 'string', '"params.data" must be a string.', - ) - let data + ); + let data; assert.doesNotThrow(() => { - data = JSON.parse(params.data) - }, '"data" must be a valid JSON string.') - const validation = jsonschema.validate(data, TYPED_MESSAGE_SCHEMA) + data = JSON.parse(params.data); + }, '"data" must be a valid JSON string.'); + const validation = jsonschema.validate(data, TYPED_MESSAGE_SCHEMA); assert.ok( data.primaryType in data.types, `Primary type of "${data.primaryType}" has no type definition.`, - ) + ); assert.equal( validation.errors.length, 0, 'Signing data must conform to EIP-712 schema. See https://git.io/fNtcx.', - ) - const { chainId } = data.domain + ); + const { chainId } = data.domain; if (chainId) { - const activeChainId = parseInt(this._getCurrentChainId(), 16) + const activeChainId = parseInt(this._getCurrentChainId(), 16); assert.ok( !Number.isNaN(activeChainId), `Cannot sign messages for chainId "${chainId}", because MetaMask is switching networks.`, - ) + ); assert.equal( chainId, activeChainId, `Provided chainId "${chainId}" must match the active chainId "${activeChainId}"`, - ) + ); } - break + break; } default: - assert.fail(`Unknown typed data version "${params.version}"`) + assert.fail(`Unknown typed data version "${params.version}"`); } } @@ -216,8 +222,8 @@ export default class TypedMessageManager extends EventEmitter { * */ addMsg(msg) { - this.messages.push(msg) - this._saveMsgList() + this.messages.push(msg); + this._saveMsgList(); } /** @@ -229,7 +235,7 @@ export default class TypedMessageManager extends EventEmitter { * */ getMsg(msgId) { - return this.messages.find((msg) => msg.id === msgId) + return this.messages.find((msg) => msg.id === msgId); } /** @@ -242,8 +248,8 @@ export default class TypedMessageManager extends EventEmitter { * */ approveMessage(msgParams) { - this.setMsgStatusApproved(msgParams.metamaskId) - return this.prepMsgForSigning(msgParams) + this.setMsgStatusApproved(msgParams.metamaskId); + return this.prepMsgForSigning(msgParams); } /** @@ -253,7 +259,7 @@ export default class TypedMessageManager extends EventEmitter { * */ setMsgStatusApproved(msgId) { - this._setMsgStatus(msgId, 'approved') + this._setMsgStatus(msgId, 'approved'); } /** @@ -265,10 +271,10 @@ export default class TypedMessageManager extends EventEmitter { * */ setMsgStatusSigned(msgId, rawSig) { - const msg = this.getMsg(msgId) - msg.rawSig = rawSig - this._updateMsg(msg) - this._setMsgStatus(msgId, 'signed') + const msg = this.getMsg(msgId); + msg.rawSig = rawSig; + this._updateMsg(msg); + this._setMsgStatus(msgId, 'signed'); } /** @@ -279,9 +285,9 @@ export default class TypedMessageManager extends EventEmitter { * */ prepMsgForSigning(msgParams) { - delete msgParams.metamaskId - delete msgParams.version - return Promise.resolve(msgParams) + delete msgParams.metamaskId; + delete msgParams.version; + return Promise.resolve(msgParams); } /** @@ -291,7 +297,7 @@ export default class TypedMessageManager extends EventEmitter { * */ rejectMsg(msgId) { - this._setMsgStatus(msgId, 'rejected') + this._setMsgStatus(msgId, 'rejected'); } /** @@ -301,10 +307,10 @@ export default class TypedMessageManager extends EventEmitter { * */ errorMessage(msgId, error) { - const msg = this.getMsg(msgId) - msg.error = error - this._updateMsg(msg) - this._setMsgStatus(msgId, 'errored') + const msg = this.getMsg(msgId); + msg.error = error; + this._updateMsg(msg); + this._setMsgStatus(msgId, 'errored'); } // @@ -325,17 +331,17 @@ export default class TypedMessageManager extends EventEmitter { * */ _setMsgStatus(msgId, status) { - const msg = this.getMsg(msgId) + const msg = this.getMsg(msgId); if (!msg) { throw new Error( `TypedMessageManager - Message not found for id: "${msgId}".`, - ) + ); } - msg.status = status - this._updateMsg(msg) - this.emit(`${msgId}:${status}`, msg) + msg.status = status; + this._updateMsg(msg); + this.emit(`${msgId}:${status}`, msg); if (status === 'rejected' || status === 'signed' || status === 'errored') { - this.emit(`${msgId}:finished`, msg) + this.emit(`${msgId}:finished`, msg); } } @@ -349,11 +355,11 @@ export default class TypedMessageManager extends EventEmitter { * */ _updateMsg(msg) { - const index = this.messages.findIndex((message) => message.id === msg.id) + const index = this.messages.findIndex((message) => message.id === msg.id); if (index !== -1) { - this.messages[index] = msg + this.messages[index] = msg; } - this._saveMsgList() + this._saveMsgList(); } /** @@ -364,13 +370,13 @@ export default class TypedMessageManager extends EventEmitter { * */ _saveMsgList() { - const unapprovedTypedMessages = this.getUnapprovedMsgs() + const unapprovedTypedMessages = this.getUnapprovedMsgs(); const unapprovedTypedMessagesCount = Object.keys(unapprovedTypedMessages) - .length + .length; this.memStore.updateState({ unapprovedTypedMessages, unapprovedTypedMessagesCount, - }) - this.emit('updateBadge') + }); + this.emit('updateBadge'); } } diff --git a/app/scripts/lib/util.js b/app/scripts/lib/util.js index 04d83aabd..ccf8d1193 100644 --- a/app/scripts/lib/util.js +++ b/app/scripts/lib/util.js @@ -1,8 +1,8 @@ -import assert from 'assert' -import extension from 'extensionizer' -import ethUtil from 'ethereumjs-util' -import BN from 'bn.js' -import { memoize } from 'lodash' +import assert from 'assert'; +import extension from 'extensionizer'; +import ethUtil from 'ethereumjs-util'; +import BN from 'bn.js'; +import { memoize } from 'lodash'; import { ENVIRONMENT_TYPE_POPUP, @@ -14,22 +14,22 @@ import { PLATFORM_CHROME, PLATFORM_EDGE, PLATFORM_BRAVE, -} from '../../../shared/constants/app' +} from '../../../shared/constants/app'; /** * @see {@link getEnvironmentType} */ const getEnvironmentTypeMemo = memoize((url) => { - const parsedUrl = new URL(url) + const parsedUrl = new URL(url); if (parsedUrl.pathname === '/popup.html') { - return ENVIRONMENT_TYPE_POPUP + return ENVIRONMENT_TYPE_POPUP; } else if (['/home.html', '/phishing.html'].includes(parsedUrl.pathname)) { - return ENVIRONMENT_TYPE_FULLSCREEN + return ENVIRONMENT_TYPE_FULLSCREEN; } else if (parsedUrl.pathname === '/notification.html') { - return ENVIRONMENT_TYPE_NOTIFICATION + return ENVIRONMENT_TYPE_NOTIFICATION; } - return ENVIRONMENT_TYPE_BACKGROUND -}) + return ENVIRONMENT_TYPE_BACKGROUND; +}); /** * Returns the window type for the application @@ -45,7 +45,7 @@ const getEnvironmentTypeMemo = memoize((url) => { * @returns {string} the environment ENUM */ const getEnvironmentType = (url = window.location.href) => - getEnvironmentTypeMemo(url) + getEnvironmentTypeMemo(url); /** * Returns the platform (browser) where the extension is running. @@ -54,21 +54,21 @@ const getEnvironmentType = (url = window.location.href) => * */ const getPlatform = (_) => { - const ua = window.navigator.userAgent + const ua = window.navigator.userAgent; if (ua.search('Firefox') === -1) { if (window && window.chrome && window.chrome.ipcRenderer) { - return PLATFORM_BRAVE + return PLATFORM_BRAVE; } if (ua.search('Edge') !== -1) { - return PLATFORM_EDGE + return PLATFORM_EDGE; } if (ua.search('OPR') !== -1) { - return PLATFORM_OPERA + return PLATFORM_OPERA; } - return PLATFORM_CHROME + return PLATFORM_CHROME; } - return PLATFORM_FIREFOX -} + return PLATFORM_FIREFOX; +}; /** * Checks whether a given balance of ETH, represented as a hex string, is sufficient to pay a value plus a gas fee @@ -87,20 +87,20 @@ function sufficientBalance(txParams, hexBalance) { typeof hexBalance, 'string', 'sufficientBalance - hexBalance is not a hex string', - ) + ); assert.equal( hexBalance.slice(0, 2), '0x', 'sufficientBalance - hexBalance is not a hex string', - ) + ); - const balance = hexToBn(hexBalance) - const value = hexToBn(txParams.value) - const gasLimit = hexToBn(txParams.gas) - const gasPrice = hexToBn(txParams.gasPrice) + const balance = hexToBn(hexBalance); + const value = hexToBn(txParams.value); + const gasLimit = hexToBn(txParams.gas); + const gasPrice = hexToBn(txParams.gasPrice); - const maxCost = value.add(gasLimit.mul(gasPrice)) - return balance.gte(maxCost) + const maxCost = value.add(gasLimit.mul(gasPrice)); + return balance.gte(maxCost); } /** @@ -111,7 +111,7 @@ function sufficientBalance(txParams, hexBalance) { * */ function hexToBn(inputHex) { - return new BN(ethUtil.stripHexPrefix(inputHex), 16) + return new BN(ethUtil.stripHexPrefix(inputHex), 16); } /** @@ -124,9 +124,9 @@ function hexToBn(inputHex) { * */ function BnMultiplyByFraction(targetBN, numerator, denominator) { - const numBN = new BN(numerator) - const denomBN = new BN(denominator) - return targetBN.mul(numBN).div(denomBN) + const numBN = new BN(numerator); + const denomBN = new BN(denominator); + return targetBN.mul(numBN).div(denomBN); } /** @@ -135,16 +135,16 @@ function BnMultiplyByFraction(targetBN, numerator, denominator) { * @returns {Error|undefined} */ function checkForError() { - const { lastError } = extension.runtime + const { lastError } = extension.runtime; if (!lastError) { - return undefined + return undefined; } // if it quacks like an Error, its an Error if (lastError.stack && lastError.message) { - return lastError + return lastError; } // repair incomplete error object (eg chromium v77) - return new Error(lastError.message) + return new Error(lastError.message); } /** @@ -155,19 +155,19 @@ function checkForError() { */ const addHexPrefix = (str) => { if (typeof str !== 'string' || str.match(/^-?0x/u)) { - return str + return str; } if (str.match(/^-?0X/u)) { - return str.replace('0X', '0x') + return str.replace('0X', '0x'); } if (str.startsWith('-')) { - return str.replace('-', '-0x') + return str.replace('-', '-0x'); } - return `0x${str}` -} + return `0x${str}`; +}; /** * Converts a BN object to a hex string with a '0x' prefix @@ -177,7 +177,7 @@ const addHexPrefix = (str) => { * */ function bnToHex(inputBn) { - return addHexPrefix(inputBn.toString(16)) + return addHexPrefix(inputBn.toString(16)); } export { @@ -189,4 +189,4 @@ export { checkForError, addHexPrefix, bnToHex, -} +}; diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index b9d6c598f..2eff30355 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -1,65 +1,65 @@ -import EventEmitter from 'events' -import pump from 'pump' -import Dnode from 'dnode' -import { ObservableStore } from '@metamask/obs-store' -import { storeAsStream } from '@metamask/obs-store/dist/asStream' -import { JsonRpcEngine } from 'json-rpc-engine' -import { debounce } from 'lodash' -import createEngineStream from 'json-rpc-middleware-stream/engineStream' -import createFilterMiddleware from 'eth-json-rpc-filters' -import createSubscriptionManager from 'eth-json-rpc-filters/subscriptionManager' -import providerAsMiddleware from 'eth-json-rpc-middleware/providerAsMiddleware' -import KeyringController from 'eth-keyring-controller' -import { Mutex } from 'await-semaphore' -import ethUtil from 'ethereumjs-util' -import log from 'loglevel' -import TrezorKeyring from 'eth-trezor-keyring' -import LedgerBridgeKeyring from '@metamask/eth-ledger-bridge-keyring' -import EthQuery from 'eth-query' -import nanoid from 'nanoid' -import contractMap from '@metamask/contract-metadata' +import EventEmitter from 'events'; +import pump from 'pump'; +import Dnode from 'dnode'; +import { ObservableStore } from '@metamask/obs-store'; +import { storeAsStream } from '@metamask/obs-store/dist/asStream'; +import { JsonRpcEngine } from 'json-rpc-engine'; +import { debounce } from 'lodash'; +import createEngineStream from 'json-rpc-middleware-stream/engineStream'; +import createFilterMiddleware from 'eth-json-rpc-filters'; +import createSubscriptionManager from 'eth-json-rpc-filters/subscriptionManager'; +import providerAsMiddleware from 'eth-json-rpc-middleware/providerAsMiddleware'; +import KeyringController from 'eth-keyring-controller'; +import { Mutex } from 'await-semaphore'; +import ethUtil from 'ethereumjs-util'; +import log from 'loglevel'; +import TrezorKeyring from 'eth-trezor-keyring'; +import LedgerBridgeKeyring from '@metamask/eth-ledger-bridge-keyring'; +import EthQuery from 'eth-query'; +import nanoid from 'nanoid'; +import contractMap from '@metamask/contract-metadata'; import { AddressBookController, ApprovalController, CurrencyRateController, PhishingController, -} from '@metamask/controllers' -import { getBackgroundMetaMetricState } from '../../ui/app/selectors' -import { TRANSACTION_STATUSES } from '../../shared/constants/transaction' -import ComposableObservableStore from './lib/ComposableObservableStore' -import AccountTracker from './lib/account-tracker' -import createLoggerMiddleware from './lib/createLoggerMiddleware' -import createMethodMiddleware from './lib/rpc-method-middleware' -import createOriginMiddleware from './lib/createOriginMiddleware' -import createTabIdMiddleware from './lib/createTabIdMiddleware' -import createOnboardingMiddleware from './lib/createOnboardingMiddleware' -import { setupMultiplex } from './lib/stream-utils' -import EnsController from './controllers/ens' -import NetworkController from './controllers/network' -import PreferencesController from './controllers/preferences' -import AppStateController from './controllers/app-state' -import CachedBalancesController from './controllers/cached-balances' -import AlertController from './controllers/alert' -import OnboardingController from './controllers/onboarding' -import ThreeBoxController from './controllers/threebox' -import IncomingTransactionsController from './controllers/incoming-transactions' -import MessageManager from './lib/message-manager' -import DecryptMessageManager from './lib/decrypt-message-manager' -import EncryptionPublicKeyManager from './lib/encryption-public-key-manager' -import PersonalMessageManager from './lib/personal-message-manager' -import TypedMessageManager from './lib/typed-message-manager' -import TransactionController from './controllers/transactions' -import TokenRatesController from './controllers/token-rates' -import DetectTokensController from './controllers/detect-tokens' -import SwapsController from './controllers/swaps' -import { PermissionsController } from './controllers/permissions' -import { NOTIFICATION_NAMES } from './controllers/permissions/enums' -import getRestrictedMethods from './controllers/permissions/restrictedMethods' -import nodeify from './lib/nodeify' -import accountImporter from './account-import-strategies' -import seedPhraseVerifier from './lib/seed-phrase-verifier' -import MetaMetricsController from './controllers/metametrics' -import { segment, segmentLegacy } from './lib/segment' +} from '@metamask/controllers'; +import { getBackgroundMetaMetricState } from '../../ui/app/selectors'; +import { TRANSACTION_STATUSES } from '../../shared/constants/transaction'; +import ComposableObservableStore from './lib/ComposableObservableStore'; +import AccountTracker from './lib/account-tracker'; +import createLoggerMiddleware from './lib/createLoggerMiddleware'; +import createMethodMiddleware from './lib/rpc-method-middleware'; +import createOriginMiddleware from './lib/createOriginMiddleware'; +import createTabIdMiddleware from './lib/createTabIdMiddleware'; +import createOnboardingMiddleware from './lib/createOnboardingMiddleware'; +import { setupMultiplex } from './lib/stream-utils'; +import EnsController from './controllers/ens'; +import NetworkController from './controllers/network'; +import PreferencesController from './controllers/preferences'; +import AppStateController from './controllers/app-state'; +import CachedBalancesController from './controllers/cached-balances'; +import AlertController from './controllers/alert'; +import OnboardingController from './controllers/onboarding'; +import ThreeBoxController from './controllers/threebox'; +import IncomingTransactionsController from './controllers/incoming-transactions'; +import MessageManager from './lib/message-manager'; +import DecryptMessageManager from './lib/decrypt-message-manager'; +import EncryptionPublicKeyManager from './lib/encryption-public-key-manager'; +import PersonalMessageManager from './lib/personal-message-manager'; +import TypedMessageManager from './lib/typed-message-manager'; +import TransactionController from './controllers/transactions'; +import TokenRatesController from './controllers/token-rates'; +import DetectTokensController from './controllers/detect-tokens'; +import SwapsController from './controllers/swaps'; +import { PermissionsController } from './controllers/permissions'; +import { NOTIFICATION_NAMES } from './controllers/permissions/enums'; +import getRestrictedMethods from './controllers/permissions/restrictedMethods'; +import nodeify from './lib/nodeify'; +import accountImporter from './account-import-strategies'; +import seedPhraseVerifier from './lib/seed-phrase-verifier'; +import MetaMetricsController from './controllers/metametrics'; +import { segment, segmentLegacy } from './lib/segment'; export default class MetamaskController extends EventEmitter { /** @@ -67,40 +67,40 @@ export default class MetamaskController extends EventEmitter { * @param {Object} opts */ constructor(opts) { - super() + super(); - this.defaultMaxListeners = 20 + this.defaultMaxListeners = 20; - this.sendUpdate = debounce(this.privateSendUpdate.bind(this), 200) - this.opts = opts - this.extension = opts.extension - this.platform = opts.platform - const initState = opts.initState || {} - const version = this.platform.getVersion() - this.recordFirstTimeInfo(initState) + this.sendUpdate = debounce(this.privateSendUpdate.bind(this), 200); + this.opts = opts; + this.extension = opts.extension; + this.platform = opts.platform; + const initState = opts.initState || {}; + const version = this.platform.getVersion(); + this.recordFirstTimeInfo(initState); // this keeps track of how many "controllerStream" connections are open // the only thing that uses controller connections are open metamask UI instances - this.activeControllerConnections = 0 + this.activeControllerConnections = 0; - this.getRequestAccountTabIds = opts.getRequestAccountTabIds - this.getOpenMetamaskTabsIds = opts.getOpenMetamaskTabsIds + this.getRequestAccountTabIds = opts.getRequestAccountTabIds; + this.getOpenMetamaskTabsIds = opts.getOpenMetamaskTabsIds; // observable state store - this.store = new ComposableObservableStore(initState) + this.store = new ComposableObservableStore(initState); // external connections by origin // Do not modify directly. Use the associated methods. - this.connections = {} + this.connections = {}; // lock to ensure only one vault created at once - this.createVaultMutex = new Mutex() + this.createVaultMutex = new Mutex(); this.extension.runtime.onInstalled.addListener((details) => { if (details.reason === 'update' && version === '8.1.0') { - this.platform.openExtensionInBrowser() + this.platform.openExtensionInBrowser(); } - }) + }); // next, we will initialize the controllers // controller initialization order matters @@ -108,10 +108,10 @@ export default class MetamaskController extends EventEmitter { this.approvalController = new ApprovalController({ showApprovalRequest: opts.showUserConfirmation, defaultApprovalType: 'NO_TYPE', - }) + }); - this.networkController = new NetworkController(initState.NetworkController) - this.networkController.setInfuraProjectId(opts.infuraProjectId) + this.networkController = new NetworkController(initState.NetworkController); + this.networkController.setInfuraProjectId(opts.infuraProjectId); this.preferencesController = new PreferencesController({ initState: initState.PreferencesController, @@ -119,7 +119,7 @@ export default class MetamaskController extends EventEmitter { openPopup: opts.openPopup, network: this.networkController, migrateAddressBookState: this.migrateAddressBookState.bind(this), - }) + }); this.metaMetricsController = new MetaMetricsController({ segment, @@ -138,7 +138,7 @@ export default class MetamaskController extends EventEmitter { version: this.platform.getVersion(), environment: process.env.METAMASK_ENVIRONMENT, initState: initState.MetaMetricsController, - }) + }); this.appStateController = new AppStateController({ addUnlockListener: this.on.bind(this, 'unlock'), @@ -147,37 +147,37 @@ export default class MetamaskController extends EventEmitter { onInactiveTimeout: () => this.setLocked(), showUnlockRequest: opts.showUserConfirmation, preferencesStore: this.preferencesController.store, - }) + }); this.currencyRateController = new CurrencyRateController( { includeUSDRate: true }, initState.CurrencyController, - ) + ); - this.phishingController = new PhishingController() + this.phishingController = new PhishingController(); // now we can initialize the RPC provider, which other controllers require - this.initializeProvider() - this.provider = this.networkController.getProviderAndBlockTracker().provider - this.blockTracker = this.networkController.getProviderAndBlockTracker().blockTracker + this.initializeProvider(); + this.provider = this.networkController.getProviderAndBlockTracker().provider; + this.blockTracker = this.networkController.getProviderAndBlockTracker().blockTracker; // token exchange rate tracker this.tokenRatesController = new TokenRatesController({ currency: this.currencyRateController, preferences: this.preferencesController.store, - }) + }); this.ensController = new EnsController({ provider: this.provider, networkStore: this.networkController.networkStore, - }) + }); this.incomingTransactionsController = new IncomingTransactionsController({ blockTracker: this.blockTracker, networkController: this.networkController, preferencesController: this.preferencesController, initState: initState.IncomingTransactionsController, - }) + }); // account tracker watches balances, nonces, and any code at their address this.accountTracker = new AccountTracker({ @@ -186,20 +186,20 @@ export default class MetamaskController extends EventEmitter { getCurrentChainId: this.networkController.getCurrentChainId.bind( this.networkController, ), - }) + }); // start and stop polling for balances based on activeControllerConnections this.on('controllerConnectionChanged', (activeControllerConnections) => { if (activeControllerConnections > 0) { - this.accountTracker.start() - this.incomingTransactionsController.start() - this.tokenRatesController.start() + this.accountTracker.start(); + this.incomingTransactionsController.start(); + this.tokenRatesController.start(); } else { - this.accountTracker.stop() - this.incomingTransactionsController.stop() - this.tokenRatesController.stop() + this.accountTracker.stop(); + this.incomingTransactionsController.stop(); + this.tokenRatesController.stop(); } - }) + }); this.cachedBalancesController = new CachedBalancesController({ accountTracker: this.accountTracker, @@ -207,29 +207,29 @@ export default class MetamaskController extends EventEmitter { this.networkController, ), initState: initState.CachedBalancesController, - }) + }); this.onboardingController = new OnboardingController({ initState: initState.OnboardingController, preferencesController: this.preferencesController, - }) + }); // ensure accountTracker updates balances after network change this.networkController.on('networkDidChange', () => { - this.accountTracker._updateAccounts() - }) + this.accountTracker._updateAccounts(); + }); - const additionalKeyrings = [TrezorKeyring, LedgerBridgeKeyring] + const additionalKeyrings = [TrezorKeyring, LedgerBridgeKeyring]; this.keyringController = new KeyringController({ keyringTypes: additionalKeyrings, initState: initState.KeyringController, encryptor: opts.encryptor || undefined, - }) + }); this.keyringController.memStore.subscribe((state) => this._onKeyringControllerUpdate(state), - ) - this.keyringController.on('unlock', () => this.emit('unlock')) - this.keyringController.on('lock', () => this._onLock()) + ); + this.keyringController.on('unlock', () => this.emit('unlock')); + this.keyringController.on('lock', () => this._onLock()); this.permissionsController = new PermissionsController( { @@ -249,23 +249,23 @@ export default class MetamaskController extends EventEmitter { }, initState.PermissionsController, initState.PermissionsMetadata, - ) + ); this.detectTokensController = new DetectTokensController({ preferences: this.preferencesController, network: this.networkController, keyringMemStore: this.keyringController.memStore, - }) + }); this.addressBookController = new AddressBookController( undefined, initState.AddressBookController, - ) + ); this.alertController = new AlertController({ initState: initState.AlertController, preferencesStore: this.preferencesController.store, - }) + }); this.threeBoxController = new ThreeBoxController({ preferencesController: this.preferencesController, @@ -276,7 +276,7 @@ export default class MetamaskController extends EventEmitter { this.keyringController.memStore, ), version, - }) + }); this.txController = new TransactionController({ initState: @@ -301,49 +301,49 @@ export default class MetamaskController extends EventEmitter { ), getParticipateInMetrics: () => this.metaMetricsController.state.participateInMetaMetrics, - }) - this.txController.on('newUnapprovedTx', () => opts.showUserConfirmation()) + }); + this.txController.on('newUnapprovedTx', () => opts.showUserConfirmation()); this.txController.on(`tx:status-update`, async (txId, status) => { if ( status === TRANSACTION_STATUSES.CONFIRMED || status === TRANSACTION_STATUSES.FAILED ) { - const txMeta = this.txController.txStateManager.getTx(txId) - this.platform.showTransactionNotification(txMeta) + const txMeta = this.txController.txStateManager.getTx(txId); + this.platform.showTransactionNotification(txMeta); - const { txReceipt } = txMeta + const { txReceipt } = txMeta; if (txReceipt && txReceipt.status === '0x0') { this.sendBackgroundMetaMetrics({ action: 'Transactions', name: 'On Chain Failure', customVariables: { errorMessage: txMeta.simulationFails?.reason }, - }) + }); } } - }) + }); this.networkController.on('networkDidChange', () => { this.setCurrentCurrency( this.currencyRateController.state.currentCurrency, (error) => { if (error) { - throw error + throw error; } }, - ) - }) + ); + }); - this.networkController.lookupNetwork() - this.messageManager = new MessageManager() - this.personalMessageManager = new PersonalMessageManager() - this.decryptMessageManager = new DecryptMessageManager() - this.encryptionPublicKeyManager = new EncryptionPublicKeyManager() + this.networkController.lookupNetwork(); + this.messageManager = new MessageManager(); + this.personalMessageManager = new PersonalMessageManager(); + this.decryptMessageManager = new DecryptMessageManager(); + this.encryptionPublicKeyManager = new EncryptionPublicKeyManager(); this.typedMessageManager = new TypedMessageManager({ getCurrentChainId: this.networkController.getCurrentChainId.bind( this.networkController, ), - }) + }); this.swapsController = new SwapsController({ getBufferedGasLimit: this.txController.txGasUtil.getBufferedGasLimit.bind( @@ -355,10 +355,10 @@ export default class MetamaskController extends EventEmitter { this.networkController, ), tokenRatesStore: this.tokenRatesController.store, - }) + }); // ensure isClientOpenAndUnlocked is updated when memState updates - this.on('update', (memState) => this._onStateUpdate(memState)) + this.on('update', (memState) => this._onStateUpdate(memState)); this.store.updateStructure({ AppStateController: this.appStateController.store, @@ -376,7 +376,7 @@ export default class MetamaskController extends EventEmitter { PermissionsController: this.permissionsController.permissions, PermissionsMetadata: this.permissionsController.store, ThreeBoxController: this.threeBoxController.store, - }) + }); this.memStore = new ComposableObservableStore(null, { AppStateController: this.appStateController.store, @@ -404,27 +404,27 @@ export default class MetamaskController extends EventEmitter { SwapsController: this.swapsController.store, EnsController: this.ensController.store, ApprovalController: this.approvalController, - }) - this.memStore.subscribe(this.sendUpdate.bind(this)) + }); + this.memStore.subscribe(this.sendUpdate.bind(this)); - const password = process.env.CONF?.password + const password = process.env.CONF?.password; if ( password && !this.isUnlocked() && this.onboardingController.completedOnboarding ) { - this.submitPassword(password) + this.submitPassword(password); } // TODO:LegacyProvider: Delete - this.publicConfigStore = this.createPublicConfigStore() + this.publicConfigStore = this.createPublicConfigStore(); } /** * Constructor helper: initialize a provider. */ initializeProvider() { - const version = this.platform.getVersion() + const version = this.platform.getVersion(); const providerOpts = { static: { eth_syncing: false, @@ -434,12 +434,12 @@ export default class MetamaskController extends EventEmitter { // account mgmt getAccounts: async ({ origin }) => { if (origin === 'metamask') { - const selectedAddress = this.preferencesController.getSelectedAddress() - return selectedAddress ? [selectedAddress] : [] + const selectedAddress = this.preferencesController.getSelectedAddress(); + return selectedAddress ? [selectedAddress] : []; } else if (this.isUnlocked()) { - return await this.permissionsController.getAccounts(origin) + return await this.permissionsController.getAccounts(origin); } - return [] // changing this is a breaking change + return []; // changing this is a breaking change }, // tx signing processTransaction: this.newUnapprovedTransaction.bind(this), @@ -457,11 +457,11 @@ export default class MetamaskController extends EventEmitter { hash, status: TRANSACTION_STATUSES.SUBMITTED, })[0], - } + }; const providerProxy = this.networkController.initializeProvider( providerOpts, - ) - return providerProxy + ); + return providerProxy; } /** @@ -471,17 +471,17 @@ export default class MetamaskController extends EventEmitter { */ createPublicConfigStore() { // subset of state for metamask inpage provider - const publicConfigStore = new ObservableStore() - const { networkController } = this + const publicConfigStore = new ObservableStore(); + const { networkController } = this; // setup memStore subscription hooks - this.on('update', updatePublicConfigStore) - updatePublicConfigStore(this.getState()) + this.on('update', updatePublicConfigStore); + updatePublicConfigStore(this.getState()); function updatePublicConfigStore(memState) { - const chainId = networkController.getCurrentChainId() + const chainId = networkController.getCurrentChainId(); if (memState.network !== 'loading') { - publicConfigStore.putState(selectPublicState(chainId, memState)) + publicConfigStore.putState(selectPublicState(chainId, memState)); } } @@ -490,10 +490,10 @@ export default class MetamaskController extends EventEmitter { isUnlocked, chainId, networkVersion: network, - } + }; } - return publicConfigStore + return publicConfigStore; } /** @@ -512,7 +512,7 @@ export default class MetamaskController extends EventEmitter { isUnlocked: this.isUnlocked(), ...this.getProviderNetworkState(), accounts: await this.permissionsController.getAccounts(origin), - } + }; } /** @@ -523,11 +523,11 @@ export default class MetamaskController extends EventEmitter { * @returns {Object} An object with relevant network state properties. */ getProviderNetworkState(memState) { - const { network } = memState || this.getState() + const { network } = memState || this.getState(); return { chainId: this.networkController.getCurrentChainId(), networkVersion: network, - } + }; } //============================================================================= @@ -540,13 +540,13 @@ export default class MetamaskController extends EventEmitter { * @returns {Object} status */ getState() { - const { vault } = this.keyringController.store.getState() - const isInitialized = Boolean(vault) + const { vault } = this.keyringController.store.getState(); + const isInitialized = Boolean(vault); return { ...{ isInitialized }, ...this.memStore.getFlatState(), - } + }; } /** @@ -568,7 +568,7 @@ export default class MetamaskController extends EventEmitter { swapsController, threeBoxController, txController, - } = this + } = this; return { // etc @@ -883,7 +883,7 @@ export default class MetamaskController extends EventEmitter { metaMetricsController.trackPage, metaMetricsController, ), - } + }; } //============================================================================= @@ -904,21 +904,23 @@ export default class MetamaskController extends EventEmitter { * @returns {Object} vault */ async createNewVaultAndKeychain(password) { - const releaseLock = await this.createVaultMutex.acquire() + const releaseLock = await this.createVaultMutex.acquire(); try { - let vault - const accounts = await this.keyringController.getAccounts() + let vault; + const accounts = await this.keyringController.getAccounts(); if (accounts.length > 0) { - vault = await this.keyringController.fullUpdate() + vault = await this.keyringController.fullUpdate(); } else { - vault = await this.keyringController.createNewVaultAndKeychain(password) - const addresses = await this.keyringController.getAccounts() - this.preferencesController.setAddresses(addresses) - this.selectFirstIdentity() + vault = await this.keyringController.createNewVaultAndKeychain( + password, + ); + const addresses = await this.keyringController.getAccounts(); + this.preferencesController.setAddresses(addresses); + this.selectFirstIdentity(); } - return vault + return vault; } finally { - releaseLock() + releaseLock(); } } @@ -928,63 +930,63 @@ export default class MetamaskController extends EventEmitter { * @param {string} seed */ async createNewVaultAndRestore(password, seed) { - const releaseLock = await this.createVaultMutex.acquire() + const releaseLock = await this.createVaultMutex.acquire(); try { - let accounts, lastBalance + let accounts, lastBalance; - const { keyringController } = this + const { keyringController } = this; // clear known identities - this.preferencesController.setAddresses([]) + this.preferencesController.setAddresses([]); // clear permissions - this.permissionsController.clearPermissions() + this.permissionsController.clearPermissions(); // clear accounts in accountTracker - this.accountTracker.clearAccounts() + this.accountTracker.clearAccounts(); // clear cachedBalances - this.cachedBalancesController.clearCachedBalances() + this.cachedBalancesController.clearCachedBalances(); // clear unapproved transactions - this.txController.txStateManager.clearUnapprovedTxs() + this.txController.txStateManager.clearUnapprovedTxs(); // create new vault const vault = await keyringController.createNewVaultAndRestore( password, seed, - ) + ); - const ethQuery = new EthQuery(this.provider) - accounts = await keyringController.getAccounts() + const ethQuery = new EthQuery(this.provider); + accounts = await keyringController.getAccounts(); lastBalance = await this.getBalance( accounts[accounts.length - 1], ethQuery, - ) + ); const primaryKeyring = keyringController.getKeyringsByType( 'HD Key Tree', - )[0] + )[0]; if (!primaryKeyring) { - throw new Error('MetamaskController - No HD Key Tree found') + throw new Error('MetamaskController - No HD Key Tree found'); } // seek out the first zero balance while (lastBalance !== '0x0') { - await keyringController.addNewAccount(primaryKeyring) - accounts = await keyringController.getAccounts() + await keyringController.addNewAccount(primaryKeyring); + accounts = await keyringController.getAccounts(); lastBalance = await this.getBalance( accounts[accounts.length - 1], ethQuery, - ) + ); } // set new identities - this.preferencesController.setAddresses(accounts) - this.selectFirstIdentity() - return vault + this.preferencesController.setAddresses(accounts); + this.selectFirstIdentity(); + return vault; } finally { - releaseLock() + releaseLock(); } } @@ -995,26 +997,26 @@ export default class MetamaskController extends EventEmitter { */ getBalance(address, ethQuery) { return new Promise((resolve, reject) => { - const cached = this.accountTracker.store.getState().accounts[address] + const cached = this.accountTracker.store.getState().accounts[address]; if (cached && cached.balance) { - resolve(cached.balance) + resolve(cached.balance); } else { ethQuery.getBalance(address, (error, balance) => { if (error) { - reject(error) - log.error(error) + reject(error); + log.error(error); } else { - resolve(balance || '0x0') + resolve(balance || '0x0'); } - }) + }); } - }) + }); } getCurrentNetwork = () => { - return this.networkController.store.getState().network - } + return this.networkController.store.getState().network; + }; /** * Collects all the information that we want to share @@ -1030,13 +1032,13 @@ export default class MetamaskController extends EventEmitter { identities, selectedAddress, tokens, - } = this.preferencesController.store.getState() + } = this.preferencesController.store.getState(); // Filter ERC20 tokens - const filteredAccountTokens = {} + const filteredAccountTokens = {}; Object.keys(accountTokens).forEach((address) => { - const checksummedAddress = ethUtil.toChecksumAddress(address) - filteredAccountTokens[checksummedAddress] = {} + const checksummedAddress = ethUtil.toChecksumAddress(address); + filteredAccountTokens[checksummedAddress] = {}; Object.keys(accountTokens[address]).forEach((networkType) => { filteredAccountTokens[checksummedAddress][networkType] = networkType === 'mainnet' @@ -1044,15 +1046,15 @@ export default class MetamaskController extends EventEmitter { ({ address: tokenAddress }) => { const checksumAddress = ethUtil.toChecksumAddress( tokenAddress, - ) + ); return contractMap[checksumAddress] ? contractMap[checksumAddress].erc20 - : true + : true; }, ) - : accountTokens[address][networkType] - }) - }) + : accountTokens[address][networkType]; + }); + }); const preferences = { accountTokens: filteredAccountTokens, @@ -1061,21 +1063,23 @@ export default class MetamaskController extends EventEmitter { identities, selectedAddress, tokens, - } + }; // Accounts - const hdKeyring = this.keyringController.getKeyringsByType('HD Key Tree')[0] + const hdKeyring = this.keyringController.getKeyringsByType( + 'HD Key Tree', + )[0]; const simpleKeyPairKeyrings = this.keyringController.getKeyringsByType( 'Simple Key Pair', - ) - const hdAccounts = await hdKeyring.getAccounts() + ); + const hdAccounts = await hdKeyring.getAccounts(); const simpleKeyPairKeyringAccounts = await Promise.all( simpleKeyPairKeyrings.map((keyring) => keyring.getAccounts()), - ) + ); const simpleKeyPairAccounts = simpleKeyPairKeyringAccounts.reduce( (acc, accounts) => [...acc, ...accounts], [], - ) + ); const accounts = { hd: hdAccounts .filter((item, pos) => hdAccounts.indexOf(item) === pos) @@ -1085,23 +1089,23 @@ export default class MetamaskController extends EventEmitter { .map((address) => ethUtil.toChecksumAddress(address)), ledger: [], trezor: [], - } + }; // transactions - let { transactions } = this.txController.store.getState() + let { transactions } = this.txController.store.getState(); // delete tx for other accounts that we're not importing transactions = transactions.filter((tx) => { - const checksummedTxFrom = ethUtil.toChecksumAddress(tx.txParams.from) - return accounts.hd.includes(checksummedTxFrom) - }) + const checksummedTxFrom = ethUtil.toChecksumAddress(tx.txParams.from); + return accounts.hd.includes(checksummedTxFrom); + }); return { accounts, preferences, transactions, network: this.networkController.store.getState(), - } + }; } /* @@ -1113,28 +1117,28 @@ export default class MetamaskController extends EventEmitter { * @returns {Promise} The keyringController update. */ async submitPassword(password) { - await this.keyringController.submitPassword(password) + await this.keyringController.submitPassword(password); try { - await this.blockTracker.checkForLatestBlock() + await this.blockTracker.checkForLatestBlock(); } catch (error) { - log.error('Error while unlocking extension.', error) + log.error('Error while unlocking extension.', error); } try { - const threeBoxSyncingAllowed = this.threeBoxController.getThreeBoxSyncingState() + const threeBoxSyncingAllowed = this.threeBoxController.getThreeBoxSyncingState(); if (threeBoxSyncingAllowed && !this.threeBoxController.box) { // 'await' intentionally omitted to avoid waiting for initialization - this.threeBoxController.init() - this.threeBoxController.turnThreeBoxSyncingOn() + this.threeBoxController.init(); + this.threeBoxController.turnThreeBoxSyncingOn(); } else if (threeBoxSyncingAllowed && this.threeBoxController.box) { - this.threeBoxController.turnThreeBoxSyncingOn() + this.threeBoxController.turnThreeBoxSyncingOn(); } } catch (error) { - log.error('Error while unlocking extension.', error) + log.error('Error while unlocking extension.', error); } - return this.keyringController.fullUpdate() + return this.keyringController.fullUpdate(); } /** @@ -1143,7 +1147,7 @@ export default class MetamaskController extends EventEmitter { * @param {string} password The user's password */ async verifyPassword(password) { - await this.keyringController.verifyPassword(password) + await this.keyringController.verifyPassword(password); } /** @@ -1158,9 +1162,9 @@ export default class MetamaskController extends EventEmitter { * Sets the first address in the state to the selected address */ selectFirstIdentity() { - const { identities } = this.preferencesController.store.getState() - const address = Object.keys(identities)[0] - this.preferencesController.setSelectedAddress(address) + const { identities } = this.preferencesController.store.getState(); + const address = Object.keys(identities)[0]; + this.preferencesController.setSelectedAddress(address); } // @@ -1168,30 +1172,32 @@ export default class MetamaskController extends EventEmitter { // async getKeyringForDevice(deviceName, hdPath = null) { - let keyringName = null + let keyringName = null; switch (deviceName) { case 'trezor': - keyringName = TrezorKeyring.type - break + keyringName = TrezorKeyring.type; + break; case 'ledger': - keyringName = LedgerBridgeKeyring.type - break + keyringName = LedgerBridgeKeyring.type; + break; default: throw new Error( 'MetamaskController:getKeyringForDevice - Unknown device', - ) + ); } - let keyring = await this.keyringController.getKeyringsByType(keyringName)[0] + let keyring = await this.keyringController.getKeyringsByType( + keyringName, + )[0]; if (!keyring) { - keyring = await this.keyringController.addNewKeyring(keyringName) + keyring = await this.keyringController.addNewKeyring(keyringName); } if (hdPath && keyring.setHdPath) { - keyring.setHdPath(hdPath) + keyring.setHdPath(hdPath); } - keyring.network = this.networkController.getProviderConfig().type + keyring.network = this.networkController.getProviderConfig().type; - return keyring + return keyring; } /** @@ -1200,29 +1206,29 @@ export default class MetamaskController extends EventEmitter { * @returns [] accounts */ async connectHardware(deviceName, page, hdPath) { - const keyring = await this.getKeyringForDevice(deviceName, hdPath) - let accounts = [] + const keyring = await this.getKeyringForDevice(deviceName, hdPath); + let accounts = []; switch (page) { case -1: - accounts = await keyring.getPreviousPage() - break + accounts = await keyring.getPreviousPage(); + break; case 1: - accounts = await keyring.getNextPage() - break + accounts = await keyring.getNextPage(); + break; default: - accounts = await keyring.getFirstPage() + accounts = await keyring.getFirstPage(); } // Merge with existing accounts // and make sure addresses are not repeated - const oldAccounts = await this.keyringController.getAccounts() + const oldAccounts = await this.keyringController.getAccounts(); const accountsToTrack = [ ...new Set( oldAccounts.concat(accounts.map((a) => a.address.toLowerCase())), ), - ] - this.accountTracker.syncWithAddresses(accountsToTrack) - return accounts + ]; + this.accountTracker.syncWithAddresses(accountsToTrack); + return accounts; } /** @@ -1231,8 +1237,8 @@ export default class MetamaskController extends EventEmitter { * @returns {Promise} */ async checkHardwareStatus(deviceName, hdPath) { - const keyring = await this.getKeyringForDevice(deviceName, hdPath) - return keyring.isUnlocked() + const keyring = await this.getKeyringForDevice(deviceName, hdPath); + return keyring.isUnlocked(); } /** @@ -1241,9 +1247,9 @@ export default class MetamaskController extends EventEmitter { * @returns {Promise} */ async forgetDevice(deviceName) { - const keyring = await this.getKeyringForDevice(deviceName) - keyring.forgetDevice() - return true + const keyring = await this.getKeyringForDevice(deviceName); + keyring.forgetDevice(); + return true; } /** @@ -1252,13 +1258,13 @@ export default class MetamaskController extends EventEmitter { * @returns {} keyState */ async unlockHardwareWalletAccount(index, deviceName, hdPath) { - const keyring = await this.getKeyringForDevice(deviceName, hdPath) + const keyring = await this.getKeyringForDevice(deviceName, hdPath); - keyring.setAccountToUnlock(index) - const oldAccounts = await this.keyringController.getAccounts() - const keyState = await this.keyringController.addNewAccount(keyring) - const newAccounts = await this.keyringController.getAccounts() - this.preferencesController.setAddresses(newAccounts) + keyring.setAccountToUnlock(index); + const oldAccounts = await this.keyringController.getAccounts(); + const keyState = await this.keyringController.addNewAccount(keyring); + const newAccounts = await this.keyringController.getAccounts(); + this.preferencesController.setAddresses(newAccounts); newAccounts.forEach((address) => { if (!oldAccounts.includes(address)) { // Set the account label to Trezor 1 / Ledger 1, etc @@ -1267,14 +1273,14 @@ export default class MetamaskController extends EventEmitter { `${deviceName[0].toUpperCase()}${deviceName.slice(1)} ${ parseInt(index, 10) + 1 }`, - ) + ); // Select the account - this.preferencesController.setSelectedAddress(address) + this.preferencesController.setSelectedAddress(address); } - }) + }); - const { identities } = this.preferencesController.store.getState() - return { ...keyState, identities } + const { identities } = this.preferencesController.store.getState(); + return { ...keyState, identities }; } // @@ -1289,26 +1295,26 @@ export default class MetamaskController extends EventEmitter { async addNewAccount() { const primaryKeyring = this.keyringController.getKeyringsByType( 'HD Key Tree', - )[0] + )[0]; if (!primaryKeyring) { - throw new Error('MetamaskController - No HD Key Tree found') + throw new Error('MetamaskController - No HD Key Tree found'); } - const { keyringController } = this - const oldAccounts = await keyringController.getAccounts() - const keyState = await keyringController.addNewAccount(primaryKeyring) - const newAccounts = await keyringController.getAccounts() + const { keyringController } = this; + const oldAccounts = await keyringController.getAccounts(); + const keyState = await keyringController.addNewAccount(primaryKeyring); + const newAccounts = await keyringController.getAccounts(); - await this.verifySeedPhrase() + await this.verifySeedPhrase(); - this.preferencesController.setAddresses(newAccounts) + this.preferencesController.setAddresses(newAccounts); newAccounts.forEach((address) => { if (!oldAccounts.includes(address)) { - this.preferencesController.setSelectedAddress(address) + this.preferencesController.setSelectedAddress(address); } - }) + }); - const { identities } = this.preferencesController.store.getState() - return { ...keyState, identities } + const { identities } = this.preferencesController.store.getState(); + return { ...keyState, identities }; } /** @@ -1323,25 +1329,25 @@ export default class MetamaskController extends EventEmitter { async verifySeedPhrase() { const primaryKeyring = this.keyringController.getKeyringsByType( 'HD Key Tree', - )[0] + )[0]; if (!primaryKeyring) { - throw new Error('MetamaskController - No HD Key Tree found') + throw new Error('MetamaskController - No HD Key Tree found'); } - const serialized = await primaryKeyring.serialize() - const seedWords = serialized.mnemonic + const serialized = await primaryKeyring.serialize(); + const seedWords = serialized.mnemonic; - const accounts = await primaryKeyring.getAccounts() + const accounts = await primaryKeyring.getAccounts(); if (accounts.length < 1) { - throw new Error('MetamaskController - No accounts found') + throw new Error('MetamaskController - No accounts found'); } try { - await seedPhraseVerifier.verifyAccounts(accounts, seedWords) - return seedWords + await seedPhraseVerifier.verifyAccounts(accounts, seedWords); + return seedWords; } catch (err) { - log.error(err.message) - throw err + log.error(err.message); + throw err; } } @@ -1353,11 +1359,11 @@ export default class MetamaskController extends EventEmitter { * @returns {Promise} The current selected address. */ async resetAccount() { - const selectedAddress = this.preferencesController.getSelectedAddress() - this.txController.wipeTransactions(selectedAddress) - this.networkController.resetConnection() + const selectedAddress = this.preferencesController.getSelectedAddress(); + this.txController.wipeTransactions(selectedAddress); + this.networkController.resetConnection(); - return selectedAddress + return selectedAddress; } /** @@ -1368,15 +1374,15 @@ export default class MetamaskController extends EventEmitter { */ async removeAccount(address) { // Remove all associated permissions - await this.permissionsController.removeAllAccountPermissions(address) + await this.permissionsController.removeAllAccountPermissions(address); // Remove account from the preferences controller - this.preferencesController.removeAddress(address) + this.preferencesController.removeAddress(address); // Remove account from the account tracker controller - this.accountTracker.removeAccount([address]) + this.accountTracker.removeAccount([address]); // Remove account from the keyring - await this.keyringController.removeAccount(address) - return address + await this.keyringController.removeAccount(address); + return address; } /** @@ -1389,17 +1395,17 @@ export default class MetamaskController extends EventEmitter { * @param {Function} cb - A callback function called with a state update on success. */ async importAccountWithStrategy(strategy, args) { - const privateKey = await accountImporter.importAccount(strategy, args) + const privateKey = await accountImporter.importAccount(strategy, args); const keyring = await this.keyringController.addNewKeyring( 'Simple Key Pair', [privateKey], - ) - const accounts = await keyring.getAccounts() + ); + const accounts = await keyring.getAccounts(); // update accounts in preferences controller - const allAccounts = await this.keyringController.getAccounts() - this.preferencesController.setAddresses(allAccounts) + const allAccounts = await this.keyringController.getAccounts(); + this.preferencesController.setAddresses(allAccounts); // set new account as selected - await this.preferencesController.setSelectedAddress(accounts[0]) + await this.preferencesController.setSelectedAddress(accounts[0]); } // --------------------------------------------------------------------------- @@ -1414,7 +1420,7 @@ export default class MetamaskController extends EventEmitter { * @param {Object} req - (optional) the original request, containing the origin */ async newUnapprovedTransaction(txParams, req) { - return await this.txController.newUnapprovedTransaction(txParams, req) + return await this.txController.newUnapprovedTransaction(txParams, req); } // eth_sign methods: @@ -1432,10 +1438,10 @@ export default class MetamaskController extends EventEmitter { const promise = this.messageManager.addUnapprovedMessageAsync( msgParams, req, - ) - this.sendUpdate() - this.opts.showUserConfirmation() - return promise + ); + this.sendUpdate(); + this.opts.showUserConfirmation(); + return promise; } /** @@ -1445,8 +1451,8 @@ export default class MetamaskController extends EventEmitter { * @returns {Promise} Full state update. */ signMessage(msgParams) { - log.info('MetaMaskController - signMessage') - const msgId = msgParams.metamaskId + log.info('MetaMaskController - signMessage'); + const msgId = msgParams.metamaskId; // sets the status op the message to 'approved' // and removes the metamaskId for signing @@ -1454,14 +1460,14 @@ export default class MetamaskController extends EventEmitter { .approveMessage(msgParams) .then((cleanMsgParams) => { // signs the message - return this.keyringController.signMessage(cleanMsgParams) + return this.keyringController.signMessage(cleanMsgParams); }) .then((rawSig) => { // tells the listener that the message has been signed // and can be returned to the dapp - this.messageManager.setMsgStatusSigned(msgId, rawSig) - return this.getState() - }) + this.messageManager.setMsgStatusSigned(msgId, rawSig); + return this.getState(); + }); } /** @@ -1470,12 +1476,12 @@ export default class MetamaskController extends EventEmitter { * @param {string} msgId - The id of the message to cancel. */ cancelMessage(msgId, cb) { - const { messageManager } = this - messageManager.rejectMsg(msgId) + const { messageManager } = this; + messageManager.rejectMsg(msgId); if (!cb || typeof cb !== 'function') { - return + return; } - cb(null, this.getState()) + cb(null, this.getState()); } // personal_sign methods: @@ -1495,10 +1501,10 @@ export default class MetamaskController extends EventEmitter { const promise = this.personalMessageManager.addUnapprovedMessageAsync( msgParams, req, - ) - this.sendUpdate() - this.opts.showUserConfirmation() - return promise + ); + this.sendUpdate(); + this.opts.showUserConfirmation(); + return promise; } /** @@ -1509,22 +1515,22 @@ export default class MetamaskController extends EventEmitter { * @returns {Promise} A full state update. */ signPersonalMessage(msgParams) { - log.info('MetaMaskController - signPersonalMessage') - const msgId = msgParams.metamaskId + log.info('MetaMaskController - signPersonalMessage'); + const msgId = msgParams.metamaskId; // sets the status op the message to 'approved' // and removes the metamaskId for signing return this.personalMessageManager .approveMessage(msgParams) .then((cleanMsgParams) => { // signs the message - return this.keyringController.signPersonalMessage(cleanMsgParams) + return this.keyringController.signPersonalMessage(cleanMsgParams); }) .then((rawSig) => { // tells the listener that the message has been signed // and can be returned to the dapp - this.personalMessageManager.setMsgStatusSigned(msgId, rawSig) - return this.getState() - }) + this.personalMessageManager.setMsgStatusSigned(msgId, rawSig); + return this.getState(); + }); } /** @@ -1533,12 +1539,12 @@ export default class MetamaskController extends EventEmitter { * @param {Function} cb - The callback function called with a full state update. */ cancelPersonalMessage(msgId, cb) { - const messageManager = this.personalMessageManager - messageManager.rejectMsg(msgId) + const messageManager = this.personalMessageManager; + messageManager.rejectMsg(msgId); if (!cb || typeof cb !== 'function') { - return + return; } - cb(null, this.getState()) + cb(null, this.getState()); } // eth_decrypt methods @@ -1554,10 +1560,10 @@ export default class MetamaskController extends EventEmitter { const promise = this.decryptMessageManager.addUnapprovedMessageAsync( msgParams, req, - ) - this.sendUpdate() - this.opts.showUserConfirmation() - return promise + ); + this.sendUpdate(); + this.opts.showUserConfirmation(); + return promise; } /** @@ -1567,22 +1573,22 @@ export default class MetamaskController extends EventEmitter { * @returns {Promise} A full state update. */ async decryptMessageInline(msgParams) { - log.info('MetaMaskController - decryptMessageInline') + log.info('MetaMaskController - decryptMessageInline'); // decrypt the message inline - const msgId = msgParams.metamaskId - const msg = this.decryptMessageManager.getMsg(msgId) + const msgId = msgParams.metamaskId; + const msg = this.decryptMessageManager.getMsg(msgId); try { - const stripped = ethUtil.stripHexPrefix(msgParams.data) - const buff = Buffer.from(stripped, 'hex') - msgParams.data = JSON.parse(buff.toString('utf8')) + const stripped = ethUtil.stripHexPrefix(msgParams.data); + const buff = Buffer.from(stripped, 'hex'); + msgParams.data = JSON.parse(buff.toString('utf8')); - msg.rawData = await this.keyringController.decryptMessage(msgParams) + msg.rawData = await this.keyringController.decryptMessage(msgParams); } catch (e) { - msg.error = e.message + msg.error = e.message; } - this.decryptMessageManager._updateMsg(msg) + this.decryptMessageManager._updateMsg(msg); - return this.getState() + return this.getState(); } /** @@ -1593,30 +1599,30 @@ export default class MetamaskController extends EventEmitter { * @returns {Promise} A full state update. */ async decryptMessage(msgParams) { - log.info('MetaMaskController - decryptMessage') - const msgId = msgParams.metamaskId + log.info('MetaMaskController - decryptMessage'); + const msgId = msgParams.metamaskId; // sets the status op the message to 'approved' // and removes the metamaskId for decryption try { const cleanMsgParams = await this.decryptMessageManager.approveMessage( msgParams, - ) + ); - const stripped = ethUtil.stripHexPrefix(cleanMsgParams.data) - const buff = Buffer.from(stripped, 'hex') - cleanMsgParams.data = JSON.parse(buff.toString('utf8')) + const stripped = ethUtil.stripHexPrefix(cleanMsgParams.data); + const buff = Buffer.from(stripped, 'hex'); + cleanMsgParams.data = JSON.parse(buff.toString('utf8')); // decrypt the message const rawMess = await this.keyringController.decryptMessage( cleanMsgParams, - ) + ); // tells the listener that the message has been decrypted and can be returned to the dapp - this.decryptMessageManager.setMsgStatusDecrypted(msgId, rawMess) + this.decryptMessageManager.setMsgStatusDecrypted(msgId, rawMess); } catch (error) { - log.info('MetaMaskController - eth_decrypt failed.', error) - this.decryptMessageManager.errorMessage(msgId, error) + log.info('MetaMaskController - eth_decrypt failed.', error); + this.decryptMessageManager.errorMessage(msgId, error); } - return this.getState() + return this.getState(); } /** @@ -1625,12 +1631,12 @@ export default class MetamaskController extends EventEmitter { * @param {Function} cb - The callback function called with a full state update. */ cancelDecryptMessage(msgId, cb) { - const messageManager = this.decryptMessageManager - messageManager.rejectMsg(msgId) + const messageManager = this.decryptMessageManager; + messageManager.rejectMsg(msgId); if (!cb || typeof cb !== 'function') { - return + return; } - cb(null, this.getState()) + cb(null, this.getState()); } // eth_getEncryptionPublicKey methods @@ -1643,34 +1649,34 @@ export default class MetamaskController extends EventEmitter { * Passed back to the requesting Dapp. */ async newRequestEncryptionPublicKey(msgParams, req) { - const address = msgParams - const keyring = await this.keyringController.getKeyringForAccount(address) + const address = msgParams; + const keyring = await this.keyringController.getKeyringForAccount(address); switch (keyring.type) { case 'Ledger Hardware': { return new Promise((_, reject) => { reject( new Error('Ledger does not support eth_getEncryptionPublicKey.'), - ) - }) + ); + }); } case 'Trezor Hardware': { return new Promise((_, reject) => { reject( new Error('Trezor does not support eth_getEncryptionPublicKey.'), - ) - }) + ); + }); } default: { const promise = this.encryptionPublicKeyManager.addUnapprovedMessageAsync( msgParams, req, - ) - this.sendUpdate() - this.opts.showUserConfirmation() - return promise + ); + this.sendUpdate(); + this.opts.showUserConfirmation(); + return promise; } } } @@ -1683,28 +1689,31 @@ export default class MetamaskController extends EventEmitter { * @returns {Promise} A full state update. */ async encryptionPublicKey(msgParams) { - log.info('MetaMaskController - encryptionPublicKey') - const msgId = msgParams.metamaskId + log.info('MetaMaskController - encryptionPublicKey'); + const msgId = msgParams.metamaskId; // sets the status op the message to 'approved' // and removes the metamaskId for decryption try { const params = await this.encryptionPublicKeyManager.approveMessage( msgParams, - ) + ); // EncryptionPublicKey message const publicKey = await this.keyringController.getEncryptionPublicKey( params.data, - ) + ); // tells the listener that the message has been processed // and can be returned to the dapp - this.encryptionPublicKeyManager.setMsgStatusReceived(msgId, publicKey) + this.encryptionPublicKeyManager.setMsgStatusReceived(msgId, publicKey); } catch (error) { - log.info('MetaMaskController - eth_getEncryptionPublicKey failed.', error) - this.encryptionPublicKeyManager.errorMessage(msgId, error) + log.info( + 'MetaMaskController - eth_getEncryptionPublicKey failed.', + error, + ); + this.encryptionPublicKeyManager.errorMessage(msgId, error); } - return this.getState() + return this.getState(); } /** @@ -1713,12 +1722,12 @@ export default class MetamaskController extends EventEmitter { * @param {Function} cb - The callback function called with a full state update. */ cancelEncryptionPublicKey(msgId, cb) { - const messageManager = this.encryptionPublicKeyManager - messageManager.rejectMsg(msgId) + const messageManager = this.encryptionPublicKeyManager; + messageManager.rejectMsg(msgId); if (!cb || typeof cb !== 'function') { - return + return; } - cb(null, this.getState()) + cb(null, this.getState()); } // eth_signTypedData methods @@ -1734,10 +1743,10 @@ export default class MetamaskController extends EventEmitter { msgParams, req, version, - ) - this.sendUpdate() - this.opts.showUserConfirmation() - return promise + ); + this.sendUpdate(); + this.opts.showUserConfirmation(); + return promise; } /** @@ -1748,32 +1757,32 @@ export default class MetamaskController extends EventEmitter { * @returns {Object} Full state update. */ async signTypedMessage(msgParams) { - log.info('MetaMaskController - eth_signTypedData') - const msgId = msgParams.metamaskId - const { version } = msgParams + log.info('MetaMaskController - eth_signTypedData'); + const msgId = msgParams.metamaskId; + const { version } = msgParams; try { const cleanMsgParams = await this.typedMessageManager.approveMessage( msgParams, - ) + ); // For some reason every version after V1 used stringified params. if (version !== 'V1') { // But we don't have to require that. We can stop suggesting it now: if (typeof cleanMsgParams.data === 'string') { - cleanMsgParams.data = JSON.parse(cleanMsgParams.data) + cleanMsgParams.data = JSON.parse(cleanMsgParams.data); } } const signature = await this.keyringController.signTypedMessage( cleanMsgParams, { version }, - ) - this.typedMessageManager.setMsgStatusSigned(msgId, signature) - return this.getState() + ); + this.typedMessageManager.setMsgStatusSigned(msgId, signature); + return this.getState(); } catch (error) { - log.info('MetaMaskController - eth_signTypedData failed.', error) - this.typedMessageManager.errorMessage(msgId, error) - throw error + log.info('MetaMaskController - eth_signTypedData failed.', error); + this.typedMessageManager.errorMessage(msgId, error); + throw error; } } @@ -1783,12 +1792,12 @@ export default class MetamaskController extends EventEmitter { * @param {Function} cb - The callback function called with a full state update. */ cancelTypedMessage(msgId, cb) { - const messageManager = this.typedMessageManager - messageManager.rejectMsg(msgId) + const messageManager = this.typedMessageManager; + messageManager.rejectMsg(msgId); if (!cb || typeof cb !== 'function') { - return + return; } - cb(null, this.getState()) + cb(null, this.getState()); } //============================================================================= @@ -1806,9 +1815,9 @@ export default class MetamaskController extends EventEmitter { await this.txController.createCancelTransaction( originalTxId, customGasPrice, - ) - const state = await this.getState() - return state + ); + const state = await this.getState(); + return state; } async createSpeedUpTransaction(originalTxId, customGasPrice, customGasLimit) { @@ -1816,9 +1825,9 @@ export default class MetamaskController extends EventEmitter { originalTxId, customGasPrice, customGasLimit, - ) - const state = await this.getState() - return state + ); + const state = await this.getState(); + return state; } estimateGas(estimateGasParams) { @@ -1827,13 +1836,13 @@ export default class MetamaskController extends EventEmitter { estimateGasParams, (err, res) => { if (err) { - return reject(err) + return reject(err); } - return resolve(res) + return resolve(res); }, - ) - }) + ); + }); } //============================================================================= @@ -1845,9 +1854,9 @@ export default class MetamaskController extends EventEmitter { * @param {Function} cb - A callback function called when complete. */ markPasswordForgotten(cb) { - this.preferencesController.setPasswordForgotten(true) - this.sendUpdate() - cb() + this.preferencesController.setPasswordForgotten(true); + this.sendUpdate(); + cb(); } /** @@ -1855,9 +1864,9 @@ export default class MetamaskController extends EventEmitter { * @param {Function} cb - A callback function called when complete. */ unMarkPasswordForgotten(cb) { - this.preferencesController.setPasswordForgotten(false) - this.sendUpdate() - cb() + this.preferencesController.setPasswordForgotten(false); + this.sendUpdate(); + cb(); } //============================================================================= @@ -1877,24 +1886,24 @@ export default class MetamaskController extends EventEmitter { * @param {MessageSender} sender - The sender of the messages on this stream */ setupUntrustedCommunication(connectionStream, sender) { - const { usePhishDetect } = this.preferencesController.store.getState() - const { hostname } = new URL(sender.url) + const { usePhishDetect } = this.preferencesController.store.getState(); + const { hostname } = new URL(sender.url); // Check if new connection is blocked if phishing detection is on if (usePhishDetect && this.phishingController.test(hostname)) { - log.debug('MetaMask - sending phishing warning for', hostname) - this.sendPhishingWarning(connectionStream, hostname) - return + log.debug('MetaMask - sending phishing warning for', hostname); + this.sendPhishingWarning(connectionStream, hostname); + return; } // setup multiplexing - const mux = setupMultiplex(connectionStream) + const mux = setupMultiplex(connectionStream); // messages between inpage and background - this.setupProviderConnection(mux.createStream('metamask-provider'), sender) + this.setupProviderConnection(mux.createStream('metamask-provider'), sender); // TODO:LegacyProvider: Delete // legacy streams - this.setupPublicConfig(mux.createStream('publicConfig')) + this.setupPublicConfig(mux.createStream('publicConfig')); } /** @@ -1908,10 +1917,10 @@ export default class MetamaskController extends EventEmitter { */ setupTrustedCommunication(connectionStream, sender) { // setup multiplexing - const mux = setupMultiplex(connectionStream) + const mux = setupMultiplex(connectionStream); // connect features - this.setupControllerConnection(mux.createStream('controller')) - this.setupProviderConnection(mux.createStream('provider'), sender, true) + this.setupControllerConnection(mux.createStream('controller')); + this.setupProviderConnection(mux.createStream('provider'), sender, true); } /** @@ -1924,9 +1933,9 @@ export default class MetamaskController extends EventEmitter { * @param {string} hostname - The hostname that triggered the suspicion. */ sendPhishingWarning(connectionStream, hostname) { - const mux = setupMultiplex(connectionStream) - const phishingStream = mux.createStream('phishing') - phishingStream.write({ hostname }) + const mux = setupMultiplex(connectionStream); + const phishingStream = mux.createStream('phishing'); + phishingStream.write({ hostname }); } /** @@ -1934,30 +1943,33 @@ export default class MetamaskController extends EventEmitter { * @param {*} outStream - The stream to provide our API over. */ setupControllerConnection(outStream) { - const api = this.getApi() + const api = this.getApi(); // the "weak: false" option is for nodejs only (eg unit tests) // it is a workaround for node v12 support - const dnode = Dnode(api, { weak: false }) + const dnode = Dnode(api, { weak: false }); // report new active controller connection - this.activeControllerConnections += 1 - this.emit('controllerConnectionChanged', this.activeControllerConnections) + this.activeControllerConnections += 1; + this.emit('controllerConnectionChanged', this.activeControllerConnections); // connect dnode api to remote connection pump(outStream, dnode, outStream, (err) => { // report new active controller connection - this.activeControllerConnections -= 1 - this.emit('controllerConnectionChanged', this.activeControllerConnections) + this.activeControllerConnections -= 1; + this.emit( + 'controllerConnectionChanged', + this.activeControllerConnections, + ); // report any error if (err) { - log.error(err) + log.error(err); } - }) + }); dnode.on('remote', (remote) => { // push updates to popup - const sendUpdate = (update) => remote.sendUpdate(update) - this.on('update', sendUpdate) + const sendUpdate = (update) => remote.sendUpdate(update); + this.on('update', sendUpdate); // remove update listener once the connection ends - dnode.on('end', () => this.removeListener('update', sendUpdate)) - }) + dnode.on('end', () => this.removeListener('update', sendUpdate)); + }); } /** @@ -1967,14 +1979,14 @@ export default class MetamaskController extends EventEmitter { * @param {boolean} isInternal - True if this is a connection with an internal process */ setupProviderConnection(outStream, sender, isInternal) { - const origin = isInternal ? 'metamask' : new URL(sender.url).origin - let extensionId + const origin = isInternal ? 'metamask' : new URL(sender.url).origin; + let extensionId; if (sender.id !== this.extension.runtime.id) { - extensionId = sender.id + extensionId = sender.id; } - let tabId + let tabId; if (sender.tab && sender.tab.id) { - tabId = sender.tab.id + tabId = sender.tab.id; } const engine = this.setupProviderEngine({ @@ -1983,25 +1995,25 @@ export default class MetamaskController extends EventEmitter { extensionId, tabId, isInternal, - }) + }); // setup connection - const providerStream = createEngineStream({ engine }) + const providerStream = createEngineStream({ engine }); - const connectionId = this.addConnection(origin, { engine }) + const connectionId = this.addConnection(origin, { engine }); pump(outStream, providerStream, outStream, (err) => { // handle any middleware cleanup engine._middleware.forEach((mid) => { if (mid.destroy && typeof mid.destroy === 'function') { - mid.destroy() + mid.destroy(); } - }) - connectionId && this.removeConnection(origin, connectionId) + }); + connectionId && this.removeConnection(origin, connectionId); if (err) { - log.error(err) + log.error(err); } - }) + }); } /** @@ -2021,35 +2033,35 @@ export default class MetamaskController extends EventEmitter { isInternal = false, }) { // setup json rpc engine stack - const engine = new JsonRpcEngine() - const { provider, blockTracker } = this + const engine = new JsonRpcEngine(); + const { provider, blockTracker } = this; // create filter polyfill middleware - const filterMiddleware = createFilterMiddleware({ provider, blockTracker }) + const filterMiddleware = createFilterMiddleware({ provider, blockTracker }); // create subscription polyfill middleware const subscriptionManager = createSubscriptionManager({ provider, blockTracker, - }) + }); subscriptionManager.events.on('notification', (message) => engine.emit('notification', message), - ) + ); // append origin to each request - engine.push(createOriginMiddleware({ origin })) + engine.push(createOriginMiddleware({ origin })); // append tabId to each request if it exists if (tabId) { - engine.push(createTabIdMiddleware({ tabId })) + engine.push(createTabIdMiddleware({ tabId })); } // logging - engine.push(createLoggerMiddleware({ origin })) + engine.push(createLoggerMiddleware({ origin })); engine.push( createOnboardingMiddleware({ location, registerOnboarding: this.onboardingController.registerOnboarding, }), - ) + ); engine.push( createMethodMiddleware({ origin, @@ -2067,19 +2079,19 @@ export default class MetamaskController extends EventEmitter { this.alertController, ), }), - ) + ); // filter and subscription polyfills - engine.push(filterMiddleware) - engine.push(subscriptionManager.middleware) + engine.push(filterMiddleware); + engine.push(subscriptionManager.middleware); if (!isInternal) { // permissions engine.push( this.permissionsController.createMiddleware({ origin, extensionId }), - ) + ); } // forward to metamask primary provider - engine.push(providerAsMiddleware(provider)) - return engine + engine.push(providerAsMiddleware(provider)); + return engine; } /** @@ -2094,14 +2106,14 @@ export default class MetamaskController extends EventEmitter { * @param {*} outStream - The stream to provide public config over. */ setupPublicConfig(outStream) { - const configStream = storeAsStream(this.publicConfigStore) + const configStream = storeAsStream(this.publicConfigStore); pump(configStream, outStream, (err) => { - configStream.destroy() + configStream.destroy(); if (err) { - log.error(err) + log.error(err); } - }) + }); } /** @@ -2116,19 +2128,19 @@ export default class MetamaskController extends EventEmitter { */ addConnection(origin, { engine }) { if (origin === 'metamask') { - return null + return null; } if (!this.connections[origin]) { - this.connections[origin] = {} + this.connections[origin] = {}; } - const id = nanoid() + const id = nanoid(); this.connections[origin][id] = { engine, - } + }; - return id + return id; } /** @@ -2139,15 +2151,15 @@ export default class MetamaskController extends EventEmitter { * @param {string} id - The connection's id, as returned from addConnection. */ removeConnection(origin, id) { - const connections = this.connections[origin] + const connections = this.connections[origin]; if (!connections) { - return + return; } - delete connections[id] + delete connections[id]; if (Object.keys(connections).length === 0) { - delete this.connections[origin] + delete this.connections[origin]; } } @@ -2164,14 +2176,14 @@ export default class MetamaskController extends EventEmitter { * @param {any} payload - The event payload. */ notifyConnections(origin, payload) { - const connections = this.connections[origin] + const connections = this.connections[origin]; if (connections) { Object.values(connections).forEach((conn) => { if (conn.engine) { - conn.engine.emit('notification', payload) + conn.engine.emit('notification', payload); } - }) + }); } } @@ -2192,15 +2204,15 @@ export default class MetamaskController extends EventEmitter { const getPayload = typeof payload === 'function' ? (origin) => payload(origin) - : () => payload + : () => payload; Object.values(this.connections).forEach((origin) => { Object.values(origin).forEach((conn) => { if (conn.engine) { - conn.engine.emit('notification', getPayload(origin)) + conn.engine.emit('notification', getPayload(origin)); } - }) - }) + }); + }); } // handlers @@ -2212,19 +2224,19 @@ export default class MetamaskController extends EventEmitter { * @private */ async _onKeyringControllerUpdate(state) { - const { keyrings } = state + const { keyrings } = state; const addresses = keyrings.reduce( (acc, { accounts }) => acc.concat(accounts), [], - ) + ); if (!addresses.length) { - return + return; } // Ensure preferences + identities controller know about all addresses - this.preferencesController.syncAddresses(addresses) - this.accountTracker.syncWithAddresses(addresses) + this.preferencesController.syncAddresses(addresses); + this.accountTracker.syncWithAddresses(addresses); } /** @@ -2239,9 +2251,9 @@ export default class MetamaskController extends EventEmitter { isUnlocked: true, accounts: this.permissionsController.getAccounts(origin), }, - } - }) - this.emit('unlock') + }; + }); + this.emit('unlock'); } /** @@ -2254,8 +2266,8 @@ export default class MetamaskController extends EventEmitter { params: { isUnlocked: false, }, - }) - this.emit('lock') + }); + this.emit('lock'); } /** @@ -2265,11 +2277,11 @@ export default class MetamaskController extends EventEmitter { * - The external providers handle diffing the state */ _onStateUpdate(newState) { - this.isClientOpenAndUnlocked = newState.isUnlocked && this._isClientOpen + this.isClientOpenAndUnlocked = newState.isUnlocked && this._isClientOpen; this.notifyAllConnections({ method: NOTIFICATION_NAMES.chainChanged, params: this.getProviderNetworkState(newState), - }) + }); } // misc @@ -2279,14 +2291,14 @@ export default class MetamaskController extends EventEmitter { * @private */ privateSendUpdate() { - this.emit('update', this.getState()) + this.emit('update', this.getState()); } /** * @returns {boolean} Whether the extension is unlocked. */ isUnlocked() { - return this.keyringController.memStore.getState().isUnlocked + return this.keyringController.memStore.getState().isUnlocked; } //============================================================================= @@ -2302,11 +2314,11 @@ export default class MetamaskController extends EventEmitter { const { nonceDetails, releaseLock, - } = await this.txController.nonceTracker.getNonceLock(address) - const pendingNonce = nonceDetails.params.highestSuggested + } = await this.txController.nonceTracker.getNonceLock(address); + const pendingNonce = nonceDetails.params.highestSuggested; - releaseLock() - return pendingNonce + releaseLock(); + return pendingNonce; } /** @@ -2315,20 +2327,22 @@ export default class MetamaskController extends EventEmitter { * @returns {Promise} */ async getNextNonce(address) { - const nonceLock = await this.txController.nonceTracker.getNonceLock(address) - nonceLock.releaseLock() - return nonceLock.nextNonce + const nonceLock = await this.txController.nonceTracker.getNonceLock( + address, + ); + nonceLock.releaseLock(); + return nonceLock.nextNonce; } async sendBackgroundMetaMetrics({ action, name, customVariables } = {}) { if (!action || !name) { - throw new Error('Must provide action and name.') + throw new Error('Must provide action and name.'); } - const metamaskState = await this.getState() + const metamaskState = await this.getState(); const additionalProperties = getBackgroundMetaMetricState({ metamask: metamaskState, - }) + }); this.metaMetricsController.trackEvent( { @@ -2343,7 +2357,7 @@ export default class MetamaskController extends EventEmitter { { matomoEvent: true, }, - ) + ); } /** @@ -2363,22 +2377,22 @@ export default class MetamaskController extends EventEmitter { * @param {boolean} [duplicate] - Whether to duplicate the addresses on both chainIds (default: false) */ async migrateAddressBookState(oldChainId, newChainId, duplicate = false) { - const { addressBook } = this.addressBookController.state + const { addressBook } = this.addressBookController.state; if (!addressBook[oldChainId]) { - return + return; } for (const address of Object.keys(addressBook[oldChainId])) { - const entry = addressBook[oldChainId][address] + const entry = addressBook[oldChainId][address]; this.addressBookController.set( address, entry.name, newChainId, entry.memo, - ) + ); if (!duplicate) { - this.addressBookController.delete(oldChainId, address) + this.addressBookController.delete(oldChainId, address); } } } @@ -2395,20 +2409,20 @@ export default class MetamaskController extends EventEmitter { * @param {Function} cb - A callback function returning currency info. */ setCurrentCurrency(currencyCode, cb) { - const { ticker } = this.networkController.getProviderConfig() + const { ticker } = this.networkController.getProviderConfig(); try { const currencyState = { nativeCurrency: ticker, currentCurrency: currencyCode, - } - this.currencyRateController.update(currencyState) - this.currencyRateController.configure(currencyState) - cb(null, this.currencyRateController.state) - return + }; + this.currencyRateController.update(currencyState); + this.currencyRateController.configure(currencyState); + cb(null, this.currencyRateController.state); + return; } catch (err) { - cb(err) + cb(err); // eslint-disable-next-line no-useless-return - return + return; } } @@ -2433,15 +2447,15 @@ export default class MetamaskController extends EventEmitter { ticker, nickname, rpcPrefs, - ) + ); await this.preferencesController.updateRpc({ rpcUrl, chainId, ticker, nickname, rpcPrefs, - }) - return rpcUrl + }); + return rpcUrl; } /** @@ -2459,10 +2473,10 @@ export default class MetamaskController extends EventEmitter { nickname = '', rpcPrefs = {}, ) { - const frequentRpcListDetail = this.preferencesController.getFrequentRpcListDetail() + const frequentRpcListDetail = this.preferencesController.getFrequentRpcListDetail(); const rpcSettings = frequentRpcListDetail.find( (rpc) => rpcUrl === rpc.rpcUrl, - ) + ); if (rpcSettings) { this.networkController.setRpcTarget( @@ -2471,7 +2485,7 @@ export default class MetamaskController extends EventEmitter { rpcSettings.ticker, rpcSettings.nickname, rpcPrefs, - ) + ); } else { this.networkController.setRpcTarget( rpcUrl, @@ -2479,16 +2493,16 @@ export default class MetamaskController extends EventEmitter { ticker, nickname, rpcPrefs, - ) + ); await this.preferencesController.addToFrequentRpcList( rpcUrl, chainId, ticker, nickname, rpcPrefs, - ) + ); } - return rpcUrl + return rpcUrl; } /** @@ -2496,11 +2510,11 @@ export default class MetamaskController extends EventEmitter { * @param {string} rpcUrl - A RPC URL to delete. */ async delCustomRpc(rpcUrl) { - await this.preferencesController.removeFromFrequentRpcList(rpcUrl) + await this.preferencesController.removeFromFrequentRpcList(rpcUrl); } async initializeThreeBox() { - await this.threeBoxController.init() + await this.threeBoxController.init(); } /** @@ -2510,13 +2524,13 @@ export default class MetamaskController extends EventEmitter { */ setUseBlockie(val, cb) { try { - this.preferencesController.setUseBlockie(val) - cb(null) - return + this.preferencesController.setUseBlockie(val); + cb(null); + return; } catch (err) { - cb(err) + cb(err); // eslint-disable-next-line no-useless-return - return + return; } } @@ -2527,13 +2541,13 @@ export default class MetamaskController extends EventEmitter { */ setUseNonceField(val, cb) { try { - this.preferencesController.setUseNonceField(val) - cb(null) - return + this.preferencesController.setUseNonceField(val); + cb(null); + return; } catch (err) { - cb(err) + cb(err); // eslint-disable-next-line no-useless-return - return + return; } } @@ -2544,13 +2558,13 @@ export default class MetamaskController extends EventEmitter { */ setUsePhishDetect(val, cb) { try { - this.preferencesController.setUsePhishDetect(val) - cb(null) - return + this.preferencesController.setUsePhishDetect(val); + cb(null); + return; } catch (err) { - cb(err) + cb(err); // eslint-disable-next-line no-useless-return - return + return; } } @@ -2561,13 +2575,13 @@ export default class MetamaskController extends EventEmitter { */ setIpfsGateway(val, cb) { try { - this.preferencesController.setIpfsGateway(val) - cb(null) - return + this.preferencesController.setIpfsGateway(val); + cb(null); + return; } catch (err) { - cb(err) + cb(err); // eslint-disable-next-line no-useless-return - return + return; } } @@ -2580,25 +2594,25 @@ export default class MetamaskController extends EventEmitter { try { const metaMetricsId = this.metaMetricsController.setParticipateInMetaMetrics( bool, - ) - cb(null, metaMetricsId) - return + ); + cb(null, metaMetricsId); + return; } catch (err) { - cb(err) + cb(err); // eslint-disable-next-line no-useless-return - return + return; } } setMetaMetricsSendCount(val, cb) { try { - this.metaMetricsController.setMetaMetricsSendCount(val) - cb(null) - return + this.metaMetricsController.setMetaMetricsSendCount(val); + cb(null); + return; } catch (err) { - cb(err) + cb(err); // eslint-disable-next-line no-useless-return - return + return; } } @@ -2609,13 +2623,13 @@ export default class MetamaskController extends EventEmitter { */ setFirstTimeFlowType(type, cb) { try { - this.preferencesController.setFirstTimeFlowType(type) - cb(null) - return + this.preferencesController.setFirstTimeFlowType(type); + cb(null); + return; } catch (err) { - cb(err) + cb(err); // eslint-disable-next-line no-useless-return - return + return; } } @@ -2626,13 +2640,13 @@ export default class MetamaskController extends EventEmitter { */ setCurrentLocale(key, cb) { try { - const direction = this.preferencesController.setCurrentLocale(key) - cb(null, direction) - return + const direction = this.preferencesController.setCurrentLocale(key); + cb(null, direction); + return; } catch (err) { - cb(err) + cb(err); // eslint-disable-next-line no-useless-return - return + return; } } @@ -2643,11 +2657,11 @@ export default class MetamaskController extends EventEmitter { */ recordFirstTimeInfo(initState) { if (!('firstTimeInfo' in initState)) { - const version = this.platform.getVersion() + const version = this.platform.getVersion(); initState.firstTimeInfo = { version, date: Date.now(), - } + }; } } @@ -2659,8 +2673,8 @@ export default class MetamaskController extends EventEmitter { * @param {boolean} open */ set isClientOpen(open) { - this._isClientOpen = open - this.detectTokensController.isOpen = open + this._isClientOpen = open; + this.detectTokensController.isOpen = open; } /* eslint-enable accessor-pairs */ @@ -2669,13 +2683,13 @@ export default class MetamaskController extends EventEmitter { * @param {string} hostname - the domain to safelist */ safelistPhishingDomain(hostname) { - return this.phishingController.bypass(hostname) + return this.phishingController.bypass(hostname); } /** * Locks MetaMask */ setLocked() { - return this.keyringController.setLocked() + return this.keyringController.setLocked(); } } diff --git a/app/scripts/migrations/002.js b/app/scripts/migrations/002.js index 9de898f83..5c8543eff 100644 --- a/app/scripts/migrations/002.js +++ b/app/scripts/migrations/002.js @@ -1,22 +1,22 @@ -import { cloneDeep } from 'lodash' +import { cloneDeep } from 'lodash'; -const version = 2 +const version = 2; export default { version, migrate(originalVersionedData) { - const versionedData = cloneDeep(originalVersionedData) - versionedData.meta.version = version + const versionedData = cloneDeep(originalVersionedData); + versionedData.meta.version = version; try { if (versionedData.data.config.provider.type === 'etherscan') { - versionedData.data.config.provider.type = 'rpc' + versionedData.data.config.provider.type = 'rpc'; versionedData.data.config.provider.rpcTarget = - 'https://rpc.metamask.io/' + 'https://rpc.metamask.io/'; } } catch (_) { // empty } - return Promise.resolve(versionedData) + return Promise.resolve(versionedData); }, -} +}; diff --git a/app/scripts/migrations/003.js b/app/scripts/migrations/003.js index 8859f2a0f..3b6b76e12 100644 --- a/app/scripts/migrations/003.js +++ b/app/scripts/migrations/003.js @@ -1,22 +1,22 @@ -import { cloneDeep } from 'lodash' +import { cloneDeep } from 'lodash'; -const version = 3 -const oldTestRpc = 'https://rawtestrpc.metamask.io/' -const newTestRpc = 'https://testrpc.metamask.io/' +const version = 3; +const oldTestRpc = 'https://rawtestrpc.metamask.io/'; +const newTestRpc = 'https://testrpc.metamask.io/'; export default { version, migrate(originalVersionedData) { - const versionedData = cloneDeep(originalVersionedData) - versionedData.meta.version = version + const versionedData = cloneDeep(originalVersionedData); + versionedData.meta.version = version; try { if (versionedData.data.config.provider.rpcTarget === oldTestRpc) { - versionedData.data.config.provider.rpcTarget = newTestRpc + versionedData.data.config.provider.rpcTarget = newTestRpc; } } catch (_) { // empty } - return Promise.resolve(versionedData) + return Promise.resolve(versionedData); }, -} +}; diff --git a/app/scripts/migrations/004.js b/app/scripts/migrations/004.js index c571e8fd1..49dc444ca 100644 --- a/app/scripts/migrations/004.js +++ b/app/scripts/migrations/004.js @@ -1,33 +1,33 @@ -import { cloneDeep } from 'lodash' +import { cloneDeep } from 'lodash'; -const version = 4 +const version = 4; export default { version, migrate(versionedData) { - const safeVersionedData = cloneDeep(versionedData) - safeVersionedData.meta.version = version + const safeVersionedData = cloneDeep(versionedData); + safeVersionedData.meta.version = version; try { if (safeVersionedData.data.config.provider.type !== 'rpc') { - return Promise.resolve(safeVersionedData) + return Promise.resolve(safeVersionedData); } switch (safeVersionedData.data.config.provider.rpcTarget) { case 'https://testrpc.metamask.io/': safeVersionedData.data.config.provider = { type: 'testnet', - } - break + }; + break; case 'https://rpc.metamask.io/': safeVersionedData.data.config.provider = { type: 'mainnet', - } - break + }; + break; // No default } } catch (_) { // empty } - return Promise.resolve(safeVersionedData) + return Promise.resolve(safeVersionedData); }, -} +}; diff --git a/app/scripts/migrations/005.js b/app/scripts/migrations/005.js index 757462353..c45594646 100644 --- a/app/scripts/migrations/005.js +++ b/app/scripts/migrations/005.js @@ -4,29 +4,29 @@ This migration moves state from the flat state trie into KeyringController subst */ -import { cloneDeep } from 'lodash' +import { cloneDeep } from 'lodash'; -const version = 5 +const version = 5; export default { version, migrate(originalVersionedData) { - const versionedData = cloneDeep(originalVersionedData) - versionedData.meta.version = version + const versionedData = cloneDeep(originalVersionedData); + versionedData.meta.version = version; try { - const state = versionedData.data - const newState = selectSubstateForKeyringController(state) - versionedData.data = newState + const state = versionedData.data; + const newState = selectSubstateForKeyringController(state); + versionedData.data = newState; } catch (err) { - console.warn(`MetaMask Migration #5${err.stack}`) + console.warn(`MetaMask Migration #5${err.stack}`); } - return Promise.resolve(versionedData) + return Promise.resolve(versionedData); }, -} +}; function selectSubstateForKeyringController(state) { - const { config } = state + const { config } = state; const newState = { ...state, KeyringController: { @@ -34,10 +34,10 @@ function selectSubstateForKeyringController(state) { selectedAccount: config.selectedAccount, walletNicknames: state.walletNicknames, }, - } - delete newState.vault - delete newState.walletNicknames - delete newState.config.selectedAccount + }; + delete newState.vault; + delete newState.walletNicknames; + delete newState.config.selectedAccount; - return newState + return newState; } diff --git a/app/scripts/migrations/006.js b/app/scripts/migrations/006.js index 90ff3f2cb..d8c2b48fd 100644 --- a/app/scripts/migrations/006.js +++ b/app/scripts/migrations/006.js @@ -4,29 +4,29 @@ This migration moves KeyringController.selectedAddress to PreferencesController. */ -import { cloneDeep } from 'lodash' +import { cloneDeep } from 'lodash'; -const version = 6 +const version = 6; export default { version, migrate(originalVersionedData) { - const versionedData = cloneDeep(originalVersionedData) - versionedData.meta.version = version + const versionedData = cloneDeep(originalVersionedData); + versionedData.meta.version = version; try { - const state = versionedData.data - const newState = migrateState(state) - versionedData.data = newState + const state = versionedData.data; + const newState = migrateState(state); + versionedData.data = newState; } catch (err) { - console.warn(`MetaMask Migration #${version}${err.stack}`) + console.warn(`MetaMask Migration #${version}${err.stack}`); } - return Promise.resolve(versionedData) + return Promise.resolve(versionedData); }, -} +}; function migrateState(state) { - const keyringSubstate = state.KeyringController + const keyringSubstate = state.KeyringController; // add new state const newState = { @@ -34,10 +34,10 @@ function migrateState(state) { PreferencesController: { selectedAddress: keyringSubstate.selectedAccount, }, - } + }; // rm old state - delete newState.KeyringController.selectedAccount + delete newState.KeyringController.selectedAccount; - return newState + return newState; } diff --git a/app/scripts/migrations/007.js b/app/scripts/migrations/007.js index cea831b7e..73ed80df3 100644 --- a/app/scripts/migrations/007.js +++ b/app/scripts/migrations/007.js @@ -4,26 +4,26 @@ This migration breaks out the TransactionManager substate */ -import { cloneDeep } from 'lodash' +import { cloneDeep } from 'lodash'; -const version = 7 +const version = 7; export default { version, migrate(originalVersionedData) { - const versionedData = cloneDeep(originalVersionedData) - versionedData.meta.version = version + const versionedData = cloneDeep(originalVersionedData); + versionedData.meta.version = version; try { - const state = versionedData.data - const newState = transformState(state) - versionedData.data = newState + const state = versionedData.data; + const newState = transformState(state); + versionedData.data = newState; } catch (err) { - console.warn(`MetaMask Migration #${version}${err.stack}`) + console.warn(`MetaMask Migration #${version}${err.stack}`); } - return Promise.resolve(versionedData) + return Promise.resolve(versionedData); }, -} +}; function transformState(state) { const newState = { @@ -32,9 +32,9 @@ function transformState(state) { transactions: state.transactions || [], gasMultiplier: state.gasMultiplier || 1, }, - } - delete newState.transactions - delete newState.gasMultiplier + }; + delete newState.transactions; + delete newState.gasMultiplier; - return newState + return newState; } diff --git a/app/scripts/migrations/008.js b/app/scripts/migrations/008.js index ce8ab37ce..d27d36882 100644 --- a/app/scripts/migrations/008.js +++ b/app/scripts/migrations/008.js @@ -4,26 +4,26 @@ This migration breaks out the NoticeController substate */ -import { cloneDeep } from 'lodash' +import { cloneDeep } from 'lodash'; -const version = 8 +const version = 8; export default { version, migrate(originalVersionedData) { - const versionedData = cloneDeep(originalVersionedData) - versionedData.meta.version = version + const versionedData = cloneDeep(originalVersionedData); + versionedData.meta.version = version; try { - const state = versionedData.data - const newState = transformState(state) - versionedData.data = newState + const state = versionedData.data; + const newState = transformState(state); + versionedData.data = newState; } catch (err) { - console.warn(`MetaMask Migration #${version}${err.stack}`) + console.warn(`MetaMask Migration #${version}${err.stack}`); } - return Promise.resolve(versionedData) + return Promise.resolve(versionedData); }, -} +}; function transformState(state) { const newState = { @@ -31,8 +31,8 @@ function transformState(state) { NoticeController: { noticesList: state.noticesList || [], }, - } - delete newState.noticesList + }; + delete newState.noticesList; - return newState + return newState; } diff --git a/app/scripts/migrations/009.js b/app/scripts/migrations/009.js index 2d1370bfc..5d8e094ab 100644 --- a/app/scripts/migrations/009.js +++ b/app/scripts/migrations/009.js @@ -4,26 +4,26 @@ This migration breaks out the CurrencyController substate */ -import { cloneDeep, merge } from 'lodash' +import { cloneDeep, merge } from 'lodash'; -const version = 9 +const version = 9; export default { version, migrate(originalVersionedData) { - const versionedData = cloneDeep(originalVersionedData) - versionedData.meta.version = version + const versionedData = cloneDeep(originalVersionedData); + versionedData.meta.version = version; try { - const state = versionedData.data - const newState = transformState(state) - versionedData.data = newState + const state = versionedData.data; + const newState = transformState(state); + versionedData.data = newState; } catch (err) { - console.warn(`MetaMask Migration #${version}${err.stack}`) + console.warn(`MetaMask Migration #${version}${err.stack}`); } - return Promise.resolve(versionedData) + return Promise.resolve(versionedData); }, -} +}; function transformState(state) { const newState = merge({}, state, { @@ -32,11 +32,11 @@ function transformState(state) { conversionRate: state.conversionRate, conversionDate: state.conversionDate, }, - }) - delete newState.currentFiat - delete newState.fiatCurrency - delete newState.conversionRate - delete newState.conversionDate + }); + delete newState.currentFiat; + delete newState.fiatCurrency; + delete newState.conversionRate; + delete newState.conversionDate; - return newState + return newState; } diff --git a/app/scripts/migrations/010.js b/app/scripts/migrations/010.js index 053af2562..2d28691a5 100644 --- a/app/scripts/migrations/010.js +++ b/app/scripts/migrations/010.js @@ -4,34 +4,34 @@ This migration breaks out the ShapeShiftController substate */ -import { cloneDeep, merge } from 'lodash' +import { cloneDeep, merge } from 'lodash'; -const version = 10 +const version = 10; export default { version, migrate(originalVersionedData) { - const versionedData = cloneDeep(originalVersionedData) - versionedData.meta.version = version + const versionedData = cloneDeep(originalVersionedData); + versionedData.meta.version = version; try { - const state = versionedData.data - const newState = transformState(state) - versionedData.data = newState + const state = versionedData.data; + const newState = transformState(state); + versionedData.data = newState; } catch (err) { - console.warn(`MetaMask Migration #${version}${err.stack}`) + console.warn(`MetaMask Migration #${version}${err.stack}`); } - return Promise.resolve(versionedData) + return Promise.resolve(versionedData); }, -} +}; function transformState(state) { const newState = merge({}, state, { ShapeShiftController: { shapeShiftTxList: state.shapeShiftTxList || [], }, - }) - delete newState.shapeShiftTxList + }); + delete newState.shapeShiftTxList; - return newState + return newState; } diff --git a/app/scripts/migrations/011.js b/app/scripts/migrations/011.js index 1e1884825..feae3d100 100644 --- a/app/scripts/migrations/011.js +++ b/app/scripts/migrations/011.js @@ -4,30 +4,30 @@ This migration removes the discaimer state from our app, which was integrated in */ -import { cloneDeep } from 'lodash' +import { cloneDeep } from 'lodash'; -const version = 11 +const version = 11; export default { version, migrate(originalVersionedData) { - const versionedData = cloneDeep(originalVersionedData) - versionedData.meta.version = version + const versionedData = cloneDeep(originalVersionedData); + versionedData.meta.version = version; try { - const state = versionedData.data - const newState = transformState(state) - versionedData.data = newState + const state = versionedData.data; + const newState = transformState(state); + versionedData.data = newState; } catch (err) { - console.warn(`MetaMask Migration #${version}${err.stack}`) + console.warn(`MetaMask Migration #${version}${err.stack}`); } - return Promise.resolve(versionedData) + return Promise.resolve(versionedData); }, -} +}; function transformState(state) { - const newState = state - delete newState.TOSHash - delete newState.isDisclaimerConfirmed - return newState + const newState = state; + delete newState.TOSHash; + delete newState.isDisclaimerConfirmed; + return newState; } diff --git a/app/scripts/migrations/012.js b/app/scripts/migrations/012.js index 3a42992ee..57e339107 100644 --- a/app/scripts/migrations/012.js +++ b/app/scripts/migrations/012.js @@ -4,33 +4,33 @@ This migration modifies our notices to delete their body after being read. */ -import { cloneDeep } from 'lodash' +import { cloneDeep } from 'lodash'; -const version = 12 +const version = 12; export default { version, migrate(originalVersionedData) { - const versionedData = cloneDeep(originalVersionedData) - versionedData.meta.version = version + const versionedData = cloneDeep(originalVersionedData); + versionedData.meta.version = version; try { - const state = versionedData.data - const newState = transformState(state) - versionedData.data = newState + const state = versionedData.data; + const newState = transformState(state); + versionedData.data = newState; } catch (err) { - console.warn(`MetaMask Migration #${version}${err.stack}`) + console.warn(`MetaMask Migration #${version}${err.stack}`); } - return Promise.resolve(versionedData) + return Promise.resolve(versionedData); }, -} +}; function transformState(state) { - const newState = state + const newState = state; newState.NoticeController.noticesList.forEach((notice) => { if (notice.read) { - notice.body = '' + notice.body = ''; } - }) - return newState + }); + return newState; } diff --git a/app/scripts/migrations/013.js b/app/scripts/migrations/013.js index 5c27496dc..f36fa0f1c 100644 --- a/app/scripts/migrations/013.js +++ b/app/scripts/migrations/013.js @@ -4,34 +4,34 @@ This migration modifies the network config from ambiguous 'testnet' to explicit */ -import { cloneDeep } from 'lodash' +import { cloneDeep } from 'lodash'; -const version = 13 +const version = 13; export default { version, migrate(originalVersionedData) { - const versionedData = cloneDeep(originalVersionedData) - versionedData.meta.version = version + const versionedData = cloneDeep(originalVersionedData); + versionedData.meta.version = version; try { - const state = versionedData.data - const newState = transformState(state) - versionedData.data = newState + const state = versionedData.data; + const newState = transformState(state); + versionedData.data = newState; } catch (err) { - console.warn(`MetaMask Migration #${version}${err.stack}`) + console.warn(`MetaMask Migration #${version}${err.stack}`); } - return Promise.resolve(versionedData) + return Promise.resolve(versionedData); }, -} +}; function transformState(state) { - const newState = state - const { config } = newState + const newState = state; + const { config } = newState; if (config && config.provider) { if (config.provider.type === 'testnet') { - newState.config.provider.type = 'ropsten' + newState.config.provider.type = 'ropsten'; } } - return newState + return newState; } diff --git a/app/scripts/migrations/014.js b/app/scripts/migrations/014.js index 0a26fcea4..22eeccdb8 100644 --- a/app/scripts/migrations/014.js +++ b/app/scripts/migrations/014.js @@ -4,31 +4,31 @@ This migration removes provider from config and moves it too NetworkController. */ -import { cloneDeep } from 'lodash' +import { cloneDeep } from 'lodash'; -const version = 14 +const version = 14; export default { version, migrate(originalVersionedData) { - const versionedData = cloneDeep(originalVersionedData) - versionedData.meta.version = version + const versionedData = cloneDeep(originalVersionedData); + versionedData.meta.version = version; try { - const state = versionedData.data - const newState = transformState(state) - versionedData.data = newState + const state = versionedData.data; + const newState = transformState(state); + versionedData.data = newState; } catch (err) { - console.warn(`MetaMask Migration #${version}${err.stack}`) + console.warn(`MetaMask Migration #${version}${err.stack}`); } - return Promise.resolve(versionedData) + return Promise.resolve(versionedData); }, -} +}; function transformState(state) { - const newState = state - newState.NetworkController = {} - newState.NetworkController.provider = newState.config.provider - delete newState.config.provider - return newState + const newState = state; + newState.NetworkController = {}; + newState.NetworkController.provider = newState.config.provider; + delete newState.config.provider; + return newState; } diff --git a/app/scripts/migrations/015.js b/app/scripts/migrations/015.js index f10ee9fd9..f2783cebb 100644 --- a/app/scripts/migrations/015.js +++ b/app/scripts/migrations/015.js @@ -5,41 +5,41 @@ to a 'failed' stated */ -import { cloneDeep } from 'lodash' -import { TRANSACTION_STATUSES } from '../../../shared/constants/transaction' +import { cloneDeep } from 'lodash'; +import { TRANSACTION_STATUSES } from '../../../shared/constants/transaction'; -const version = 15 +const version = 15; export default { version, migrate(originalVersionedData) { - const versionedData = cloneDeep(originalVersionedData) - versionedData.meta.version = version + const versionedData = cloneDeep(originalVersionedData); + versionedData.meta.version = version; try { - const state = versionedData.data - const newState = transformState(state) - versionedData.data = newState + const state = versionedData.data; + const newState = transformState(state); + versionedData.data = newState; } catch (err) { - console.warn(`MetaMask Migration #${version}${err.stack}`) + console.warn(`MetaMask Migration #${version}${err.stack}`); } - return Promise.resolve(versionedData) + return Promise.resolve(versionedData); }, -} +}; function transformState(state) { - const newState = state - const { TransactionController } = newState + const newState = state; + const { TransactionController } = newState; if (TransactionController && TransactionController.transactions) { - const { transactions } = TransactionController + const { transactions } = TransactionController; newState.TransactionController.transactions = transactions.map((txMeta) => { if (!txMeta.err) { - return txMeta + return txMeta; } else if (txMeta.err.message === 'Gave up submitting tx.') { - txMeta.status = TRANSACTION_STATUSES.FAILED + txMeta.status = TRANSACTION_STATUSES.FAILED; } - return txMeta - }) + return txMeta; + }); } - return newState + return newState; } diff --git a/app/scripts/migrations/016.js b/app/scripts/migrations/016.js index 3f3d3973c..542ebe81a 100644 --- a/app/scripts/migrations/016.js +++ b/app/scripts/migrations/016.js @@ -5,46 +5,46 @@ to a 'failed' stated */ -import { cloneDeep } from 'lodash' -import { TRANSACTION_STATUSES } from '../../../shared/constants/transaction' +import { cloneDeep } from 'lodash'; +import { TRANSACTION_STATUSES } from '../../../shared/constants/transaction'; -const version = 16 +const version = 16; export default { version, migrate(originalVersionedData) { - const versionedData = cloneDeep(originalVersionedData) - versionedData.meta.version = version + const versionedData = cloneDeep(originalVersionedData); + versionedData.meta.version = version; try { - const state = versionedData.data - const newState = transformState(state) - versionedData.data = newState + const state = versionedData.data; + const newState = transformState(state); + versionedData.data = newState; } catch (err) { - console.warn(`MetaMask Migration #${version}${err.stack}`) + console.warn(`MetaMask Migration #${version}${err.stack}`); } - return Promise.resolve(versionedData) + return Promise.resolve(versionedData); }, -} +}; function transformState(state) { - const newState = state - const { TransactionController } = newState + const newState = state; + const { TransactionController } = newState; if (TransactionController && TransactionController.transactions) { - const { transactions } = newState.TransactionController + const { transactions } = newState.TransactionController; newState.TransactionController.transactions = transactions.map((txMeta) => { if (!txMeta.err) { - return txMeta + return txMeta; } if ( txMeta.err === 'transaction with the same hash was already imported.' ) { - txMeta.status = TRANSACTION_STATUSES.SUBMITTED - delete txMeta.err + txMeta.status = TRANSACTION_STATUSES.SUBMITTED; + delete txMeta.err; } - return txMeta - }) + return txMeta; + }); } - return newState + return newState; } diff --git a/app/scripts/migrations/017.js b/app/scripts/migrations/017.js index d6814dd8c..8d510b857 100644 --- a/app/scripts/migrations/017.js +++ b/app/scripts/migrations/017.js @@ -4,43 +4,43 @@ This migration sets transactions who were retried and marked as failed to submit */ -import { cloneDeep } from 'lodash' -import { TRANSACTION_STATUSES } from '../../../shared/constants/transaction' +import { cloneDeep } from 'lodash'; +import { TRANSACTION_STATUSES } from '../../../shared/constants/transaction'; -const version = 17 +const version = 17; export default { version, migrate(originalVersionedData) { - const versionedData = cloneDeep(originalVersionedData) - versionedData.meta.version = version + const versionedData = cloneDeep(originalVersionedData); + versionedData.meta.version = version; try { - const state = versionedData.data - const newState = transformState(state) - versionedData.data = newState + const state = versionedData.data; + const newState = transformState(state); + versionedData.data = newState; } catch (err) { - console.warn(`MetaMask Migration #${version}${err.stack}`) + console.warn(`MetaMask Migration #${version}${err.stack}`); } - return Promise.resolve(versionedData) + return Promise.resolve(versionedData); }, -} +}; function transformState(state) { - const newState = state - const { TransactionController } = newState + const newState = state; + const { TransactionController } = newState; if (TransactionController && TransactionController.transactions) { - const { transactions } = newState.TransactionController + const { transactions } = newState.TransactionController; newState.TransactionController.transactions = transactions.map((txMeta) => { if (!txMeta.status === TRANSACTION_STATUSES.FAILED) { - return txMeta + return txMeta; } if (txMeta.retryCount > 0 && txMeta.retryCount < 2) { - txMeta.status = TRANSACTION_STATUSES.SUBMITTED - delete txMeta.err + txMeta.status = TRANSACTION_STATUSES.SUBMITTED; + delete txMeta.err; } - return txMeta - }) + return txMeta; + }); } - return newState + return newState; } diff --git a/app/scripts/migrations/018.js b/app/scripts/migrations/018.js index 5a616514c..10bc9fa69 100644 --- a/app/scripts/migrations/018.js +++ b/app/scripts/migrations/018.js @@ -4,52 +4,52 @@ This migration updates "transaction state history" to diffs style */ -import { cloneDeep } from 'lodash' +import { cloneDeep } from 'lodash'; import { snapshotFromTxMeta, migrateFromSnapshotsToDiffs, -} from '../controllers/transactions/lib/tx-state-history-helpers' +} from '../controllers/transactions/lib/tx-state-history-helpers'; -const version = 18 +const version = 18; export default { version, migrate(originalVersionedData) { - const versionedData = cloneDeep(originalVersionedData) - versionedData.meta.version = version + const versionedData = cloneDeep(originalVersionedData); + versionedData.meta.version = version; try { - const state = versionedData.data - const newState = transformState(state) - versionedData.data = newState + const state = versionedData.data; + const newState = transformState(state); + versionedData.data = newState; } catch (err) { - console.warn(`MetaMask Migration #${version}${err.stack}`) + console.warn(`MetaMask Migration #${version}${err.stack}`); } - return Promise.resolve(versionedData) + return Promise.resolve(versionedData); }, -} +}; function transformState(state) { - const newState = state - const { TransactionController } = newState + const newState = state; + const { TransactionController } = newState; if (TransactionController && TransactionController.transactions) { - const { transactions } = newState.TransactionController + const { transactions } = newState.TransactionController; newState.TransactionController.transactions = transactions.map((txMeta) => { // no history: initialize if (!txMeta.history || txMeta.history.length === 0) { - const snapshot = snapshotFromTxMeta(txMeta) - txMeta.history = [snapshot] - return txMeta + const snapshot = snapshotFromTxMeta(txMeta); + txMeta.history = [snapshot]; + return txMeta; } // has history: migrate const newHistory = migrateFromSnapshotsToDiffs(txMeta.history) // remove empty diffs .filter((entry) => { - return !Array.isArray(entry) || entry.length > 0 - }) - txMeta.history = newHistory - return txMeta - }) + return !Array.isArray(entry) || entry.length > 0; + }); + txMeta.history = newHistory; + return txMeta; + }); } - return newState + return newState; } diff --git a/app/scripts/migrations/019.js b/app/scripts/migrations/019.js index d8cb5f73e..828795e6f 100644 --- a/app/scripts/migrations/019.js +++ b/app/scripts/migrations/019.js @@ -5,38 +5,38 @@ whos nonce is too high */ -import { cloneDeep } from 'lodash' -import { TRANSACTION_STATUSES } from '../../../shared/constants/transaction' +import { cloneDeep } from 'lodash'; +import { TRANSACTION_STATUSES } from '../../../shared/constants/transaction'; -const version = 19 +const version = 19; export default { version, migrate(originalVersionedData) { - const versionedData = cloneDeep(originalVersionedData) - versionedData.meta.version = version + const versionedData = cloneDeep(originalVersionedData); + versionedData.meta.version = version; try { - const state = versionedData.data - const newState = transformState(state) - versionedData.data = newState + const state = versionedData.data; + const newState = transformState(state); + versionedData.data = newState; } catch (err) { - console.warn(`MetaMask Migration #${version}${err.stack}`) + console.warn(`MetaMask Migration #${version}${err.stack}`); } - return Promise.resolve(versionedData) + return Promise.resolve(versionedData); }, -} +}; function transformState(state) { - const newState = state - const { TransactionController } = newState + const newState = state; + const { TransactionController } = newState; if (TransactionController && TransactionController.transactions) { - const { transactions } = newState.TransactionController + const { transactions } = newState.TransactionController; newState.TransactionController.transactions = transactions.map( (txMeta, _, txList) => { if (txMeta.status !== TRANSACTION_STATUSES.SUBMITTED) { - return txMeta + return txMeta; } const confirmedTxs = txList @@ -44,55 +44,58 @@ function transformState(state) { .filter((tx) => tx.txParams.from === txMeta.txParams.from) .filter( (tx) => tx.metamaskNetworkId.from === txMeta.metamaskNetworkId.from, - ) - const highestConfirmedNonce = getHighestNonce(confirmedTxs) + ); + const highestConfirmedNonce = getHighestNonce(confirmedTxs); const pendingTxs = txList .filter((tx) => tx.status === TRANSACTION_STATUSES.SUBMITTED) .filter((tx) => tx.txParams.from === txMeta.txParams.from) .filter( (tx) => tx.metamaskNetworkId.from === txMeta.metamaskNetworkId.from, - ) + ); const highestContinuousNonce = getHighestContinuousFrom( pendingTxs, highestConfirmedNonce, - ) + ); - const maxNonce = Math.max(highestContinuousNonce, highestConfirmedNonce) + const maxNonce = Math.max( + highestContinuousNonce, + highestConfirmedNonce, + ); if (parseInt(txMeta.txParams.nonce, 16) > maxNonce + 1) { - txMeta.status = TRANSACTION_STATUSES.FAILED + txMeta.status = TRANSACTION_STATUSES.FAILED; txMeta.err = { message: 'nonce too high', note: 'migration 019 custom error', - } + }; } - return txMeta + return txMeta; }, - ) + ); } - return newState + return newState; } function getHighestContinuousFrom(txList, startPoint) { const nonces = txList.map((txMeta) => { - const { nonce } = txMeta.txParams - return parseInt(nonce, 16) - }) + const { nonce } = txMeta.txParams; + return parseInt(nonce, 16); + }); - let highest = startPoint + let highest = startPoint; while (nonces.includes(highest)) { - highest += 1 + highest += 1; } - return highest + return highest; } function getHighestNonce(txList) { const nonces = txList.map((txMeta) => { - const { nonce } = txMeta.txParams - return parseInt(nonce || '0x0', 16) - }) - const highestNonce = Math.max.apply(null, nonces) - return highestNonce + const { nonce } = txMeta.txParams; + return parseInt(nonce || '0x0', 16); + }); + const highestNonce = Math.max.apply(null, nonces); + return highestNonce; } diff --git a/app/scripts/migrations/020.js b/app/scripts/migrations/020.js index b2a28cb7a..04884eb41 100644 --- a/app/scripts/migrations/020.js +++ b/app/scripts/migrations/020.js @@ -6,34 +6,34 @@ so that we can version notices in the future. */ -import { cloneDeep } from 'lodash' +import { cloneDeep } from 'lodash'; -const version = 20 +const version = 20; export default { version, migrate(originalVersionedData) { - const versionedData = cloneDeep(originalVersionedData) - versionedData.meta.version = version + const versionedData = cloneDeep(originalVersionedData); + versionedData.meta.version = version; try { - const state = versionedData.data - const newState = transformState(state) - versionedData.data = newState + const state = versionedData.data; + const newState = transformState(state); + versionedData.data = newState; } catch (err) { - console.warn(`MetaMask Migration #${version}${err.stack}`) + console.warn(`MetaMask Migration #${version}${err.stack}`); } - return Promise.resolve(versionedData) + return Promise.resolve(versionedData); }, -} +}; function transformState(state) { - const newState = state + const newState = state; if ('metamask' in newState && !('firstTimeInfo' in newState.metamask)) { newState.metamask.firstTimeInfo = { version: '3.12.0', date: Date.now(), - } + }; } - return newState + return newState; } diff --git a/app/scripts/migrations/021.js b/app/scripts/migrations/021.js index 4783d6ed9..2ae40183c 100644 --- a/app/scripts/migrations/021.js +++ b/app/scripts/migrations/021.js @@ -4,30 +4,30 @@ This migration removes the BlackListController from disk state */ -import { cloneDeep } from 'lodash' +import { cloneDeep } from 'lodash'; -const version = 21 +const version = 21; export default { version, migrate(originalVersionedData) { - const versionedData = cloneDeep(originalVersionedData) - versionedData.meta.version = version + const versionedData = cloneDeep(originalVersionedData); + versionedData.meta.version = version; try { - const state = versionedData.data - const newState = transformState(state) - versionedData.data = newState + const state = versionedData.data; + const newState = transformState(state); + versionedData.data = newState; } catch (err) { - console.warn(`MetaMask Migration #${version}${err.stack}`) + console.warn(`MetaMask Migration #${version}${err.stack}`); } - return Promise.resolve(versionedData) + return Promise.resolve(versionedData); }, -} +}; function transformState(state) { - const newState = state - delete newState.BlacklistController - delete newState.RecentBlocks - return newState + const newState = state; + delete newState.BlacklistController; + delete newState.RecentBlocks; + return newState; } diff --git a/app/scripts/migrations/022.js b/app/scripts/migrations/022.js index cb1b4335f..d0477b0d1 100644 --- a/app/scripts/migrations/022.js +++ b/app/scripts/migrations/022.js @@ -4,44 +4,44 @@ This migration adds submittedTime to the txMeta if it is not their */ -import { cloneDeep } from 'lodash' -import { TRANSACTION_STATUSES } from '../../../shared/constants/transaction' +import { cloneDeep } from 'lodash'; +import { TRANSACTION_STATUSES } from '../../../shared/constants/transaction'; -const version = 22 +const version = 22; export default { version, migrate(originalVersionedData) { - const versionedData = cloneDeep(originalVersionedData) - versionedData.meta.version = version + const versionedData = cloneDeep(originalVersionedData); + versionedData.meta.version = version; try { - const state = versionedData.data - const newState = transformState(state) - versionedData.data = newState + const state = versionedData.data; + const newState = transformState(state); + versionedData.data = newState; } catch (err) { - console.warn(`MetaMask Migration #${version}${err.stack}`) + console.warn(`MetaMask Migration #${version}${err.stack}`); } - return Promise.resolve(versionedData) + return Promise.resolve(versionedData); }, -} +}; function transformState(state) { - const newState = state - const { TransactionController } = newState + const newState = state; + const { TransactionController } = newState; if (TransactionController && TransactionController.transactions) { - const { transactions } = newState.TransactionController + const { transactions } = newState.TransactionController; newState.TransactionController.transactions = transactions.map((txMeta) => { if ( txMeta.status !== TRANSACTION_STATUSES.SUBMITTED || txMeta.submittedTime ) { - return txMeta + return txMeta; } - txMeta.submittedTime = new Date().getTime() - return txMeta - }) + txMeta.submittedTime = new Date().getTime(); + return txMeta; + }); } - return newState + return newState; } diff --git a/app/scripts/migrations/023.js b/app/scripts/migrations/023.js index 531a73e13..4ec54b138 100644 --- a/app/scripts/migrations/023.js +++ b/app/scripts/migrations/023.js @@ -4,41 +4,41 @@ This migration removes transactions that are no longer usefull down to 40 total */ -import { cloneDeep } from 'lodash' -import { TRANSACTION_STATUSES } from '../../../shared/constants/transaction' +import { cloneDeep } from 'lodash'; +import { TRANSACTION_STATUSES } from '../../../shared/constants/transaction'; -const version = 23 +const version = 23; export default { version, migrate(originalVersionedData) { - const versionedData = cloneDeep(originalVersionedData) - versionedData.meta.version = version + const versionedData = cloneDeep(originalVersionedData); + versionedData.meta.version = version; try { - const state = versionedData.data - const newState = transformState(state) - versionedData.data = newState + const state = versionedData.data; + const newState = transformState(state); + versionedData.data = newState; } catch (err) { - console.warn(`MetaMask Migration #${version}${err.stack}`) + console.warn(`MetaMask Migration #${version}${err.stack}`); } - return Promise.resolve(versionedData) + return Promise.resolve(versionedData); }, -} +}; function transformState(state) { - const newState = state + const newState = state; - const { TransactionController } = newState + const { TransactionController } = newState; if (TransactionController && TransactionController.transactions) { - const { transactions } = newState.TransactionController + const { transactions } = newState.TransactionController; if (transactions.length <= 40) { - return newState + return newState; } - const reverseTxList = transactions.reverse() - let stripping = true + const reverseTxList = transactions.reverse(); + let stripping = true; while (reverseTxList.length > 40 && stripping) { const txIndex = reverseTxList.findIndex((txMeta) => { return ( @@ -46,16 +46,16 @@ function transformState(state) { txMeta.status === TRANSACTION_STATUSES.REJECTED || txMeta.status === TRANSACTION_STATUSES.CONFIRMED || txMeta.status === TRANSACTION_STATUSES.DROPPED - ) - }) + ); + }); if (txIndex < 0) { - stripping = false + stripping = false; } else { - reverseTxList.splice(txIndex, 1) + reverseTxList.splice(txIndex, 1); } } - newState.TransactionController.transactions = reverseTxList.reverse() + newState.TransactionController.transactions = reverseTxList.reverse(); } - return newState + return newState; } diff --git a/app/scripts/migrations/024.js b/app/scripts/migrations/024.js index b4189a4e0..1eb210029 100644 --- a/app/scripts/migrations/024.js +++ b/app/scripts/migrations/024.js @@ -5,30 +5,30 @@ all unapproved transactions */ -import { cloneDeep } from 'lodash' -import { TRANSACTION_STATUSES } from '../../../shared/constants/transaction' +import { cloneDeep } from 'lodash'; +import { TRANSACTION_STATUSES } from '../../../shared/constants/transaction'; -const version = 24 +const version = 24; export default { version, async migrate(originalVersionedData) { - const versionedData = cloneDeep(originalVersionedData) - versionedData.meta.version = version - const state = versionedData.data - const newState = transformState(state) - versionedData.data = newState - return versionedData + const versionedData = cloneDeep(originalVersionedData); + versionedData.meta.version = version; + const state = versionedData.data; + const newState = transformState(state); + versionedData.data = newState; + return versionedData; }, -} +}; function transformState(state) { - const newState = state + const newState = state; if (!newState.TransactionController) { - return newState + return newState; } - const { transactions } = newState.TransactionController + const { transactions } = newState.TransactionController; newState.TransactionController.transactions = transactions.map( (txMeta, _) => { if ( @@ -36,10 +36,10 @@ function transformState(state) { txMeta.txParams && txMeta.txParams.from ) { - txMeta.txParams.from = txMeta.txParams.from.toLowerCase() + txMeta.txParams.from = txMeta.txParams.from.toLowerCase(); } - return txMeta + return txMeta; }, - ) - return newState + ); + return newState; } diff --git a/app/scripts/migrations/025.js b/app/scripts/migrations/025.js index 3338ec9cf..7ea7a00cb 100644 --- a/app/scripts/migrations/025.js +++ b/app/scripts/migrations/025.js @@ -4,44 +4,44 @@ normalizes txParams on unconfirmed txs */ -import { cloneDeep } from 'lodash' -import { addHexPrefix } from '../lib/util' -import { TRANSACTION_STATUSES } from '../../../shared/constants/transaction' +import { cloneDeep } from 'lodash'; +import { addHexPrefix } from '../lib/util'; +import { TRANSACTION_STATUSES } from '../../../shared/constants/transaction'; -const version = 25 +const version = 25; export default { version, async migrate(originalVersionedData) { - const versionedData = cloneDeep(originalVersionedData) - versionedData.meta.version = version - const state = versionedData.data - const newState = transformState(state) - versionedData.data = newState - return versionedData + const versionedData = cloneDeep(originalVersionedData); + versionedData.meta.version = version; + const state = versionedData.data; + const newState = transformState(state); + versionedData.data = newState; + return versionedData; }, -} +}; function transformState(state) { - const newState = state + const newState = state; if (newState.TransactionController) { if (newState.TransactionController.transactions) { - const { transactions } = newState.TransactionController + const { transactions } = newState.TransactionController; newState.TransactionController.transactions = transactions.map( (txMeta) => { if (txMeta.status !== TRANSACTION_STATUSES.UNAPPROVED) { - return txMeta + return txMeta; } - txMeta.txParams = normalizeTxParams(txMeta.txParams) - return txMeta + txMeta.txParams = normalizeTxParams(txMeta.txParams); + return txMeta; }, - ) + ); } } - return newState + return newState; } function normalizeTxParams(txParams) { @@ -54,15 +54,15 @@ function normalizeTxParams(txParams) { data: (data) => addHexPrefix(data), gas: (gas) => addHexPrefix(gas), gasPrice: (gasPrice) => addHexPrefix(gasPrice), - } + }; // apply only keys in the whiteList - const normalizedTxParams = {} + const normalizedTxParams = {}; Object.keys(whiteList).forEach((key) => { if (txParams[key]) { - normalizedTxParams[key] = whiteList[key](txParams[key]) + normalizedTxParams[key] = whiteList[key](txParams[key]); } - }) + }); - return normalizedTxParams + return normalizedTxParams; } diff --git a/app/scripts/migrations/026.js b/app/scripts/migrations/026.js index c237cce1c..a141343d0 100644 --- a/app/scripts/migrations/026.js +++ b/app/scripts/migrations/026.js @@ -5,33 +5,33 @@ This migration moves the identities stored in the KeyringController */ -import { cloneDeep } from 'lodash' +import { cloneDeep } from 'lodash'; -const version = 26 +const version = 26; export default { version, migrate(originalVersionedData) { - const versionedData = cloneDeep(originalVersionedData) - versionedData.meta.version = version + const versionedData = cloneDeep(originalVersionedData); + versionedData.meta.version = version; try { - const state = versionedData.data - versionedData.data = transformState(state) + const state = versionedData.data; + versionedData.data = transformState(state); } catch (err) { - console.warn(`MetaMask Migration #${version}${err.stack}`) - return Promise.reject(err) + console.warn(`MetaMask Migration #${version}${err.stack}`); + return Promise.reject(err); } - return Promise.resolve(versionedData) + return Promise.resolve(versionedData); }, -} +}; function transformState(state) { if (!state.KeyringController || !state.PreferencesController) { - return state + return state; } if (!state.KeyringController.walletNicknames) { - return state + return state; } state.PreferencesController.identities = Object.keys( @@ -40,9 +40,9 @@ function transformState(state) { identities[address] = { name: state.KeyringController.walletNicknames[address], address, - } - return identities - }, {}) - delete state.KeyringController.walletNicknames - return state + }; + return identities; + }, {}); + delete state.KeyringController.walletNicknames; + return state; } diff --git a/app/scripts/migrations/027.js b/app/scripts/migrations/027.js index 09d5a00e8..a067e0084 100644 --- a/app/scripts/migrations/027.js +++ b/app/scripts/migrations/027.js @@ -4,35 +4,35 @@ normalizes txParams on unconfirmed txs */ -import { cloneDeep } from 'lodash' -import { TRANSACTION_STATUSES } from '../../../shared/constants/transaction' +import { cloneDeep } from 'lodash'; +import { TRANSACTION_STATUSES } from '../../../shared/constants/transaction'; -const version = 27 +const version = 27; export default { version, async migrate(originalVersionedData) { - const versionedData = cloneDeep(originalVersionedData) - versionedData.meta.version = version - const state = versionedData.data - const newState = transformState(state) - versionedData.data = newState - return versionedData + const versionedData = cloneDeep(originalVersionedData); + versionedData.meta.version = version; + const state = versionedData.data; + const newState = transformState(state); + versionedData.data = newState; + return versionedData; }, -} +}; function transformState(state) { - const newState = state + const newState = state; if (newState.TransactionController) { if (newState.TransactionController.transactions) { - const { transactions } = newState.TransactionController + const { transactions } = newState.TransactionController; newState.TransactionController.transactions = transactions.filter( (txMeta) => txMeta.status !== TRANSACTION_STATUSES.REJECTED, - ) + ); } } - return newState + return newState; } diff --git a/app/scripts/migrations/028.js b/app/scripts/migrations/028.js index 8f83bda04..8ee590e22 100644 --- a/app/scripts/migrations/028.js +++ b/app/scripts/migrations/028.js @@ -4,41 +4,41 @@ normalizes txParams on unconfirmed txs */ -import { cloneDeep } from 'lodash' +import { cloneDeep } from 'lodash'; -const version = 28 +const version = 28; export default { version, async migrate(originalVersionedData) { - const versionedData = cloneDeep(originalVersionedData) - versionedData.meta.version = version - const state = versionedData.data - const newState = transformState(state) - versionedData.data = newState - return versionedData + const versionedData = cloneDeep(originalVersionedData); + versionedData.meta.version = version; + const state = versionedData.data; + const newState = transformState(state); + versionedData.data = newState; + return versionedData; }, -} +}; function transformState(state) { - const newState = state + const newState = state; if (newState.PreferencesController) { if ( newState.PreferencesController.tokens && newState.PreferencesController.identities ) { - const { identities, tokens } = newState.PreferencesController - newState.PreferencesController.accountTokens = {} + const { identities, tokens } = newState.PreferencesController; + newState.PreferencesController.accountTokens = {}; Object.keys(identities).forEach((identity) => { newState.PreferencesController.accountTokens[identity] = { mainnet: tokens, - } - }) - newState.PreferencesController.tokens = [] + }; + }); + newState.PreferencesController.tokens = []; } } - return newState + return newState; } diff --git a/app/scripts/migrations/029.js b/app/scripts/migrations/029.js index 242cc995b..af70ee899 100644 --- a/app/scripts/migrations/029.js +++ b/app/scripts/migrations/029.js @@ -1,14 +1,14 @@ // next version number -import { TRANSACTION_STATUSES } from '../../../shared/constants/transaction' -import failTxsThat from './fail-tx' +import { TRANSACTION_STATUSES } from '../../../shared/constants/transaction'; +import failTxsThat from './fail-tx'; -const version = 29 +const version = 29; // time -const seconds = 1000 -const minutes = 60 * seconds -const hours = 60 * minutes -const unacceptableDelay = 12 * hours +const seconds = 1000; +const minutes = 60 * seconds; +const hours = 60 * minutes; +const unacceptableDelay = 12 * hours; /* @@ -23,10 +23,10 @@ export default { version, 'Stuck in approved state for too long.', (txMeta) => { - const isApproved = txMeta.status === TRANSACTION_STATUSES.APPROVED - const createdTime = txMeta.submittedTime - const now = Date.now() - return isApproved && now - createdTime > unacceptableDelay + const isApproved = txMeta.status === TRANSACTION_STATUSES.APPROVED; + const createdTime = txMeta.submittedTime; + const now = Date.now(); + return isApproved && now - createdTime > unacceptableDelay; }, ), -} +}; diff --git a/app/scripts/migrations/030.js b/app/scripts/migrations/030.js index 1062cbaf2..31dc1cf6e 100644 --- a/app/scripts/migrations/030.js +++ b/app/scripts/migrations/030.js @@ -5,35 +5,35 @@ removes invalid chaids from preferences and networkController for custom rpcs */ -import { cloneDeep } from 'lodash' +import { cloneDeep } from 'lodash'; -const version = 30 +const version = 30; export default { version, async migrate(originalVersionedData) { - const versionedData = cloneDeep(originalVersionedData) - versionedData.meta.version = version - const state = versionedData.data - const newState = transformState(state) - versionedData.data = newState - return versionedData + const versionedData = cloneDeep(originalVersionedData); + versionedData.meta.version = version; + const state = versionedData.data; + const newState = transformState(state); + versionedData.data = newState; + return versionedData; }, -} +}; function transformState(state) { - const newState = state + const newState = state; if (state.PreferencesController) { - const { frequentRpcListDetail } = newState.PreferencesController + const { frequentRpcListDetail } = newState.PreferencesController; if (frequentRpcListDetail) { frequentRpcListDetail.forEach((rpc, index) => { // eslint-disable-next-line radix if (Boolean(rpc.chainId) && Number.isNaN(parseInt(rpc.chainId))) { - delete frequentRpcListDetail[index].chainId + delete frequentRpcListDetail[index].chainId; } - }) - newState.PreferencesController.frequentRpcListDetail = frequentRpcListDetail + }); + newState.PreferencesController.frequentRpcListDetail = frequentRpcListDetail; } } if (state.NetworkController) { @@ -42,7 +42,7 @@ function transformState(state) { // eslint-disable-next-line radix Number.isNaN(parseInt(newState.NetworkController.network)) ) { - delete newState.NetworkController.network + delete newState.NetworkController.network; } if ( @@ -51,9 +51,9 @@ function transformState(state) { // eslint-disable-next-line radix Number.isNaN(parseInt(newState.NetworkController.provider.chainId)) ) { - delete newState.NetworkController.provider.chainId + delete newState.NetworkController.provider.chainId; } } - return newState + return newState; } diff --git a/app/scripts/migrations/031.js b/app/scripts/migrations/031.js index 87eea11fa..904e2da4f 100644 --- a/app/scripts/migrations/031.js +++ b/app/scripts/migrations/031.js @@ -1,7 +1,7 @@ // next version number -import { cloneDeep } from 'lodash' +import { cloneDeep } from 'lodash'; -const version = 31 +const version = 31; /* * The purpose of this migration is to properly set the completedOnboarding flag based on the state @@ -11,22 +11,22 @@ export default { version, async migrate(originalVersionedData) { - const versionedData = cloneDeep(originalVersionedData) - versionedData.meta.version = version - const state = versionedData.data - const newState = transformState(state) - versionedData.data = newState - return versionedData + const versionedData = cloneDeep(originalVersionedData); + versionedData.meta.version = version; + const state = versionedData.data; + const newState = transformState(state); + versionedData.data = newState; + return versionedData; }, -} +}; function transformState(state) { - const { KeyringController, PreferencesController } = state + const { KeyringController, PreferencesController } = state; if (KeyringController && PreferencesController) { - const { vault } = KeyringController - PreferencesController.completedOnboarding = Boolean(vault) + const { vault } = KeyringController; + PreferencesController.completedOnboarding = Boolean(vault); } - return state + return state; } diff --git a/app/scripts/migrations/032.js b/app/scripts/migrations/032.js index facdf1072..0f3ceab39 100644 --- a/app/scripts/migrations/032.js +++ b/app/scripts/migrations/032.js @@ -1,6 +1,6 @@ -import { cloneDeep } from 'lodash' +import { cloneDeep } from 'lodash'; -const version = 32 +const version = 32; /** * The purpose of this migration is to set the {@code completedUiMigration} flag based on the user's UI preferences @@ -8,23 +8,23 @@ const version = 32 export default { version, async migrate(originalVersionedData) { - const versionedData = cloneDeep(originalVersionedData) - versionedData.meta.version = version - const state = versionedData.data - versionedData.data = transformState(state) - return versionedData + const versionedData = cloneDeep(originalVersionedData); + versionedData.meta.version = version; + const state = versionedData.data; + versionedData.data = transformState(state); + return versionedData; }, -} +}; function transformState(state) { - const { PreferencesController } = state + const { PreferencesController } = state; if (PreferencesController) { - const { betaUI } = PreferencesController.featureFlags || {} + const { betaUI } = PreferencesController.featureFlags || {}; // Users who have been using the "beta" UI are considered to have completed the migration // as they'll see no difference in this version - PreferencesController.completedUiMigration = betaUI + PreferencesController.completedUiMigration = betaUI; } - return state + return state; } diff --git a/app/scripts/migrations/033.js b/app/scripts/migrations/033.js index 8f88ba4e1..b815dae66 100644 --- a/app/scripts/migrations/033.js +++ b/app/scripts/migrations/033.js @@ -5,28 +5,28 @@ Cleans up notices and assocated notice controller code */ -import { cloneDeep } from 'lodash' +import { cloneDeep } from 'lodash'; -const version = 33 +const version = 33; export default { version, async migrate(originalVersionedData) { - const versionedData = cloneDeep(originalVersionedData) - versionedData.meta.version = version - const state = versionedData.data - const newState = transformState(state) - versionedData.data = newState - return versionedData + const versionedData = cloneDeep(originalVersionedData); + versionedData.meta.version = version; + const state = versionedData.data; + const newState = transformState(state); + versionedData.data = newState; + return versionedData; }, -} +}; function transformState(state) { - const newState = state + const newState = state; // transform state here if (state.NoticeController) { - delete newState.NoticeController + delete newState.NoticeController; } - return newState + return newState; } diff --git a/app/scripts/migrations/034.js b/app/scripts/migrations/034.js index 4bb2f9491..59369b149 100644 --- a/app/scripts/migrations/034.js +++ b/app/scripts/migrations/034.js @@ -1,6 +1,6 @@ -import { cloneDeep } from 'lodash' +import { cloneDeep } from 'lodash'; -const version = 34 +const version = 34; /** * The purpose of this migration is to enable the {@code privacyMode} feature flag and set the user as being migrated @@ -9,29 +9,29 @@ const version = 34 export default { version, async migrate(originalVersionedData) { - const versionedData = cloneDeep(originalVersionedData) - versionedData.meta.version = version - const state = versionedData.data - versionedData.data = transformState(state) - return versionedData + const versionedData = cloneDeep(originalVersionedData); + versionedData.meta.version = version; + const state = versionedData.data; + versionedData.data = transformState(state); + return versionedData; }, -} +}; function transformState(state) { - const { PreferencesController } = state + const { PreferencesController } = state; if (PreferencesController) { - const featureFlags = PreferencesController.featureFlags || {} + const featureFlags = PreferencesController.featureFlags || {}; if ( !featureFlags.privacyMode && typeof PreferencesController.migratedPrivacyMode === 'undefined' ) { // Mark the state has being migrated and enable Privacy Mode - PreferencesController.migratedPrivacyMode = true - featureFlags.privacyMode = true + PreferencesController.migratedPrivacyMode = true; + featureFlags.privacyMode = true; } } - return state + return state; } diff --git a/app/scripts/migrations/035.js b/app/scripts/migrations/035.js index d98f8562a..0fa498823 100644 --- a/app/scripts/migrations/035.js +++ b/app/scripts/migrations/035.js @@ -5,27 +5,27 @@ Removes the deprecated 'seedWords' state */ -import { cloneDeep } from 'lodash' +import { cloneDeep } from 'lodash'; -const version = 35 +const version = 35; export default { version, async migrate(originalVersionedData) { - const versionedData = cloneDeep(originalVersionedData) - versionedData.meta.version = version - versionedData.data = transformState(versionedData.data) - return versionedData + const versionedData = cloneDeep(originalVersionedData); + versionedData.meta.version = version; + versionedData.data = transformState(versionedData.data); + return versionedData; }, -} +}; function transformState(state) { if ( state.PreferencesController && state.PreferencesController.seedWords !== undefined ) { - delete state.PreferencesController.seedWords + delete state.PreferencesController.seedWords; } - return state + return state; } diff --git a/app/scripts/migrations/036.js b/app/scripts/migrations/036.js index 056f96f01..3fc055bfa 100644 --- a/app/scripts/migrations/036.js +++ b/app/scripts/migrations/036.js @@ -1,6 +1,6 @@ -import { cloneDeep } from 'lodash' +import { cloneDeep } from 'lodash'; -const version = 36 +const version = 36; /** * The purpose of this migration is to remove the {@code privacyMode} feature flag. @@ -8,24 +8,24 @@ const version = 36 export default { version, async migrate(originalVersionedData) { - const versionedData = cloneDeep(originalVersionedData) - versionedData.meta.version = version - const state = versionedData.data - versionedData.data = transformState(state) - return versionedData + const versionedData = cloneDeep(originalVersionedData); + versionedData.meta.version = version; + const state = versionedData.data; + versionedData.data = transformState(state); + return versionedData; }, -} +}; function transformState(state) { - const { PreferencesController } = state + const { PreferencesController } = state; if (PreferencesController) { - const featureFlags = PreferencesController.featureFlags || {} + const featureFlags = PreferencesController.featureFlags || {}; if (typeof featureFlags.privacyMode !== 'undefined') { - delete featureFlags.privacyMode + delete featureFlags.privacyMode; } } - return state + return state; } diff --git a/app/scripts/migrations/037.js b/app/scripts/migrations/037.js index 80a166e61..4552de1da 100644 --- a/app/scripts/migrations/037.js +++ b/app/scripts/migrations/037.js @@ -1,7 +1,7 @@ -import { cloneDeep } from 'lodash' -import { util } from '@metamask/controllers' +import { cloneDeep } from 'lodash'; +import { util } from '@metamask/controllers'; -const version = 37 +const version = 37; /** * The purpose of this migration is to update the address book state @@ -11,43 +11,43 @@ const version = 37 export default { version, async migrate(originalVersionedData) { - const versionedData = cloneDeep(originalVersionedData) - versionedData.meta.version = version - const state = versionedData.data - versionedData.data = transformState(state) - return versionedData + const versionedData = cloneDeep(originalVersionedData); + versionedData.meta.version = version; + const state = versionedData.data; + versionedData.data = transformState(state); + return versionedData; }, -} +}; function transformState(state) { if (state.AddressBookController) { - const ab = state.AddressBookController.addressBook + const ab = state.AddressBookController.addressBook; - const chainIds = new Set() - const newAddressBook = {} + const chainIds = new Set(); + const newAddressBook = {}; // add all of the chainIds to a set Object.values(ab).forEach((v) => { - chainIds.add(v.chainId) - }) + chainIds.add(v.chainId); + }); // fill the chainId object with the entries with the matching chainId for (const id of chainIds.values()) { // make an empty object entry for each chainId - newAddressBook[id] = {} + newAddressBook[id] = {}; for (const address in ab) { if (ab[address].chainId === id) { - ab[address].isEns = false + ab[address].isEns = false; if (util.normalizeEnsName(ab[address].name)) { - ab[address].isEns = true + ab[address].isEns = true; } - newAddressBook[id][address] = ab[address] + newAddressBook[id][address] = ab[address]; } } } - state.AddressBookController.addressBook = newAddressBook + state.AddressBookController.addressBook = newAddressBook; } - return state + return state; } diff --git a/app/scripts/migrations/038.js b/app/scripts/migrations/038.js index 9c179735b..c533f338a 100644 --- a/app/scripts/migrations/038.js +++ b/app/scripts/migrations/038.js @@ -1,6 +1,6 @@ -import { cloneDeep } from 'lodash' +import { cloneDeep } from 'lodash'; -const version = 38 +const version = 38; /** * The purpose of this migration is to assign all users to a test group for the fullScreenVsPopup a/b test @@ -8,20 +8,20 @@ const version = 38 export default { version, async migrate(originalVersionedData) { - const versionedData = cloneDeep(originalVersionedData) - versionedData.meta.version = version - const state = versionedData.data - versionedData.data = transformState(state) - return versionedData + const versionedData = cloneDeep(originalVersionedData); + versionedData.meta.version = version; + const state = versionedData.data; + versionedData.data = transformState(state); + return versionedData; }, -} +}; function transformState(state) { - const { ABTestController: ABTestControllerState = {} } = state - const { abTests = {} } = ABTestControllerState + const { ABTestController: ABTestControllerState = {} } = state; + const { abTests = {} } = ABTestControllerState; if (abTests.fullScreenVsPopup) { - return state + return state; } return { @@ -33,5 +33,5 @@ function transformState(state) { fullScreenVsPopup: 'control', }, }, - } + }; } diff --git a/app/scripts/migrations/039.js b/app/scripts/migrations/039.js index d8bec42e4..adc8390db 100644 --- a/app/scripts/migrations/039.js +++ b/app/scripts/migrations/039.js @@ -1,11 +1,11 @@ -import { cloneDeep } from 'lodash' -import ethUtil from 'ethereumjs-util' +import { cloneDeep } from 'lodash'; +import ethUtil from 'ethereumjs-util'; -const version = 39 +const version = 39; -const DAI_V1_CONTRACT_ADDRESS = '0x89d24A6b4CcB1B6fAA2625fE562bDD9a23260359' -const DAI_V1_TOKEN_SYMBOL = 'DAI' -const SAI_TOKEN_SYMBOL = 'SAI' +const DAI_V1_CONTRACT_ADDRESS = '0x89d24A6b4CcB1B6fAA2625fE562bDD9a23260359'; +const DAI_V1_TOKEN_SYMBOL = 'DAI'; +const SAI_TOKEN_SYMBOL = 'SAI'; function isOldDai(token = {}) { return ( @@ -13,7 +13,7 @@ function isOldDai(token = {}) { typeof token === 'object' && token.symbol === DAI_V1_TOKEN_SYMBOL && ethUtil.toChecksumAddress(token.address) === DAI_V1_CONTRACT_ADDRESS - ) + ); } /** @@ -26,38 +26,38 @@ function isOldDai(token = {}) { export default { version, async migrate(originalVersionedData) { - const versionedData = cloneDeep(originalVersionedData) - versionedData.meta.version = version - const state = versionedData.data - versionedData.data = transformState(state) - return versionedData + const versionedData = cloneDeep(originalVersionedData); + versionedData.meta.version = version; + const state = versionedData.data; + versionedData.data = transformState(state); + return versionedData; }, -} +}; function transformState(state) { - const { PreferencesController } = state + const { PreferencesController } = state; if (PreferencesController) { - const tokens = PreferencesController.tokens || [] + const tokens = PreferencesController.tokens || []; if (Array.isArray(tokens)) { for (const token of tokens) { if (isOldDai(token)) { - token.symbol = SAI_TOKEN_SYMBOL + token.symbol = SAI_TOKEN_SYMBOL; } } } - const accountTokens = PreferencesController.accountTokens || {} + const accountTokens = PreferencesController.accountTokens || {}; if (accountTokens && typeof accountTokens === 'object') { for (const address of Object.keys(accountTokens)) { - const networkTokens = accountTokens[address] + const networkTokens = accountTokens[address]; if (networkTokens && typeof networkTokens === 'object') { for (const network of Object.keys(networkTokens)) { - const tokensOnNetwork = networkTokens[network] + const tokensOnNetwork = networkTokens[network]; if (Array.isArray(tokensOnNetwork)) { for (const token of tokensOnNetwork) { if (isOldDai(token)) { - token.symbol = SAI_TOKEN_SYMBOL + token.symbol = SAI_TOKEN_SYMBOL; } } } @@ -67,5 +67,5 @@ function transformState(state) { } } - return state + return state; } diff --git a/app/scripts/migrations/040.js b/app/scripts/migrations/040.js index 49f91fecd..6c91693b6 100644 --- a/app/scripts/migrations/040.js +++ b/app/scripts/migrations/040.js @@ -1,6 +1,6 @@ -import { cloneDeep } from 'lodash' +import { cloneDeep } from 'lodash'; -const version = 40 +const version = 40; /** * Site connections are now managed by the PermissionsController, and the @@ -10,15 +10,15 @@ const version = 40 export default { version, async migrate(originalVersionedData) { - const versionedData = cloneDeep(originalVersionedData) - versionedData.meta.version = version - const state = versionedData.data - versionedData.data = transformState(state) - return versionedData + const versionedData = cloneDeep(originalVersionedData); + versionedData.meta.version = version; + const state = versionedData.data; + versionedData.data = transformState(state); + return versionedData; }, -} +}; function transformState(state) { - delete state.ProviderApprovalController - return state + delete state.ProviderApprovalController; + return state; } diff --git a/app/scripts/migrations/041.js b/app/scripts/migrations/041.js index eb0964e4c..a93c5a115 100644 --- a/app/scripts/migrations/041.js +++ b/app/scripts/migrations/041.js @@ -1,6 +1,6 @@ -import { cloneDeep } from 'lodash' +import { cloneDeep } from 'lodash'; -const version = 41 +const version = 41; /** * PreferencesController.autoLogoutTimeLimit -> autoLockTimeLimit @@ -8,19 +8,19 @@ const version = 41 export default { version, async migrate(originalVersionedData) { - const versionedData = cloneDeep(originalVersionedData) - versionedData.meta.version = version - const state = versionedData.data - versionedData.data = transformState(state) - return versionedData + const versionedData = cloneDeep(originalVersionedData); + versionedData.meta.version = version; + const state = versionedData.data; + versionedData.data = transformState(state); + return versionedData; }, -} +}; function transformState(state) { if (state.PreferencesController && state.PreferencesController.preferences) { state.PreferencesController.preferences.autoLockTimeLimit = - state.PreferencesController.preferences.autoLogoutTimeLimit - delete state.PreferencesController.preferences.autoLogoutTimeLimit + state.PreferencesController.preferences.autoLogoutTimeLimit; + delete state.PreferencesController.preferences.autoLogoutTimeLimit; } - return state + return state; } diff --git a/app/scripts/migrations/042.js b/app/scripts/migrations/042.js index ca52cada7..5320ecf53 100644 --- a/app/scripts/migrations/042.js +++ b/app/scripts/migrations/042.js @@ -1,6 +1,6 @@ -import { cloneDeep } from 'lodash' +import { cloneDeep } from 'lodash'; -const version = 42 +const version = 42; /** * Initialize `connectedStatusPopoverHasBeenShown` to `false` if it hasn't yet been set, @@ -9,21 +9,21 @@ const version = 42 export default { version, async migrate(originalVersionedData) { - const versionedData = cloneDeep(originalVersionedData) - versionedData.meta.version = version - const state = versionedData.data - versionedData.data = transformState(state) - return versionedData + const versionedData = cloneDeep(originalVersionedData); + versionedData.meta.version = version; + const state = versionedData.data; + versionedData.data = transformState(state); + return versionedData; }, -} +}; function transformState(state) { if (state.AppStateController) { - state.AppStateController.connectedStatusPopoverHasBeenShown = false + state.AppStateController.connectedStatusPopoverHasBeenShown = false; } else { state.AppStateController = { connectedStatusPopoverHasBeenShown: false, - } + }; } - return state + return state; } diff --git a/app/scripts/migrations/043.js b/app/scripts/migrations/043.js index afee378f8..963a87549 100644 --- a/app/scripts/migrations/043.js +++ b/app/scripts/migrations/043.js @@ -1,6 +1,6 @@ -import { cloneDeep } from 'lodash' +import { cloneDeep } from 'lodash'; -const version = 43 +const version = 43; /** * Remove unused 'currentAccountTab' state @@ -8,17 +8,17 @@ const version = 43 export default { version, async migrate(originalVersionedData) { - const versionedData = cloneDeep(originalVersionedData) - versionedData.meta.version = version - const state = versionedData.data - versionedData.data = transformState(state) - return versionedData + const versionedData = cloneDeep(originalVersionedData); + versionedData.meta.version = version; + const state = versionedData.data; + versionedData.data = transformState(state); + return versionedData; }, -} +}; function transformState(state) { if (state?.PreferencesController?.currentAccountTab) { - delete state.PreferencesController.currentAccountTab + delete state.PreferencesController.currentAccountTab; } - return state + return state; } diff --git a/app/scripts/migrations/044.js b/app/scripts/migrations/044.js index a3fcf5036..8bb3be857 100644 --- a/app/scripts/migrations/044.js +++ b/app/scripts/migrations/044.js @@ -1,6 +1,6 @@ -import { cloneDeep } from 'lodash' +import { cloneDeep } from 'lodash'; -const version = 44 +const version = 44; /** * Remove unused 'mkrMigrationReminderTimestamp' state from the `AppStateController` @@ -8,20 +8,20 @@ const version = 44 export default { version, async migrate(originalVersionedData) { - const versionedData = cloneDeep(originalVersionedData) - versionedData.meta.version = version - const state = versionedData.data - versionedData.data = transformState(state) - return versionedData + const versionedData = cloneDeep(originalVersionedData); + versionedData.meta.version = version; + const state = versionedData.data; + versionedData.data = transformState(state); + return versionedData; }, -} +}; function transformState(state) { if ( typeof state?.AppStateController?.mkrMigrationReminderTimestamp !== 'undefined' ) { - delete state.AppStateController.mkrMigrationReminderTimestamp + delete state.AppStateController.mkrMigrationReminderTimestamp; } - return state + return state; } diff --git a/app/scripts/migrations/045.js b/app/scripts/migrations/045.js index 69965845a..50d99f307 100644 --- a/app/scripts/migrations/045.js +++ b/app/scripts/migrations/045.js @@ -1,6 +1,6 @@ -import { cloneDeep } from 'lodash' +import { cloneDeep } from 'lodash'; -const version = 45 +const version = 45; /** * Replaces {@code PreferencesController.ipfsGateway} with 'dweb.link' if set @@ -8,19 +8,19 @@ const version = 45 export default { version, async migrate(originalVersionedData) { - const versionedData = cloneDeep(originalVersionedData) - versionedData.meta.version = version - const state = versionedData.data - versionedData.data = transformState(state) - return versionedData + const versionedData = cloneDeep(originalVersionedData); + versionedData.meta.version = version; + const state = versionedData.data; + versionedData.data = transformState(state); + return versionedData; }, -} +}; -const outdatedGateways = ['ipfs.io', 'ipfs.dweb.link'] +const outdatedGateways = ['ipfs.io', 'ipfs.dweb.link']; function transformState(state) { if (outdatedGateways.includes(state?.PreferencesController?.ipfsGateway)) { - state.PreferencesController.ipfsGateway = 'dweb.link' + state.PreferencesController.ipfsGateway = 'dweb.link'; } - return state + return state; } diff --git a/app/scripts/migrations/046.js b/app/scripts/migrations/046.js index d7e2fbcec..9aaefdaec 100644 --- a/app/scripts/migrations/046.js +++ b/app/scripts/migrations/046.js @@ -1,6 +1,6 @@ -import { cloneDeep } from 'lodash' +import { cloneDeep } from 'lodash'; -const version = 46 +const version = 46; /** * Delete {@code ABTestController} state @@ -8,17 +8,17 @@ const version = 46 export default { version, async migrate(originalVersionedData) { - const versionedData = cloneDeep(originalVersionedData) - versionedData.meta.version = version - const state = versionedData.data - versionedData.data = transformState(state) - return versionedData + const versionedData = cloneDeep(originalVersionedData); + versionedData.meta.version = version; + const state = versionedData.data; + versionedData.data = transformState(state); + return versionedData; }, -} +}; function transformState(state) { if (typeof state?.ABTestController !== 'undefined') { - delete state.ABTestController + delete state.ABTestController; } - return state + return state; } diff --git a/app/scripts/migrations/047.js b/app/scripts/migrations/047.js index 2e3fffe84..b3d2a6fd7 100644 --- a/app/scripts/migrations/047.js +++ b/app/scripts/migrations/047.js @@ -1,6 +1,6 @@ -import { cloneDeep } from 'lodash' +import { cloneDeep } from 'lodash'; -const version = 47 +const version = 47; /** * Stringify the `metamaskNetworkId` property of all transactions @@ -8,22 +8,22 @@ const version = 47 export default { version, async migrate(originalVersionedData) { - const versionedData = cloneDeep(originalVersionedData) - versionedData.meta.version = version - const state = versionedData.data - versionedData.data = transformState(state) - return versionedData + const versionedData = cloneDeep(originalVersionedData); + versionedData.meta.version = version; + const state = versionedData.data; + versionedData.data = transformState(state); + return versionedData; }, -} +}; function transformState(state) { - const transactions = state?.TransactionController?.transactions + const transactions = state?.TransactionController?.transactions; if (Array.isArray(transactions)) { transactions.forEach((transaction) => { if (typeof transaction.metamaskNetworkId === 'number') { - transaction.metamaskNetworkId = transaction.metamaskNetworkId.toString() + transaction.metamaskNetworkId = transaction.metamaskNetworkId.toString(); } - }) + }); } - return state + return state; } diff --git a/app/scripts/migrations/048.js b/app/scripts/migrations/048.js index 4a7c1fecf..75d80f633 100644 --- a/app/scripts/migrations/048.js +++ b/app/scripts/migrations/048.js @@ -1,6 +1,6 @@ -import { cloneDeep } from 'lodash' +import { cloneDeep } from 'lodash'; -const version = 48 +const version = 48; /** * 1. Delete NetworkController.settings @@ -17,27 +17,27 @@ const version = 48 export default { version, async migrate(originalVersionedData) { - const versionedData = cloneDeep(originalVersionedData) - versionedData.meta.version = version - const state = versionedData.data - versionedData.data = transformState(state) - return versionedData + const versionedData = cloneDeep(originalVersionedData); + versionedData.meta.version = version; + const state = versionedData.data; + versionedData.data = transformState(state); + return versionedData; }, -} +}; -const hexRegEx = /^0x[0-9a-f]+$/iu -const chainIdRegEx = /^0x[1-9a-f]+[0-9a-f]*$/iu +const hexRegEx = /^0x[0-9a-f]+$/iu; +const chainIdRegEx = /^0x[1-9a-f]+[0-9a-f]*$/iu; function transformState(state = {}) { // 1. Delete NetworkController.settings - delete state.NetworkController?.settings + delete state.NetworkController?.settings; // 2. Migrate NetworkController.provider to Rinkeby or rename rpcTarget key - const provider = state.NetworkController?.provider || {} + const provider = state.NetworkController?.provider || {}; const isCustomRpcWithInvalidChainId = provider.type === 'rpc' && (typeof provider.chainId !== 'string' || - !chainIdRegEx.test(provider.chainId)) + !chainIdRegEx.test(provider.chainId)); if (isCustomRpcWithInvalidChainId || provider.type === 'localhost') { state.NetworkController.provider = { type: 'rinkeby', @@ -46,21 +46,21 @@ function transformState(state = {}) { nickname: '', rpcPrefs: {}, ticker: 'ETH', - } + }; } else if (state.NetworkController?.provider) { if ('rpcTarget' in state.NetworkController.provider) { - const rpcUrl = state.NetworkController.provider.rpcTarget - state.NetworkController.provider.rpcUrl = rpcUrl + const rpcUrl = state.NetworkController.provider.rpcTarget; + state.NetworkController.provider.rpcUrl = rpcUrl; } - delete state.NetworkController?.provider?.rpcTarget + delete state.NetworkController?.provider?.rpcTarget; } // 3. Add localhost network to frequentRpcListDetail. if (!state.PreferencesController) { - state.PreferencesController = {} + state.PreferencesController = {}; } if (!state.PreferencesController.frequentRpcListDetail) { - state.PreferencesController.frequentRpcListDetail = [] + state.PreferencesController.frequentRpcListDetail = []; } state.PreferencesController.frequentRpcListDetail.unshift({ rpcUrl: 'http://localhost:8545', @@ -68,16 +68,16 @@ function transformState(state = {}) { ticker: 'ETH', nickname: 'Localhost 8545', rpcPrefs: {}, - }) + }); // 4. Delete CachedBalancesController.cachedBalances - delete state.CachedBalancesController?.cachedBalances + delete state.CachedBalancesController?.cachedBalances; // 5. Convert transactions metamaskNetworkId to decimal if they are hex - const transactions = state.TransactionController?.transactions + const transactions = state.TransactionController?.transactions; if (Array.isArray(transactions)) { transactions.forEach((transaction) => { - const metamaskNetworkId = transaction?.metamaskNetworkId + const metamaskNetworkId = transaction?.metamaskNetworkId; if ( typeof metamaskNetworkId === 'string' && hexRegEx.test(metamaskNetworkId) @@ -85,54 +85,54 @@ function transformState(state = {}) { transaction.metamaskNetworkId = parseInt( metamaskNetworkId, 16, - ).toString(10) + ).toString(10); } - }) + }); } // 6. Convert address book keys from decimal to hex - const addressBook = state.AddressBookController?.addressBook || {} + const addressBook = state.AddressBookController?.addressBook || {}; Object.keys(addressBook).forEach((networkKey) => { if (/^\d+$/iu.test(networkKey)) { - const chainId = `0x${parseInt(networkKey, 10).toString(16)}` - updateChainIds(addressBook[networkKey], chainId) + const chainId = `0x${parseInt(networkKey, 10).toString(16)}`; + updateChainIds(addressBook[networkKey], chainId); if (addressBook[chainId]) { - mergeAddressBookKeys(addressBook, networkKey, chainId) + mergeAddressBookKeys(addressBook, networkKey, chainId); } else { - addressBook[chainId] = addressBook[networkKey] + addressBook[chainId] = addressBook[networkKey]; } - delete addressBook[networkKey] + delete addressBook[networkKey]; } - }) + }); // 7. Delete localhost key in IncomingTransactionsController delete state.IncomingTransactionsController - ?.incomingTxLastFetchedBlocksByNetwork?.localhost + ?.incomingTxLastFetchedBlocksByNetwork?.localhost; // 8. Merge 'localhost' tokens into 'rpc' tokens - const accountTokens = state.PreferencesController?.accountTokens + const accountTokens = state.PreferencesController?.accountTokens; if (accountTokens) { Object.keys(accountTokens).forEach((account) => { - const localhostTokens = accountTokens[account]?.localhost || [] + const localhostTokens = accountTokens[account]?.localhost || []; if (localhostTokens.length > 0) { - const rpcTokens = accountTokens[account].rpc || [] + const rpcTokens = accountTokens[account].rpc || []; if (rpcTokens.length > 0) { accountTokens[account].rpc = mergeTokenArrays( localhostTokens, rpcTokens, - ) + ); } else { - accountTokens[account].rpc = localhostTokens + accountTokens[account].rpc = localhostTokens; } } - delete accountTokens[account]?.localhost - }) + delete accountTokens[account]?.localhost; + }); } - return state + return state; } /** @@ -141,14 +141,14 @@ function transformState(state = {}) { * @returns {void} */ function mergeAddressBookKeys(addressBook, networkKey, chainIdKey) { - const networkKeyEntries = addressBook[networkKey] || {} + const networkKeyEntries = addressBook[networkKey] || {}; // For the new entries, start by copying the existing entries for the chainId - const newEntries = { ...addressBook[chainIdKey] } + const newEntries = { ...addressBook[chainIdKey] }; // For each address of the old/networkId key entries Object.keys(networkKeyEntries).forEach((address) => { if (newEntries[address] && typeof newEntries[address] === 'object') { - const mergedEntry = {} + const mergedEntry = {}; // Collect all keys from both entries and merge the corresponding chainId // entry with the networkId entry @@ -158,21 +158,21 @@ function mergeAddressBookKeys(addressBook, networkKey, chainIdKey) { ]).forEach((key) => { // Use non-empty value for the current key, if any mergedEntry[key] = - newEntries[address][key] || networkKeyEntries[address]?.[key] || '' - }) + newEntries[address][key] || networkKeyEntries[address]?.[key] || ''; + }); - newEntries[address] = mergedEntry + newEntries[address] = mergedEntry; } else if ( networkKeyEntries[address] && typeof networkKeyEntries[address] === 'object' ) { // If there is no corresponding chainId entry, just use the networkId entry // directly - newEntries[address] = networkKeyEntries[address] + newEntries[address] = networkKeyEntries[address]; } - }) + }); - addressBook[chainIdKey] = newEntries + addressBook[chainIdKey] = newEntries; } /** @@ -184,9 +184,9 @@ function mergeAddressBookKeys(addressBook, networkKey, chainIdKey) { function updateChainIds(networkEntries, chainId) { Object.values(networkEntries).forEach((entry) => { if (entry && typeof entry === 'object') { - entry.chainId = chainId + entry.chainId = chainId; } - }) + }); } /** @@ -196,10 +196,10 @@ function updateChainIds(networkEntries, chainId) { * @returns {Array} */ function mergeTokenArrays(localhostTokens, rpcTokens) { - const localhostTokensMap = tokenArrayToMap(localhostTokens) - const rpcTokensMap = tokenArrayToMap(rpcTokens) + const localhostTokensMap = tokenArrayToMap(localhostTokens); + const rpcTokensMap = tokenArrayToMap(rpcTokens); - const mergedTokens = [] + const mergedTokens = []; new Set([ ...Object.keys(localhostTokensMap), ...Object.keys(rpcTokensMap), @@ -207,17 +207,17 @@ function mergeTokenArrays(localhostTokens, rpcTokens) { mergedTokens.push({ ...localhostTokensMap[tokenAddress], ...rpcTokensMap[tokenAddress], - }) - }) + }); + }); - return mergedTokens + return mergedTokens; function tokenArrayToMap(array) { return array.reduce((map, token) => { if (token?.address && typeof token?.address === 'string') { - map[token.address] = token + map[token.address] = token; } - return map - }, {}) + return map; + }, {}); } } diff --git a/app/scripts/migrations/049.js b/app/scripts/migrations/049.js index 6a9b6ea43..6b3013d82 100644 --- a/app/scripts/migrations/049.js +++ b/app/scripts/migrations/049.js @@ -1,6 +1,6 @@ -import { cloneDeep } from 'lodash' +import { cloneDeep } from 'lodash'; -const version = 49 +const version = 49; /** * Migrate metaMetrics state to the new MetaMetrics controller @@ -8,13 +8,13 @@ const version = 49 export default { version, async migrate(originalVersionedData) { - const versionedData = cloneDeep(originalVersionedData) - versionedData.meta.version = version - const state = versionedData.data - versionedData.data = transformState(state) - return versionedData + const versionedData = cloneDeep(originalVersionedData); + versionedData.meta.version = version; + const state = versionedData.data; + versionedData.data = transformState(state); + return versionedData; }, -} +}; function transformState(state = {}) { if (state.PreferencesController) { @@ -22,23 +22,23 @@ function transformState(state = {}) { metaMetricsId, participateInMetaMetrics, metaMetricsSendCount, - } = state.PreferencesController - state.MetaMetricsController = state.MetaMetricsController ?? {} + } = state.PreferencesController; + state.MetaMetricsController = state.MetaMetricsController ?? {}; if (metaMetricsId !== undefined) { - state.MetaMetricsController.metaMetricsId = metaMetricsId - delete state.PreferencesController.metaMetricsId + state.MetaMetricsController.metaMetricsId = metaMetricsId; + delete state.PreferencesController.metaMetricsId; } if (participateInMetaMetrics !== undefined) { - state.MetaMetricsController.participateInMetaMetrics = participateInMetaMetrics - delete state.PreferencesController.participateInMetaMetrics + state.MetaMetricsController.participateInMetaMetrics = participateInMetaMetrics; + delete state.PreferencesController.participateInMetaMetrics; } if (metaMetricsSendCount !== undefined) { - state.MetaMetricsController.metaMetricsSendCount = metaMetricsSendCount - delete state.PreferencesController.metaMetricsSendCount + state.MetaMetricsController.metaMetricsSendCount = metaMetricsSendCount; + delete state.PreferencesController.metaMetricsSendCount; } } - return state + return state; } diff --git a/app/scripts/migrations/050.js b/app/scripts/migrations/050.js index af2873873..0d7b16296 100644 --- a/app/scripts/migrations/050.js +++ b/app/scripts/migrations/050.js @@ -1,6 +1,6 @@ -import { cloneDeep } from 'lodash' +import { cloneDeep } from 'lodash'; -const version = 50 +const version = 50; const LEGACY_LOCAL_STORAGE_KEYS = [ 'METASWAP_GAS_PRICE_ESTIMATES_LAST_RETRIEVED', @@ -12,7 +12,7 @@ const LEGACY_LOCAL_STORAGE_KEYS = [ 'BASIC_GAS_AND_TIME_API_ESTIMATES_LAST_RETRIEVED', 'GAS_API_ESTIMATES_LAST_RETRIEVED', 'GAS_API_ESTIMATES', -] +]; /** * Migrate metaMetrics state to the new MetaMetrics controller @@ -20,13 +20,13 @@ const LEGACY_LOCAL_STORAGE_KEYS = [ export default { version, async migrate(originalVersionedData) { - const versionedData = cloneDeep(originalVersionedData) - versionedData.meta.version = version + const versionedData = cloneDeep(originalVersionedData); + versionedData.meta.version = version; LEGACY_LOCAL_STORAGE_KEYS.forEach((key) => window.localStorage.removeItem(key), - ) + ); - return versionedData + return versionedData; }, -} +}; diff --git a/app/scripts/migrations/051.js b/app/scripts/migrations/051.js index 4c024458d..c429fa635 100644 --- a/app/scripts/migrations/051.js +++ b/app/scripts/migrations/051.js @@ -1,7 +1,7 @@ -import { cloneDeep } from 'lodash' -import { NETWORK_TYPE_TO_ID_MAP } from '../../../shared/constants/network' +import { cloneDeep } from 'lodash'; +import { NETWORK_TYPE_TO_ID_MAP } from '../../../shared/constants/network'; -const version = 51 +const version = 51; /** * Set the chainId in the Network Controller provider data for all infura networks @@ -9,20 +9,20 @@ const version = 51 export default { version, async migrate(originalVersionedData) { - const versionedData = cloneDeep(originalVersionedData) - versionedData.meta.version = version - const state = versionedData.data - versionedData.data = transformState(state) - return versionedData + const versionedData = cloneDeep(originalVersionedData); + versionedData.meta.version = version; + const state = versionedData.data; + versionedData.data = transformState(state); + return versionedData; }, -} +}; function transformState(state) { - const { chainId, type } = state?.NetworkController?.provider || {} - const enumChainId = NETWORK_TYPE_TO_ID_MAP[type]?.chainId + const { chainId, type } = state?.NetworkController?.provider || {}; + const enumChainId = NETWORK_TYPE_TO_ID_MAP[type]?.chainId; if (enumChainId && chainId !== enumChainId) { - state.NetworkController.provider.chainId = enumChainId + state.NetworkController.provider.chainId = enumChainId; } - return state + return state; } diff --git a/app/scripts/migrations/fail-tx.js b/app/scripts/migrations/fail-tx.js index 240d11036..0fedb6052 100644 --- a/app/scripts/migrations/fail-tx.js +++ b/app/scripts/migrations/fail-tx.js @@ -1,40 +1,40 @@ -import { cloneDeep } from 'lodash' -import { TRANSACTION_STATUSES } from '../../../shared/constants/transaction' +import { cloneDeep } from 'lodash'; +import { TRANSACTION_STATUSES } from '../../../shared/constants/transaction'; export default function failTxsThat(version, reason, condition) { return function (originalVersionedData) { - const versionedData = cloneDeep(originalVersionedData) - versionedData.meta.version = version + const versionedData = cloneDeep(originalVersionedData); + versionedData.meta.version = version; try { - const state = versionedData.data - const newState = transformState(state, condition, reason) - versionedData.data = newState + const state = versionedData.data; + const newState = transformState(state, condition, reason); + versionedData.data = newState; } catch (err) { - console.warn(`MetaMask Migration #${version}${err.stack}`) + console.warn(`MetaMask Migration #${version}${err.stack}`); } - return Promise.resolve(versionedData) - } + return Promise.resolve(versionedData); + }; } function transformState(state, condition, reason) { - const newState = state - const { TransactionController } = newState + const newState = state; + const { TransactionController } = newState; if (TransactionController && TransactionController.transactions) { - const { transactions } = TransactionController + const { transactions } = TransactionController; newState.TransactionController.transactions = transactions.map((txMeta) => { if (!condition(txMeta)) { - return txMeta + return txMeta; } - txMeta.status = TRANSACTION_STATUSES.FAILED + txMeta.status = TRANSACTION_STATUSES.FAILED; txMeta.err = { message: reason, note: `Tx automatically failed by migration because ${reason}`, - } + }; - return txMeta - }) + return txMeta; + }); } - return newState + return newState; } diff --git a/app/scripts/migrations/index.js b/app/scripts/migrations/index.js index 1701fd19c..5fe85ae74 100644 --- a/app/scripts/migrations/index.js +++ b/app/scripts/migrations/index.js @@ -56,6 +56,6 @@ const migrations = [ require('./049').default, require('./050').default, require('./051').default, -] +]; -export default migrations +export default migrations; diff --git a/app/scripts/migrations/template.js b/app/scripts/migrations/template.js index b582c5a00..b3f050dfc 100644 --- a/app/scripts/migrations/template.js +++ b/app/scripts/migrations/template.js @@ -5,25 +5,25 @@ description of migration and what it does */ -import { cloneDeep } from 'lodash' +import { cloneDeep } from 'lodash'; -const version = 0 +const version = 0; export default { version, async migrate(originalVersionedData) { - const versionedData = cloneDeep(originalVersionedData) - versionedData.meta.version = version - const state = versionedData.data - const newState = transformState(state) - versionedData.data = newState - return versionedData + const versionedData = cloneDeep(originalVersionedData); + versionedData.meta.version = version; + const state = versionedData.data; + const newState = transformState(state); + versionedData.data = newState; + return versionedData; }, -} +}; function transformState(state) { - const newState = state + const newState = state; // transform state here - return newState + return newState; } diff --git a/app/scripts/phishing-detect.js b/app/scripts/phishing-detect.js index 300fe70fa..9ade869f0 100644 --- a/app/scripts/phishing-detect.js +++ b/app/scripts/phishing-detect.js @@ -1,57 +1,57 @@ -import querystring from 'querystring' -import { EventEmitter } from 'events' -import dnode from 'dnode' -import PortStream from 'extension-port-stream' -import extension from 'extensionizer' -import { setupMultiplex } from './lib/stream-utils' -import { getEnvironmentType } from './lib/util' -import ExtensionPlatform from './platforms/extension' +import querystring from 'querystring'; +import { EventEmitter } from 'events'; +import dnode from 'dnode'; +import PortStream from 'extension-port-stream'; +import extension from 'extensionizer'; +import { setupMultiplex } from './lib/stream-utils'; +import { getEnvironmentType } from './lib/util'; +import ExtensionPlatform from './platforms/extension'; -document.addEventListener('DOMContentLoaded', start) +document.addEventListener('DOMContentLoaded', start); function start() { - const hash = window.location.hash.substring(1) - const suspect = querystring.parse(hash) + const hash = window.location.hash.substring(1); + const suspect = querystring.parse(hash); - document.getElementById('csdbLink').href = `https://cryptoscamdb.org/search` + document.getElementById('csdbLink').href = `https://cryptoscamdb.org/search`; - global.platform = new ExtensionPlatform() + global.platform = new ExtensionPlatform(); const extensionPort = extension.runtime.connect({ name: getEnvironmentType(), - }) - const connectionStream = new PortStream(extensionPort) - const mx = setupMultiplex(connectionStream) + }); + const connectionStream = new PortStream(extensionPort); + const mx = setupMultiplex(connectionStream); setupControllerConnection( mx.createStream('controller'), (err, metaMaskController) => { if (err) { - return + return; } - const continueLink = document.getElementById('unsafe-continue') + const continueLink = document.getElementById('unsafe-continue'); continueLink.addEventListener('click', () => { - metaMaskController.safelistPhishingDomain(suspect.hostname) - window.location.href = suspect.href - }) + metaMaskController.safelistPhishingDomain(suspect.hostname); + window.location.href = suspect.href; + }); }, - ) + ); } function setupControllerConnection(connectionStream, cb) { - const eventEmitter = new EventEmitter() + const eventEmitter = new EventEmitter(); // the "weak: false" option is for nodejs only (eg unit tests) // it is a workaround for node v12 support const metaMaskControllerDnode = dnode( { sendUpdate(state) { - eventEmitter.emit('update', state) + eventEmitter.emit('update', state); }, }, { weak: false }, - ) - connectionStream.pipe(metaMaskControllerDnode).pipe(connectionStream) + ); + connectionStream.pipe(metaMaskControllerDnode).pipe(connectionStream); metaMaskControllerDnode.once('remote', (backgroundConnection) => cb(null, backgroundConnection), - ) + ); } diff --git a/app/scripts/platforms/extension.js b/app/scripts/platforms/extension.js index 88117700d..8c43a343b 100644 --- a/app/scripts/platforms/extension.js +++ b/app/scripts/platforms/extension.js @@ -1,117 +1,117 @@ -import extension from 'extensionizer' -import { createExplorerLink as explorerLink } from '@metamask/etherscan-link' -import { getEnvironmentType, checkForError } from '../lib/util' -import { ENVIRONMENT_TYPE_BACKGROUND } from '../../../shared/constants/app' -import { TRANSACTION_STATUSES } from '../../../shared/constants/transaction' +import extension from 'extensionizer'; +import { createExplorerLink as explorerLink } from '@metamask/etherscan-link'; +import { getEnvironmentType, checkForError } from '../lib/util'; +import { ENVIRONMENT_TYPE_BACKGROUND } from '../../../shared/constants/app'; +import { TRANSACTION_STATUSES } from '../../../shared/constants/transaction'; export default class ExtensionPlatform { // // Public // reload() { - extension.runtime.reload() + extension.runtime.reload(); } openTab(options) { return new Promise((resolve, reject) => { extension.tabs.create(options, (newTab) => { - const error = checkForError() + const error = checkForError(); if (error) { - return reject(error) + return reject(error); } - return resolve(newTab) - }) - }) + return resolve(newTab); + }); + }); } openWindow(options) { return new Promise((resolve, reject) => { extension.windows.create(options, (newWindow) => { - const error = checkForError() + const error = checkForError(); if (error) { - return reject(error) + return reject(error); } - return resolve(newWindow) - }) - }) + return resolve(newWindow); + }); + }); } focusWindow(windowId) { return new Promise((resolve, reject) => { extension.windows.update(windowId, { focused: true }, () => { - const error = checkForError() + const error = checkForError(); if (error) { - return reject(error) + return reject(error); } - return resolve() - }) - }) + return resolve(); + }); + }); } updateWindowPosition(windowId, left, top) { return new Promise((resolve, reject) => { extension.windows.update(windowId, { left, top }, () => { - const error = checkForError() + const error = checkForError(); if (error) { - return reject(error) + return reject(error); } - return resolve() - }) - }) + return resolve(); + }); + }); } getLastFocusedWindow() { return new Promise((resolve, reject) => { extension.windows.getLastFocused((windowObject) => { - const error = checkForError() + const error = checkForError(); if (error) { - return reject(error) + return reject(error); } - return resolve(windowObject) - }) - }) + return resolve(windowObject); + }); + }); } closeCurrentWindow() { return extension.windows.getCurrent((windowDetails) => { - return extension.windows.remove(windowDetails.id) - }) + return extension.windows.remove(windowDetails.id); + }); } getVersion() { - return extension.runtime.getManifest().version + return extension.runtime.getManifest().version; } openExtensionInBrowser(route = null, queryString = null) { - let extensionURL = extension.runtime.getURL('home.html') + let extensionURL = extension.runtime.getURL('home.html'); if (queryString) { - extensionURL += `?${queryString}` + extensionURL += `?${queryString}`; } if (route) { - extensionURL += `#${route}` + extensionURL += `#${route}`; } - this.openTab({ url: extensionURL }) + this.openTab({ url: extensionURL }); if (getEnvironmentType() !== ENVIRONMENT_TYPE_BACKGROUND) { - window.close() + window.close(); } } getPlatformInfo(cb) { try { extension.runtime.getPlatformInfo((platform) => { - cb(null, platform) - }) + cb(null, platform); + }); } catch (e) { - cb(e) + cb(e); // eslint-disable-next-line no-useless-return - return + return; } } showTransactionNotification(txMeta) { - const { status, txReceipt: { status: receiptStatus } = {} } = txMeta + const { status, txReceipt: { status: receiptStatus } = {} } = txMeta; if (status === TRANSACTION_STATUSES.CONFIRMED) { // There was an on-chain failure @@ -120,93 +120,93 @@ export default class ExtensionPlatform { txMeta, 'Transaction encountered an error.', ) - : this._showConfirmedTransaction(txMeta) + : this._showConfirmedTransaction(txMeta); } else if (status === TRANSACTION_STATUSES.FAILED) { - this._showFailedTransaction(txMeta) + this._showFailedTransaction(txMeta); } } getAllWindows() { return new Promise((resolve, reject) => { extension.windows.getAll((windows) => { - const error = checkForError() + const error = checkForError(); if (error) { - return reject(error) + return reject(error); } - return resolve(windows) - }) - }) + return resolve(windows); + }); + }); } getActiveTabs() { return new Promise((resolve, reject) => { extension.tabs.query({ active: true }, (tabs) => { - const error = checkForError() + const error = checkForError(); if (error) { - return reject(error) + return reject(error); } - return resolve(tabs) - }) - }) + return resolve(tabs); + }); + }); } currentTab() { return new Promise((resolve, reject) => { extension.tabs.getCurrent((tab) => { - const err = checkForError() + const err = checkForError(); if (err) { - reject(err) + reject(err); } else { - resolve(tab) + resolve(tab); } - }) - }) + }); + }); } switchToTab(tabId) { return new Promise((resolve, reject) => { extension.tabs.update(tabId, { highlighted: true }, (tab) => { - const err = checkForError() + const err = checkForError(); if (err) { - reject(err) + reject(err); } else { - resolve(tab) + resolve(tab); } - }) - }) + }); + }); } closeTab(tabId) { return new Promise((resolve, reject) => { extension.tabs.remove(tabId, () => { - const err = checkForError() + const err = checkForError(); if (err) { - reject(err) + reject(err); } else { - resolve() + resolve(); } - }) - }) + }); + }); } _showConfirmedTransaction(txMeta) { - this._subscribeToNotificationClicked() + this._subscribeToNotificationClicked(); - const url = explorerLink(txMeta.hash, txMeta.metamaskNetworkId) - const nonce = parseInt(txMeta.txParams.nonce, 16) + const url = explorerLink(txMeta.hash, txMeta.metamaskNetworkId); + const nonce = parseInt(txMeta.txParams.nonce, 16); - const title = 'Confirmed transaction' - const message = `Transaction ${nonce} confirmed! View on Etherscan` - this._showNotification(title, message, url) + const title = 'Confirmed transaction'; + const message = `Transaction ${nonce} confirmed! View on Etherscan`; + this._showNotification(title, message, url); } _showFailedTransaction(txMeta, errorMessage) { - const nonce = parseInt(txMeta.txParams.nonce, 16) - const title = 'Failed transaction' + const nonce = parseInt(txMeta.txParams.nonce, 16); + const title = 'Failed transaction'; const message = `Transaction ${nonce} failed! ${ errorMessage || txMeta.err.message - }` - this._showNotification(title, message) + }`; + this._showNotification(title, message); } _showNotification(title, message, url) { @@ -215,18 +215,18 @@ export default class ExtensionPlatform { title, iconUrl: extension.extension.getURL('../../images/icon-64.png'), message, - }) + }); } _subscribeToNotificationClicked() { if (!extension.notifications.onClicked.hasListener(this._viewOnEtherscan)) { - extension.notifications.onClicked.addListener(this._viewOnEtherscan) + extension.notifications.onClicked.addListener(this._viewOnEtherscan); } } _viewOnEtherscan(txId) { if (txId.startsWith('https://')) { - extension.tabs.create({ url: txId }) + extension.tabs.create({ url: txId }); } } } diff --git a/app/scripts/runLockdown.js b/app/scripts/runLockdown.js index 210005967..8dc1b0154 100644 --- a/app/scripts/runLockdown.js +++ b/app/scripts/runLockdown.js @@ -6,14 +6,14 @@ try { errorTaming: 'unsafe', mathTaming: 'unsafe', dateTaming: 'unsafe', - }) + }); } catch (error) { // If the `lockdown` call throws an exception, it interferes with the // contentscript injection on some versions of Firefox. The error is // caught and logged here so that the contentscript still gets injected. // This affects Firefox v56 and Waterfox Classic - console.error('Lockdown failed:', error) + console.error('Lockdown failed:', error); if (window.sentry && window.sentry.captureException) { - window.sentry.captureException(error) + window.sentry.captureException(error); } } diff --git a/app/scripts/ui.js b/app/scripts/ui.js index a67eb3e6a..0d048191c 100644 --- a/app/scripts/ui.js +++ b/app/scripts/ui.js @@ -1,64 +1,64 @@ // polyfills -import 'abortcontroller-polyfill/dist/polyfill-patch-fetch' -import '@formatjs/intl-relativetimeformat/polyfill' +import 'abortcontroller-polyfill/dist/polyfill-patch-fetch'; +import '@formatjs/intl-relativetimeformat/polyfill'; -import { EventEmitter } from 'events' -import PortStream from 'extension-port-stream' -import extension from 'extensionizer' +import { EventEmitter } from 'events'; +import PortStream from 'extension-port-stream'; +import extension from 'extensionizer'; -import Dnode from 'dnode' -import Eth from 'ethjs' -import EthQuery from 'eth-query' -import StreamProvider from 'web3-stream-provider' -import log from 'loglevel' -import launchMetaMaskUi from '../../ui' +import Dnode from 'dnode'; +import Eth from 'ethjs'; +import EthQuery from 'eth-query'; +import StreamProvider from 'web3-stream-provider'; +import log from 'loglevel'; +import launchMetaMaskUi from '../../ui'; import { ENVIRONMENT_TYPE_FULLSCREEN, ENVIRONMENT_TYPE_POPUP, -} from '../../shared/constants/app' -import ExtensionPlatform from './platforms/extension' -import { setupMultiplex } from './lib/stream-utils' -import { getEnvironmentType } from './lib/util' +} from '../../shared/constants/app'; +import ExtensionPlatform from './platforms/extension'; +import { setupMultiplex } from './lib/stream-utils'; +import { getEnvironmentType } from './lib/util'; -start().catch(log.error) +start().catch(log.error); async function start() { // create platform global - global.platform = new ExtensionPlatform() + global.platform = new ExtensionPlatform(); // identify window type (popup, notification) - const windowType = getEnvironmentType() + const windowType = getEnvironmentType(); // setup stream to background - const extensionPort = extension.runtime.connect({ name: windowType }) - const connectionStream = new PortStream(extensionPort) + const extensionPort = extension.runtime.connect({ name: windowType }); + const connectionStream = new PortStream(extensionPort); - const activeTab = await queryCurrentActiveTab(windowType) - initializeUiWithTab(activeTab) + const activeTab = await queryCurrentActiveTab(windowType); + initializeUiWithTab(activeTab); function displayCriticalError(container, err) { container.innerHTML = - '
The MetaMask app failed to load: please open and close MetaMask again to restart.
' - container.style.height = '80px' - log.error(err.stack) - throw err + '
The MetaMask app failed to load: please open and close MetaMask again to restart.
'; + container.style.height = '80px'; + log.error(err.stack); + throw err; } function initializeUiWithTab(tab) { - const container = document.getElementById('app-content') + const container = document.getElementById('app-content'); initializeUi(tab, container, connectionStream, (err, store) => { if (err) { - displayCriticalError(container, err) - return + displayCriticalError(container, err); + return; } - const state = store.getState() - const { metamask: { completedOnboarding } = {} } = state + const state = store.getState(); + const { metamask: { completedOnboarding } = {} } = state; if (!completedOnboarding && windowType !== ENVIRONMENT_TYPE_FULLSCREEN) { - global.platform.openExtensionInBrowser() + global.platform.openExtensionInBrowser(); } - }) + }); } } @@ -67,30 +67,30 @@ async function queryCurrentActiveTab(windowType) { // At the time of writing we only have the `activeTab` permission which means // that this query will only succeed in the popup context (i.e. after a "browserAction") if (windowType !== ENVIRONMENT_TYPE_POPUP) { - resolve({}) - return + resolve({}); + return; } extension.tabs.query({ active: true, currentWindow: true }, (tabs) => { - const [activeTab] = tabs - const { id, title, url } = activeTab - const { origin, protocol } = url ? new URL(url) : {} + const [activeTab] = tabs; + const { id, title, url } = activeTab; + const { origin, protocol } = url ? new URL(url) : {}; if (!origin || origin === 'null') { - resolve({}) - return + resolve({}); + return; } - resolve({ id, title, origin, protocol, url }) - }) - }) + resolve({ id, title, origin, protocol, url }); + }); + }); } function initializeUi(activeTab, container, connectionStream, cb) { connectToAccountManager(connectionStream, (err, backgroundConnection) => { if (err) { - cb(err) - return + cb(err); + return; } launchMetaMaskUi( @@ -100,8 +100,8 @@ function initializeUi(activeTab, container, connectionStream, cb) { backgroundConnection, }, cb, - ) - }) + ); + }); } /** @@ -111,9 +111,9 @@ function initializeUi(activeTab, container, connectionStream, cb) { * @param {Function} cb - Called when controller connection is established */ function connectToAccountManager(connectionStream, cb) { - const mx = setupMultiplex(connectionStream) - setupControllerConnection(mx.createStream('controller'), cb) - setupWeb3Connection(mx.createStream('provider')) + const mx = setupMultiplex(connectionStream); + setupControllerConnection(mx.createStream('controller'), cb); + setupWeb3Connection(mx.createStream('provider')); } /** @@ -122,13 +122,13 @@ function connectToAccountManager(connectionStream, cb) { * @param {PortDuplexStream} connectionStream - PortStream instance establishing a background connection */ function setupWeb3Connection(connectionStream) { - const providerStream = new StreamProvider() - providerStream.pipe(connectionStream).pipe(providerStream) - connectionStream.on('error', console.error.bind(console)) - providerStream.on('error', console.error.bind(console)) - global.ethereumProvider = providerStream - global.ethQuery = new EthQuery(providerStream) - global.eth = new Eth(providerStream) + const providerStream = new StreamProvider(); + providerStream.pipe(connectionStream).pipe(providerStream); + connectionStream.on('error', console.error.bind(console)); + providerStream.on('error', console.error.bind(console)); + global.ethereumProvider = providerStream; + global.ethQuery = new EthQuery(providerStream); + global.eth = new Eth(providerStream); } /** @@ -138,20 +138,20 @@ function setupWeb3Connection(connectionStream) { * @param {Function} cb - Called when the remote account manager connection is established */ function setupControllerConnection(connectionStream, cb) { - const eventEmitter = new EventEmitter() + const eventEmitter = new EventEmitter(); // the "weak: false" option is for nodejs only (eg unit tests) // it is a workaround for node v12 support const backgroundDnode = Dnode( { sendUpdate(state) { - eventEmitter.emit('update', state) + eventEmitter.emit('update', state); }, }, { weak: false }, - ) - connectionStream.pipe(backgroundDnode).pipe(connectionStream) + ); + connectionStream.pipe(backgroundDnode).pipe(connectionStream); backgroundDnode.once('remote', function (backgroundConnection) { - backgroundConnection.on = eventEmitter.on.bind(eventEmitter) - cb(null, backgroundConnection) - }) + backgroundConnection.on = eventEmitter.on.bind(eventEmitter); + cb(null, backgroundConnection); + }); } diff --git a/babel.config.js b/babel.config.js index d95fa7e3f..6c98e6df4 100644 --- a/babel.config.js +++ b/babel.config.js @@ -1,5 +1,5 @@ module.exports = function (api) { - api.cache(false) + api.cache(false); return { presets: [ [ @@ -19,5 +19,5 @@ module.exports = function (api) { '@babel/plugin-proposal-optional-chaining', '@babel/plugin-proposal-nullish-coalescing-operator', ], - } -} + }; +}; diff --git a/development/announcer.js b/development/announcer.js index e6927cb8b..f0c42c07a 100644 --- a/development/announcer.js +++ b/development/announcer.js @@ -1,13 +1,13 @@ -const fs = require('fs') -const path = require('path') -const { version } = require('../app/manifest/_base.json') +const fs = require('fs'); +const path = require('path'); +const { version } = require('../app/manifest/_base.json'); const changelog = fs.readFileSync( path.join(__dirname, '..', 'CHANGELOG.md'), 'utf8', -) +); -const log = changelog.split(version)[1].split('##')[0].trim() -const msg = `*MetaMask ${version}* now published! It should auto-update soon!\n${log}` +const log = changelog.split(version)[1].split('##')[0].trim(); +const msg = `*MetaMask ${version}* now published! It should auto-update soon!\n${log}`; -console.log(msg) +console.log(msg); diff --git a/development/build/display.js b/development/build/display.js index 153f47189..6d16cc7e7 100644 --- a/development/build/display.js +++ b/development/build/display.js @@ -1,7 +1,7 @@ -const randomColor = require('randomcolor') -const chalk = require('chalk') +const randomColor = require('randomcolor'); +const chalk = require('chalk'); -module.exports = { setupTaskDisplay, displayChart } +module.exports = { setupTaskDisplay, displayChart }; const SYMBOLS = { Empty: '', @@ -16,135 +16,145 @@ const SYMBOLS = { Eighth: '▏', RightHalf: '▐', RightEighth: '▕', -} +}; function setupTaskDisplay(taskEvents) { - const taskData = [] + const taskData = []; taskEvents.on('start', ([name]) => { - console.log(`Starting '${name}'...`) - }) + console.log(`Starting '${name}'...`); + }); taskEvents.on('end', ([name, start, end]) => { - taskData.push([name, start, end]) - console.log(`Finished '${name}'`) - }) + taskData.push([name, start, end]); + console.log(`Finished '${name}'`); + }); taskEvents.on('complete', () => { - displayChart(taskData) - }) + displayChart(taskData); + }); } function displayChart(data) { // sort tasks by start time - data.sort((a, b) => a[1] - b[1]) + data.sort((a, b) => a[1] - b[1]); // get bounds - const first = Math.min(...data.map((entry) => entry[1])) - const last = Math.max(...data.map((entry) => entry[2])) + const first = Math.min(...data.map((entry) => entry[1])); + const last = Math.max(...data.map((entry) => entry[2])); // get colors - const colors = randomColor({ count: data.length }) + const colors = randomColor({ count: data.length }); // some heading before the bars - console.log(`\nbuild completed. task timeline:`) + console.log(`\nbuild completed. task timeline:`); // build bars for bounds data.forEach((entry, index) => { - const [label, start, end] = entry + const [label, start, end] = entry; const [start2, end2] = [start, end].map((value) => adjust(value, first, last, 40), - ) - const barString = barBuilder(start2, end2) - const color = colors[index] - const coloredBarString = colorize(color, barString) - const duration = ((end - start) / 1e3).toFixed(1) - console.log(coloredBarString, `${label} ${duration}s`) - }) + ); + const barString = barBuilder(start2, end2); + const color = colors[index]; + const coloredBarString = colorize(color, barString); + const duration = ((end - start) / 1e3).toFixed(1); + console.log(coloredBarString, `${label} ${duration}s`); + }); } function colorize(color, string) { const colorizer = - typeof chalk[color] === 'function' ? chalk[color] : chalk.hex(color) - return colorizer(string) + typeof chalk[color] === 'function' ? chalk[color] : chalk.hex(color); + return colorizer(string); } // scale number within bounds function adjust(value, first, last, size) { - const length = last - first - const result = ((value - first) / length) * size - return result + const length = last - first; + const result = ((value - first) / length) * size; + return result; } // draw bars function barBuilder(start, end) { - const [spaceInt, spaceRest] = splitNumber(start) - const barBodyLength = end - spaceInt - let [barInt, barRest] = splitNumber(barBodyLength) + const [spaceInt, spaceRest] = splitNumber(start); + const barBodyLength = end - spaceInt; + let [barInt, barRest] = splitNumber(barBodyLength); // We are handling zero value as a special case // to print at least something on the screen if (barInt === 0 && barRest === 0) { - barInt = 0 - barRest = 0.001 + barInt = 0; + barRest = 0.001; } - const spaceFull = SYMBOLS.Space.repeat(spaceInt) - const spacePartial = getSymbolNormalRight(spaceRest) - const barFull = SYMBOLS.Full.repeat(barInt) - const barPartial = getSymbolNormal(barRest) + const spaceFull = SYMBOLS.Space.repeat(spaceInt); + const spacePartial = getSymbolNormalRight(spaceRest); + const barFull = SYMBOLS.Full.repeat(barInt); + const barPartial = getSymbolNormal(barRest); - return `${spaceFull}${spacePartial}${barFull}${barPartial}` + return `${spaceFull}${spacePartial}${barFull}${barPartial}`; } // get integer and remainder function splitNumber(value = 0) { - const [int, rest = '0'] = value.toString().split('.') - const int2 = parseInt(int, 10) - const rest2 = parseInt(rest, 10) / Math.pow(10, rest.length) - return [int2, rest2] + const [int, rest = '0'] = value.toString().split('.'); + const int2 = parseInt(int, 10); + const rest2 = parseInt(rest, 10) / Math.pow(10, rest.length); + return [int2, rest2]; } // get partial block char for value (left-adjusted) function getSymbolNormal(value) { // round to closest supported value - const possibleValues = [0, 1 / 8, 1 / 4, 3 / 8, 1 / 2, 5 / 8, 3 / 4, 7 / 8, 1] + const possibleValues = [ + 0, + 1 / 8, + 1 / 4, + 3 / 8, + 1 / 2, + 5 / 8, + 3 / 4, + 7 / 8, + 1, + ]; const rounded = possibleValues.reduce((prev, curr) => { - return Math.abs(curr - value) < Math.abs(prev - value) ? curr : prev - }) + return Math.abs(curr - value) < Math.abs(prev - value) ? curr : prev; + }); if (rounded === 0) { - return SYMBOLS.Empty + return SYMBOLS.Empty; } else if (rounded === 1 / 8) { - return SYMBOLS.Eighth + return SYMBOLS.Eighth; } else if (rounded === 1 / 4) { - return SYMBOLS.Quarter + return SYMBOLS.Quarter; } else if (rounded === 3 / 8) { - return SYMBOLS.ThreeEighths + return SYMBOLS.ThreeEighths; } else if (rounded === 1 / 2) { - return SYMBOLS.Half + return SYMBOLS.Half; } else if (rounded === 5 / 8) { - return SYMBOLS.FiveEighths + return SYMBOLS.FiveEighths; } else if (rounded === 3 / 4) { - return SYMBOLS.ThreeQuarters + return SYMBOLS.ThreeQuarters; } else if (rounded === 7 / 8) { - return SYMBOLS.SevenEighths + return SYMBOLS.SevenEighths; } - return SYMBOLS.Full + return SYMBOLS.Full; } // get partial block char for value (right-adjusted) function getSymbolNormalRight(value) { // round to closest supported value (not much :/) - const possibleValues = [0, 1 / 2, 7 / 8, 1] + const possibleValues = [0, 1 / 2, 7 / 8, 1]; const rounded = possibleValues.reduce((prev, curr) => { - return Math.abs(curr - value) < Math.abs(prev - value) ? curr : prev - }) + return Math.abs(curr - value) < Math.abs(prev - value) ? curr : prev; + }); if (rounded === 0) { - return SYMBOLS.Full + return SYMBOLS.Full; } else if (rounded === 1 / 2) { - return SYMBOLS.RightHalf + return SYMBOLS.RightHalf; } else if (rounded === 7 / 8) { - return SYMBOLS.RightEighth + return SYMBOLS.RightEighth; } else if (rounded === 1) { - return SYMBOLS.Space + return SYMBOLS.Space; } - throw new Error('getSymbolNormalRight got unexpected result') + throw new Error('getSymbolNormalRight got unexpected result'); } diff --git a/development/build/etc.js b/development/build/etc.js index 374b9a616..49070887f 100644 --- a/development/build/etc.js +++ b/development/build/etc.js @@ -1,27 +1,27 @@ -const { promises: fs } = require('fs') -const gulp = require('gulp') -const gulpZip = require('gulp-zip') -const del = require('del') -const pify = require('pify') -const pump = pify(require('pump')) -const baseManifest = require('../../app/manifest/_base.json') -const { createTask, composeParallel } = require('./task') +const { promises: fs } = require('fs'); +const gulp = require('gulp'); +const gulpZip = require('gulp-zip'); +const del = require('del'); +const pify = require('pify'); +const pump = pify(require('pump')); +const baseManifest = require('../../app/manifest/_base.json'); +const { createTask, composeParallel } = require('./task'); -module.exports = createEtcTasks +module.exports = createEtcTasks; function createEtcTasks({ browserPlatforms, livereload }) { const clean = createTask('clean', async function clean() { - await del(['./dist/*']) + await del(['./dist/*']); await Promise.all( browserPlatforms.map(async (platform) => { - await fs.mkdir(`./dist/${platform}`, { recursive: true }) + await fs.mkdir(`./dist/${platform}`, { recursive: true }); }), - ) - }) + ); + }); const reload = createTask('reload', function devReload() { - livereload.listen({ port: 35729 }) - }) + livereload.listen({ port: 35729 }); + }); // zip tasks for distribution const zip = createTask( @@ -29,9 +29,9 @@ function createEtcTasks({ browserPlatforms, livereload }) { composeParallel( ...browserPlatforms.map((platform) => createZipTask(platform)), ), - ) + ); - return { clean, reload, zip } + return { clean, reload, zip }; } function createZipTask(target) { @@ -40,6 +40,6 @@ function createZipTask(target) { gulp.src(`dist/${target}/**`), gulpZip(`metamask-${target}-${baseManifest.version}.zip`), gulp.dest('builds'), - ) - } + ); + }; } diff --git a/development/build/index.js b/development/build/index.js index 7c5aeb6a2..c6ce884f5 100755 --- a/development/build/index.js +++ b/development/build/index.js @@ -3,33 +3,33 @@ // // run any task with "yarn build ${taskName}" // -const livereload = require('gulp-livereload') +const livereload = require('gulp-livereload'); const { createTask, composeSeries, composeParallel, detectAndRunEntryTask, -} = require('./task') -const createManifestTasks = require('./manifest') -const createScriptTasks = require('./scripts') -const createStyleTasks = require('./styles') -const createStaticAssetTasks = require('./static') -const createEtcTasks = require('./etc') +} = require('./task'); +const createManifestTasks = require('./manifest'); +const createScriptTasks = require('./scripts'); +const createStyleTasks = require('./styles'); +const createStaticAssetTasks = require('./static'); +const createEtcTasks = require('./etc'); -const browserPlatforms = ['firefox', 'chrome', 'brave', 'opera'] +const browserPlatforms = ['firefox', 'chrome', 'brave', 'opera']; -defineAllTasks() -detectAndRunEntryTask() +defineAllTasks(); +detectAndRunEntryTask(); function defineAllTasks() { - const staticTasks = createStaticAssetTasks({ livereload, browserPlatforms }) - const manifestTasks = createManifestTasks({ browserPlatforms }) - const styleTasks = createStyleTasks({ livereload }) - const scriptTasks = createScriptTasks({ livereload, browserPlatforms }) + const staticTasks = createStaticAssetTasks({ livereload, browserPlatforms }); + const manifestTasks = createManifestTasks({ browserPlatforms }); + const styleTasks = createStyleTasks({ livereload }); + const scriptTasks = createScriptTasks({ livereload, browserPlatforms }); const { clean, reload, zip } = createEtcTasks({ livereload, browserPlatforms, - }) + }); // build for development (livereload) createTask( @@ -44,7 +44,7 @@ function defineAllTasks() { reload, ), ), - ) + ); // build for test development (livereload) createTask( @@ -59,7 +59,7 @@ function defineAllTasks() { reload, ), ), - ) + ); // build for prod release createTask( @@ -70,7 +70,7 @@ function defineAllTasks() { composeParallel(scriptTasks.prod, staticTasks.prod, manifestTasks.prod), zip, ), - ) + ); // build for CI testing createTask( @@ -81,8 +81,8 @@ function defineAllTasks() { composeParallel(scriptTasks.test, staticTasks.prod, manifestTasks.test), zip, ), - ) + ); // special build for minimal CI testing - createTask('styles', styleTasks.prod) + createTask('styles', styleTasks.prod); } diff --git a/development/build/manifest.js b/development/build/manifest.js index 7750205b1..0dc8880b1 100644 --- a/development/build/manifest.js +++ b/development/build/manifest.js @@ -1,16 +1,16 @@ -const { promises: fs } = require('fs') -const path = require('path') -const { merge, cloneDeep } = require('lodash') +const { promises: fs } = require('fs'); +const path = require('path'); +const { merge, cloneDeep } = require('lodash'); -const baseManifest = require('../../app/manifest/_base.json') +const baseManifest = require('../../app/manifest/_base.json'); -const { createTask, composeSeries } = require('./task') +const { createTask, composeSeries } = require('./task'); -module.exports = createManifestTasks +module.exports = createManifestTasks; const scriptsToExcludeFromBackgroundDevBuild = { 'bg-libs.js': true, -} +}; function createManifestTasks({ browserPlatforms }) { // merge base manifest with per-platform manifests @@ -26,44 +26,44 @@ function createManifestTasks({ browserPlatforms }) { 'manifest', `${platform}.json`, ), - ) - const result = merge(cloneDeep(baseManifest), platformModifications) - const dir = path.join('.', 'dist', platform) - await fs.mkdir(dir, { recursive: true }) - await writeJson(result, path.join(dir, 'manifest.json')) + ); + const result = merge(cloneDeep(baseManifest), platformModifications); + const dir = path.join('.', 'dist', platform); + await fs.mkdir(dir, { recursive: true }); + await writeJson(result, path.join(dir, 'manifest.json')); }), - ) - } + ); + }; // dev: remove bg-libs, add chromereload, add perms const envDev = createTaskForModifyManifestForEnvironment((manifest) => { const scripts = manifest.background.scripts.filter( (scriptName) => !scriptsToExcludeFromBackgroundDevBuild[scriptName], - ) - scripts.push('chromereload.js') + ); + scripts.push('chromereload.js'); manifest.background = { ...manifest.background, scripts, - } - manifest.permissions = [...manifest.permissions, 'webRequestBlocking'] - }) + }; + manifest.permissions = [...manifest.permissions, 'webRequestBlocking']; + }); // testDev: remove bg-libs, add perms const envTestDev = createTaskForModifyManifestForEnvironment((manifest) => { const scripts = manifest.background.scripts.filter( (scriptName) => !scriptsToExcludeFromBackgroundDevBuild[scriptName], - ) - scripts.push('chromereload.js') + ); + scripts.push('chromereload.js'); manifest.background = { ...manifest.background, scripts, - } + }; manifest.permissions = [ ...manifest.permissions, 'webRequestBlocking', 'http://localhost/*', - ] - }) + ]; + }); // test: add permissions const envTest = createTaskForModifyManifestForEnvironment((manifest) => { @@ -71,47 +71,52 @@ function createManifestTasks({ browserPlatforms }) { ...manifest.permissions, 'webRequestBlocking', 'http://localhost/*', - ] - }) + ]; + }); // high level manifest tasks - const dev = createTask('manifest:dev', composeSeries(prepPlatforms, envDev)) + const dev = createTask('manifest:dev', composeSeries(prepPlatforms, envDev)); const testDev = createTask( 'manifest:testDev', composeSeries(prepPlatforms, envTestDev), - ) + ); const test = createTask( 'manifest:test', composeSeries(prepPlatforms, envTest), - ) + ); - const prod = createTask('manifest:prod', prepPlatforms) + const prod = createTask('manifest:prod', prepPlatforms); - return { prod, dev, testDev, test } + return { prod, dev, testDev, test }; // helper for modifying each platform's manifest.json in place function createTaskForModifyManifestForEnvironment(transformFn) { return () => { return Promise.all( browserPlatforms.map(async (platform) => { - const manifestPath = path.join('.', 'dist', platform, 'manifest.json') - const manifest = await readJson(manifestPath) - transformFn(manifest) - await writeJson(manifest, manifestPath) + const manifestPath = path.join( + '.', + 'dist', + platform, + 'manifest.json', + ); + const manifest = await readJson(manifestPath); + transformFn(manifest); + await writeJson(manifest, manifestPath); }), - ) - } + ); + }; } } // helper for reading and deserializing json from fs async function readJson(file) { - return JSON.parse(await fs.readFile(file, 'utf8')) + return JSON.parse(await fs.readFile(file, 'utf8')); } // helper for serializing and writing json to fs async function writeJson(obj, file) { - return fs.writeFile(file, JSON.stringify(obj, null, 2)) + return fs.writeFile(file, JSON.stringify(obj, null, 2)); } diff --git a/development/build/scripts.js b/development/build/scripts.js index 8a54c9b33..57bbbcc6d 100644 --- a/development/build/scripts.js +++ b/development/build/scripts.js @@ -1,46 +1,46 @@ -const gulp = require('gulp') -const watch = require('gulp-watch') -const pify = require('pify') -const pump = pify(require('pump')) -const source = require('vinyl-source-stream') -const buffer = require('vinyl-buffer') -const log = require('fancy-log') -const { assign } = require('lodash') -const watchify = require('watchify') -const browserify = require('browserify') -const envify = require('loose-envify/custom') -const sourcemaps = require('gulp-sourcemaps') -const terser = require('gulp-terser-js') +const gulp = require('gulp'); +const watch = require('gulp-watch'); +const pify = require('pify'); +const pump = pify(require('pump')); +const source = require('vinyl-source-stream'); +const buffer = require('vinyl-buffer'); +const log = require('fancy-log'); +const { assign } = require('lodash'); +const watchify = require('watchify'); +const browserify = require('browserify'); +const envify = require('loose-envify/custom'); +const sourcemaps = require('gulp-sourcemaps'); +const terser = require('gulp-terser-js'); const conf = require('rc')('metamask', { INFURA_PROJECT_ID: process.env.INFURA_PROJECT_ID, SEGMENT_HOST: process.env.SEGMENT_HOST, SEGMENT_WRITE_KEY: process.env.SEGMENT_WRITE_KEY, SEGMENT_LEGACY_WRITE_KEY: process.env.SEGMENT_LEGACY_WRITE_KEY, -}) +}); -const baseManifest = require('../../app/manifest/_base.json') +const baseManifest = require('../../app/manifest/_base.json'); -const packageJSON = require('../../package.json') +const packageJSON = require('../../package.json'); const { createTask, composeParallel, composeSeries, runInChildProcess, -} = require('./task') +} = require('./task'); -module.exports = createScriptTasks +module.exports = createScriptTasks; const dependencies = Object.keys( (packageJSON && packageJSON.dependencies) || {}, -) -const materialUIDependencies = ['@material-ui/core'] -const reactDepenendencies = dependencies.filter((dep) => dep.match(/react/u)) +); +const materialUIDependencies = ['@material-ui/core']; +const reactDepenendencies = dependencies.filter((dep) => dep.match(/react/u)); const externalDependenciesMap = { background: ['3box'], ui: [...materialUIDependencies, ...reactDepenendencies], -} +}; function createScriptTasks({ browserPlatforms, livereload }) { // internal tasks @@ -62,24 +62,24 @@ function createScriptTasks({ browserPlatforms, livereload }) { }), // production prod: createTasksForBuildJsExtension({ taskPrefix: 'scripts:core:prod' }), - } + }; const deps = { background: createTasksForBuildJsDeps({ filename: 'bg-libs', key: 'background', }), ui: createTasksForBuildJsDeps({ filename: 'ui-libs', key: 'ui' }), - } + }; // high level tasks - const prod = composeParallel(deps.background, deps.ui, core.prod) + const prod = composeParallel(deps.background, deps.ui, core.prod); - const { dev, testDev } = core + const { dev, testDev } = core; - const test = composeParallel(deps.background, deps.ui, core.test) + const test = composeParallel(deps.background, deps.ui, core.test); - return { prod, dev, testDev, test } + return { prod, dev, testDev, test }; function createTasksForBuildJsDeps({ key, filename }) { return createTask( @@ -91,7 +91,7 @@ function createScriptTasks({ browserPlatforms, livereload }) { dependenciesToBundle: externalDependenciesMap[key], devMode: false, }), - ) + ); } function createTasksForBuildJsExtension({ taskPrefix, devMode, testing }) { @@ -100,7 +100,7 @@ function createScriptTasks({ browserPlatforms, livereload }) { 'ui', 'phishing-detect', 'initSentry', - ] + ]; const standardSubtasks = standardBundles.map((filename) => { return createTask( @@ -110,21 +110,21 @@ function createScriptTasks({ browserPlatforms, livereload }) { devMode, testing, }), - ) - }) + ); + }); // inpage must be built before contentscript // because inpage bundle result is included inside contentscript const contentscriptSubtask = createTask( `${taskPrefix}:contentscript`, createTaskForBuildJsExtensionContentscript({ devMode, testing }), - ) + ); // this can run whenever const disableConsoleSubtask = createTask( `${taskPrefix}:disable-console`, createTaskForBuildJsExtensionDisableConsole({ devMode }), - ) + ); // task for initiating livereload const initiateLiveReload = async () => { @@ -136,21 +136,21 @@ function createScriptTasks({ browserPlatforms, livereload }) { // - build tasks never "complete" when run with livereload + child process setTimeout(() => { watch('./dist/*/*.js', (event) => { - livereload.changed(event.path) - }) - }, 75e3) + livereload.changed(event.path); + }); + }, 75e3); } - } + }; // make each bundle run in a separate process const allSubtasks = [ ...standardSubtasks, contentscriptSubtask, disableConsoleSubtask, - ].map((subtask) => runInChildProcess(subtask)) + ].map((subtask) => runInChildProcess(subtask)); // const allSubtasks = [...standardSubtasks, contentscriptSubtask].map(subtask => (subtask)) // make a parent task that runs each task in a child thread - return composeParallel(initiateLiveReload, ...allSubtasks) + return composeParallel(initiateLiveReload, ...allSubtasks); } function createBundleTaskForBuildJsExtensionNormal({ @@ -167,22 +167,22 @@ function createScriptTasks({ browserPlatforms, livereload }) { : externalDependenciesMap[filename], devMode, testing, - }) + }); } function createTaskForBuildJsExtensionDisableConsole({ devMode }) { - const filename = 'disable-console' + const filename = 'disable-console'; return bundleTask({ label: filename, filename: `${filename}.js`, filepath: `./app/scripts/${filename}.js`, devMode, - }) + }); } function createTaskForBuildJsExtensionContentscript({ devMode, testing }) { - const inpage = 'inpage' - const contentscript = 'contentscript' + const inpage = 'inpage'; + const contentscript = 'contentscript'; return composeSeries( bundleTask({ label: inpage, @@ -204,21 +204,21 @@ function createScriptTasks({ browserPlatforms, livereload }) { devMode, testing, }), - ) + ); } function bundleTask(opts) { - let bundler + let bundler; - return performBundle + return performBundle; async function performBundle() { // initialize bundler if not available yet // dont create bundler until task is actually run if (!bundler) { - bundler = generateBundler(opts, performBundle) + bundler = generateBundler(opts, performBundle); // output build logs to terminal - bundler.on('log', log) + bundler.on('log', log); } const buildPipeline = [ @@ -229,7 +229,7 @@ function createScriptTasks({ browserPlatforms, livereload }) { buffer(), // loads map from browserify file sourcemaps.init({ loadMaps: true }), - ] + ]; // Minification if (!opts.devMode) { @@ -242,7 +242,7 @@ function createScriptTasks({ browserPlatforms, livereload }) { content: true, }, }), - ) + ); } // Finalize Source Maps @@ -250,26 +250,26 @@ function createScriptTasks({ browserPlatforms, livereload }) { // Use inline source maps for development due to Chrome DevTools bug // https://bugs.chromium.org/p/chromium/issues/detail?id=931675 // note: sourcemaps call arity is important - buildPipeline.push(sourcemaps.write()) + buildPipeline.push(sourcemaps.write()); } else { - buildPipeline.push(sourcemaps.write('../sourcemaps')) + buildPipeline.push(sourcemaps.write('../sourcemaps')); } // write completed bundles browserPlatforms.forEach((platform) => { - const dest = `./dist/${platform}` - buildPipeline.push(gulp.dest(dest)) - }) + const dest = `./dist/${platform}`; + buildPipeline.push(gulp.dest(dest)); + }); // process bundles if (opts.devMode) { try { - await pump(buildPipeline) + await pump(buildPipeline); } catch (err) { - gracefulError(err) + gracefulError(err); } } else { - await pump(buildPipeline) + await pump(buildPipeline); } } } @@ -280,37 +280,37 @@ function createScriptTasks({ browserPlatforms, livereload }) { transform: [], debug: true, fullPaths: opts.devMode, - }) + }); if (!opts.buildLib) { if (opts.devMode && opts.filename === 'ui.js') { browserifyOpts.entries = [ './development/require-react-devtools.js', opts.filepath, - ] + ]; } else { - browserifyOpts.entries = [opts.filepath] + browserifyOpts.entries = [opts.filepath]; } } let bundler = browserify(browserifyOpts) .transform('babelify') - .transform('brfs') + .transform('brfs'); if (opts.buildLib) { - bundler = bundler.require(opts.dependenciesToBundle) + bundler = bundler.require(opts.dependenciesToBundle); } if (opts.externalDependencies) { - bundler = bundler.external(opts.externalDependencies) + bundler = bundler.external(opts.externalDependencies); } const environment = getEnvironment({ devMode: opts.devMode, test: opts.testing, - }) + }); if (environment === 'production' && !process.env.SENTRY_DSN) { - throw new Error('Missing SENTRY_DSN environment variable') + throw new Error('Missing SENTRY_DSN environment variable'); } // Inject variables into bundle @@ -346,46 +346,46 @@ function createScriptTasks({ browserPlatforms, livereload }) { { global: true, }, - ) + ); // Live reload - minimal rebundle on change if (opts.devMode) { - bundler = watchify(bundler) + bundler = watchify(bundler); // on any file update, re-runs the bundler bundler.on('update', () => { - performBundle() - }) + performBundle(); + }); } - return bundler + return bundler; } } function getEnvironment({ devMode, test }) { // get environment slug if (devMode) { - return 'development' + return 'development'; } else if (test) { - return 'testing' + return 'testing'; } else if (process.env.CIRCLE_BRANCH === 'master') { - return 'production' + return 'production'; } else if ( /^Version-v(\d+)[.](\d+)[.](\d+)/u.test(process.env.CIRCLE_BRANCH) ) { - return 'release-candidate' + return 'release-candidate'; } else if (process.env.CIRCLE_BRANCH === 'develop') { - return 'staging' + return 'staging'; } else if (process.env.CIRCLE_PULL_REQUEST) { - return 'pull-request' + return 'pull-request'; } - return 'other' + return 'other'; } function beep() { - process.stdout.write('\x07') + process.stdout.write('\x07'); } function gracefulError(err) { - console.warn(err) - beep() + console.warn(err); + beep(); } diff --git a/development/build/static.js b/development/build/static.js index ee3341643..d041d87ae 100644 --- a/development/build/static.js +++ b/development/build/static.js @@ -1,13 +1,13 @@ -const path = require('path') -const fs = require('fs-extra') -const watch = require('gulp-watch') -const glob = require('fast-glob') +const path = require('path'); +const fs = require('fs-extra'); +const watch = require('gulp-watch'); +const glob = require('fast-glob'); -const locales = require('../../app/_locales/index.json') +const locales = require('../../app/_locales/index.json'); -const { createTask, composeSeries } = require('./task') +const { createTask, composeSeries } = require('./task'); -module.exports = createStaticAssetTasks +module.exports = createStaticAssetTasks; const copyTargets = [ { @@ -57,20 +57,20 @@ const copyTargets = [ pattern: `runLockdown.js`, dest: ``, }, -] +]; -const languageTags = new Set() +const languageTags = new Set(); for (const locale of locales) { - const { code } = locale - const tag = code.split('_')[0] - languageTags.add(tag) + const { code } = locale; + const tag = code.split('_')[0]; + languageTags.add(tag); } for (const tag of languageTags) { copyTargets.push({ src: `./node_modules/@formatjs/intl-relativetimeformat/dist/locale-data/${tag}.json`, dest: `intl/${tag}/relative-time-format-data.json`, - }) + }); } const copyTargetsDev = [ @@ -80,7 +80,7 @@ const copyTargetsDev = [ pattern: '/chromereload.js', dest: ``, }, -] +]; function createStaticAssetTasks({ livereload, browserPlatforms }) { const prod = createTask( @@ -88,31 +88,31 @@ function createStaticAssetTasks({ livereload, browserPlatforms }) { composeSeries( ...copyTargets.map((target) => { return async function copyStaticAssets() { - await performCopy(target) - } + await performCopy(target); + }; }), ), - ) + ); const dev = createTask( 'static:dev', composeSeries( ...copyTargetsDev.map((target) => { return async function copyStaticAssets() { - await setupLiveCopy(target) - } + await setupLiveCopy(target); + }; }), ), - ) + ); - return { dev, prod } + return { dev, prod }; async function setupLiveCopy(target) { - const pattern = target.pattern || '/**/*' + const pattern = target.pattern || '/**/*'; watch(target.src + pattern, (event) => { - livereload.changed(event.path) - performCopy(target) - }) - await performCopy(target) + livereload.changed(event.path); + performCopy(target); + }); + await performCopy(target); } async function performCopy(target) { @@ -123,25 +123,25 @@ function createStaticAssetTasks({ livereload, browserPlatforms }) { target.src, `${target.src}${target.pattern}`, `./dist/${platform}/${target.dest}`, - ) + ); } else { await copyGlob( target.src, `${target.src}`, `./dist/${platform}/${target.dest}`, - ) + ); } }), - ) + ); } async function copyGlob(baseDir, srcGlob, dest) { - const sources = await glob(srcGlob, { onlyFiles: false }) + const sources = await glob(srcGlob, { onlyFiles: false }); await Promise.all( sources.map(async (src) => { - const relativePath = path.relative(baseDir, src) - await fs.copy(src, `${dest}${relativePath}`) + const relativePath = path.relative(baseDir, src); + await fs.copy(src, `${dest}${relativePath}`); }), - ) + ); } } diff --git a/development/build/styles.js b/development/build/styles.js index c8b9e6718..b1b31fbef 100644 --- a/development/build/styles.js +++ b/development/build/styles.js @@ -1,18 +1,18 @@ -const pify = require('pify') -const gulp = require('gulp') -const sass = require('gulp-sass') -sass.compiler = require('sass') -const autoprefixer = require('gulp-autoprefixer') -const gulpStylelint = require('gulp-stylelint') -const watch = require('gulp-watch') -const sourcemaps = require('gulp-sourcemaps') -const rtlcss = require('gulp-rtlcss') -const rename = require('gulp-rename') -const pump = pify(require('pump')) -const { createTask } = require('./task') +const pify = require('pify'); +const gulp = require('gulp'); +const sass = require('gulp-sass'); +sass.compiler = require('sass'); +const autoprefixer = require('gulp-autoprefixer'); +const gulpStylelint = require('gulp-stylelint'); +const watch = require('gulp-watch'); +const sourcemaps = require('gulp-sourcemaps'); +const rtlcss = require('gulp-rtlcss'); +const rename = require('gulp-rename'); +const pump = pify(require('pump')); +const { createTask } = require('./task'); // scss compilation and autoprefixing tasks -module.exports = createStyleTasks +module.exports = createStyleTasks; function createStyleTasks({ livereload }) { const prod = createTask( @@ -22,7 +22,7 @@ function createStyleTasks({ livereload }) { dest: 'ui/app/css/output', devMode: false, }), - ) + ); const dev = createTask( 'styles:dev', @@ -32,7 +32,7 @@ function createStyleTasks({ livereload }) { devMode: true, pattern: 'ui/app/**/*.scss', }), - ) + ); const lint = createTask('lint-scss', function () { return gulp.src('ui/app/css/itcss/**/*.scss').pipe( @@ -40,27 +40,27 @@ function createStyleTasks({ livereload }) { reporters: [{ formatter: 'string', console: true }], fix: true, }), - ) - }) + ); + }); - return { prod, dev, lint } + return { prod, dev, lint }; function createScssBuildTask({ src, dest, devMode, pattern }) { return async function () { if (devMode) { watch(pattern, async (event) => { - await buildScss() - livereload.changed(event.path) - }) + await buildScss(); + livereload.changed(event.path); + }); } - await buildScss() - } + await buildScss(); + }; async function buildScss() { await Promise.all([ buildScssPipeline(src, dest, devMode, false), buildScssPipeline(src, dest, devMode, true), - ]) + ]); } } } @@ -78,5 +78,5 @@ async function buildScssPipeline(src, dest, devMode, rtl) { devMode && sourcemaps.write(), gulp.dest(dest), ].filter(Boolean), - ) + ); } diff --git a/development/build/task.js b/development/build/task.js index 1ed252413..e4de01ef6 100644 --- a/development/build/task.js +++ b/development/build/task.js @@ -1,8 +1,8 @@ -const EventEmitter = require('events') -const spawn = require('cross-spawn') +const EventEmitter = require('events'); +const spawn = require('cross-spawn'); -const tasks = {} -const taskEvents = new EventEmitter() +const tasks = {}; +const taskEvents = new EventEmitter(); module.exports = { detectAndRunEntryTask, @@ -13,74 +13,74 @@ module.exports = { composeSeries, composeParallel, runInChildProcess, -} +}; -const { setupTaskDisplay } = require('./display') +const { setupTaskDisplay } = require('./display'); function detectAndRunEntryTask() { // get requested task name and execute - const taskName = process.argv[2] + const taskName = process.argv[2]; if (!taskName) { - throw new Error(`MetaMask build: No task name specified`) + throw new Error(`MetaMask build: No task name specified`); } - const skipStats = process.argv[3] === '--skip-stats' + const skipStats = process.argv[3] === '--skip-stats'; - runTask(taskName, { skipStats }) + runTask(taskName, { skipStats }); } async function runTask(taskName, { skipStats } = {}) { if (!(taskName in tasks)) { - throw new Error(`MetaMask build: Unrecognized task name "${taskName}"`) + throw new Error(`MetaMask build: Unrecognized task name "${taskName}"`); } if (!skipStats) { - setupTaskDisplay(taskEvents) - console.log(`running task "${taskName}"...`) + setupTaskDisplay(taskEvents); + console.log(`running task "${taskName}"...`); } try { - await tasks[taskName]() + await tasks[taskName](); } catch (err) { console.error( `MetaMask build: Encountered an error while running task "${taskName}".`, - ) - console.error(err) - process.exit(1) + ); + console.error(err); + process.exit(1); } - taskEvents.emit('complete') + taskEvents.emit('complete'); } function createTask(taskName, taskFn) { if (taskName in tasks) { throw new Error( `MetaMask build: task "${taskName}" already exists. Refusing to redefine`, - ) + ); } - const task = instrumentForTaskStats(taskName, taskFn) - task.taskName = taskName - tasks[taskName] = task - return task + const task = instrumentForTaskStats(taskName, taskFn); + task.taskName = taskName; + tasks[taskName] = task; + return task; } function runInChildProcess(task) { - const taskName = typeof task === 'string' ? task : task.taskName + const taskName = typeof task === 'string' ? task : task.taskName; if (!taskName) { throw new Error( `MetaMask build: runInChildProcess unable to identify task name`, - ) + ); } return instrumentForTaskStats(taskName, async () => { const childProcess = spawn('yarn', ['build', taskName, '--skip-stats'], { env: process.env, - }) + }); // forward logs to main process // skip the first stdout event (announcing the process command) childProcess.stdout.once('data', () => { childProcess.stdout.on('data', (data) => process.stdout.write(`${taskName}: ${data}`), - ) - }) + ); + }); childProcess.stderr.on('data', (data) => process.stderr.write(`${taskName}: ${data}`), - ) + ); // await end of process await new Promise((resolve, reject) => { childProcess.once('close', (errCode) => { @@ -89,37 +89,37 @@ function runInChildProcess(task) { new Error( `MetaMask build: runInChildProcess for task "${taskName}" encountered an error ${errCode}`, ), - ) - return + ); + return; } - resolve() - }) - }) - }) + resolve(); + }); + }); + }); } function instrumentForTaskStats(taskName, asyncFn) { return async () => { - const start = Date.now() - taskEvents.emit('start', [taskName, start]) - await asyncFn() - const end = Date.now() - taskEvents.emit('end', [taskName, start, end]) - } + const start = Date.now(); + taskEvents.emit('start', [taskName, start]); + await asyncFn(); + const end = Date.now(); + taskEvents.emit('end', [taskName, start, end]); + }; } function composeSeries(...subtasks) { return async () => { - const realTasks = subtasks + const realTasks = subtasks; for (const subtask of realTasks) { - await subtask() + await subtask(); } - } + }; } function composeParallel(...subtasks) { return async () => { - const realTasks = subtasks - await Promise.all(realTasks.map((subtask) => subtask())) - } + const realTasks = subtasks; + await Promise.all(realTasks.map((subtask) => subtask())); + }; } diff --git a/development/create-static-server.js b/development/create-static-server.js index 3312c43e7..c01a5e16a 100644 --- a/development/create-static-server.js +++ b/development/create-static-server.js @@ -1,22 +1,22 @@ -const http = require('http') -const path = require('path') +const http = require('http'); +const path = require('path'); -const serveHandler = require('serve-handler') +const serveHandler = require('serve-handler'); const createStaticServer = (rootDirectory) => { return http.createServer((request, response) => { if (request.url.startsWith('/node_modules/')) { - request.url = request.url.substr(14) + request.url = request.url.substr(14); return serveHandler(request, response, { directoryListing: false, public: path.resolve('./node_modules'), - }) + }); } return serveHandler(request, response, { directoryListing: false, public: rootDirectory, - }) - }) -} + }); + }); +}; -module.exports = createStaticServer +module.exports = createStaticServer; diff --git a/development/lib/create-segment-server.js b/development/lib/create-segment-server.js index 2a15a34c9..00f999c9e 100644 --- a/development/lib/create-segment-server.js +++ b/development/lib/create-segment-server.js @@ -1,4 +1,4 @@ -const http = require('http') +const http = require('http'); /** * This is the default error handler to be used by this mock segment server. @@ -7,8 +7,8 @@ const http = require('http') * @param {Error} error - The server error */ function defaultOnError(error) { - console.log(error) - process.exit(1) + console.log(error); + process.exit(1); } /** @@ -32,62 +32,62 @@ function defaultOnError(error) { */ function createSegmentServer(onRequest, onError = defaultOnError) { const server = http.createServer(async (request, response) => { - const chunks = [] + const chunks = []; request.on('data', (chunk) => { - chunks.push(chunk) - }) + chunks.push(chunk); + }); await new Promise((resolve) => { request.on('end', () => { - resolve() - }) - }) + resolve(); + }); + }); // respond to preflight request if (request.method === 'OPTIONS') { - response.setHeader('Access-Control-Allow-Origin', '*') - response.setHeader('Access-Control-Allow-Methods', '*') - response.setHeader('Access-Control-Allow-Headers', '*') - response.statusCode = 200 - response.end() - return + response.setHeader('Access-Control-Allow-Origin', '*'); + response.setHeader('Access-Control-Allow-Methods', '*'); + response.setHeader('Access-Control-Allow-Headers', '*'); + response.statusCode = 200; + response.end(); + return; } - let metricEvents = [] + let metricEvents = []; if (chunks.length) { - const body = Buffer.concat(chunks).toString() - const segmentPayload = JSON.parse(body) - metricEvents = segmentPayload.batch + const body = Buffer.concat(chunks).toString(); + const segmentPayload = JSON.parse(body); + metricEvents = segmentPayload.batch; } - onRequest(request, response, metricEvents) - }) + onRequest(request, response, metricEvents); + }); - server.on('error', onError) + server.on('error', onError); return { start: async (port) => { await new Promise((resolve, reject) => { server.listen(port, (error) => { if (error) { - return reject(error) + return reject(error); } - return resolve() - }) - }) + return resolve(); + }); + }); }, stop: async () => { await new Promise((resolve, reject) => { server.close((error) => { if (error) { - return reject(error) + return reject(error); } - return resolve() - }) - }) + return resolve(); + }); + }); }, - } + }; } -module.exports = { createSegmentServer } +module.exports = { createSegmentServer }; diff --git a/development/lib/locales.js b/development/lib/locales.js index 86f1e6ec9..0b83d0ac6 100644 --- a/development/lib/locales.js +++ b/development/lib/locales.js @@ -1,10 +1,10 @@ -const path = require('path') -const fs = require('fs') -const { promisify } = require('util') +const path = require('path'); +const fs = require('fs'); +const { promisify } = require('util'); -const log = require('loglevel') +const log = require('loglevel'); -const readFile = promisify(fs.readFile) +const readFile = promisify(fs.readFile); function getLocalePath(code) { return path.resolve( @@ -15,26 +15,26 @@ function getLocalePath(code) { '_locales', code, 'messages.json', - ) + ); } async function getLocale(code) { try { - const localeFilePath = getLocalePath(code) - const fileContents = await readFile(localeFilePath, 'utf8') - return JSON.parse(fileContents) + const localeFilePath = getLocalePath(code); + const fileContents = await readFile(localeFilePath, 'utf8'); + return JSON.parse(fileContents); } catch (e) { if (e.code === 'ENOENT') { - log.error('Locale file not found') + log.error('Locale file not found'); } else { - log.error(`Error opening your locale ("${code}") file: `, e) + log.error(`Error opening your locale ("${code}") file: `, e); } - process.exit(1) + process.exit(1); } } function compareLocalesForMissingItems({ base, subject }) { - return Object.keys(base).filter((key) => !subject[key]) + return Object.keys(base).filter((key) => !subject[key]); } function compareLocalesForMissingDescriptions({ englishLocale, targetLocale }) { @@ -43,7 +43,7 @@ function compareLocalesForMissingDescriptions({ englishLocale, targetLocale }) { targetLocale[key] !== undefined && englishLocale[key].description !== undefined && englishLocale[key].description !== targetLocale[key].description, - ) + ); } module.exports = { @@ -51,4 +51,4 @@ module.exports = { compareLocalesForMissingItems, getLocale, getLocalePath, -} +}; diff --git a/development/lib/parse-port.js b/development/lib/parse-port.js index 0a53712fb..4368da79f 100644 --- a/development/lib/parse-port.js +++ b/development/lib/parse-port.js @@ -6,15 +6,15 @@ * @returns {number} The parsed port number */ function parsePort(portString) { - const port = Number(portString) + const port = Number(portString); if (!Number.isInteger(port)) { - throw new Error(`Port '${portString}' is invalid; must be an integer`) + throw new Error(`Port '${portString}' is invalid; must be an integer`); } else if (port < 0 || port > 65535) { throw new Error( `Port '${portString}' is out of range; must be between 0 and 65535 inclusive`, - ) + ); } - return port + return port; } -module.exports = { parsePort } +module.exports = { parsePort }; diff --git a/development/metamaskbot-build-announce.js b/development/metamaskbot-build-announce.js index 8ea766ed3..f0fd33260 100755 --- a/development/metamaskbot-build-announce.js +++ b/development/metamaskbot-build-announce.js @@ -1,42 +1,42 @@ #!/usr/bin/env node -const { promises: fs } = require('fs') -const path = require('path') -const fetch = require('node-fetch') -const VERSION = require('../dist/chrome/manifest.json').version // eslint-disable-line import/no-unresolved +const { promises: fs } = require('fs'); +const path = require('path'); +const fetch = require('node-fetch'); +const VERSION = require('../dist/chrome/manifest.json').version; // eslint-disable-line import/no-unresolved -start().catch(console.error) +start().catch(console.error); function capitalizeFirstLetter(string) { - return string.charAt(0).toUpperCase() + string.slice(1) + return string.charAt(0).toUpperCase() + string.slice(1); } async function start() { - const { GITHUB_COMMENT_TOKEN, CIRCLE_PULL_REQUEST } = process.env - console.log('CIRCLE_PULL_REQUEST', CIRCLE_PULL_REQUEST) - const { CIRCLE_SHA1 } = process.env - console.log('CIRCLE_SHA1', CIRCLE_SHA1) - const { CIRCLE_BUILD_NUM } = process.env - console.log('CIRCLE_BUILD_NUM', CIRCLE_BUILD_NUM) + const { GITHUB_COMMENT_TOKEN, CIRCLE_PULL_REQUEST } = process.env; + console.log('CIRCLE_PULL_REQUEST', CIRCLE_PULL_REQUEST); + const { CIRCLE_SHA1 } = process.env; + console.log('CIRCLE_SHA1', CIRCLE_SHA1); + const { CIRCLE_BUILD_NUM } = process.env; + console.log('CIRCLE_BUILD_NUM', CIRCLE_BUILD_NUM); if (!CIRCLE_PULL_REQUEST) { - console.warn(`No pull request detected for commit "${CIRCLE_SHA1}"`) - return + console.warn(`No pull request detected for commit "${CIRCLE_SHA1}"`); + return; } - const CIRCLE_PR_NUMBER = CIRCLE_PULL_REQUEST.split('/').pop() - const SHORT_SHA1 = CIRCLE_SHA1.slice(0, 7) - const BUILD_LINK_BASE = `https://${CIRCLE_BUILD_NUM}-42009758-gh.circle-artifacts.com/0` + const CIRCLE_PR_NUMBER = CIRCLE_PULL_REQUEST.split('/').pop(); + const SHORT_SHA1 = CIRCLE_SHA1.slice(0, 7); + const BUILD_LINK_BASE = `https://${CIRCLE_BUILD_NUM}-42009758-gh.circle-artifacts.com/0`; // build the github comment content // links to extension builds - const platforms = ['chrome', 'firefox', 'opera'] + const platforms = ['chrome', 'firefox', 'opera']; const buildLinks = platforms .map((platform) => { - const url = `${BUILD_LINK_BASE}/builds/metamask-${platform}-${VERSION}.zip` - return `${platform}` + const url = `${BUILD_LINK_BASE}/builds/metamask-${platform}-${VERSION}.zip`; + return `${platform}`; }) - .join(', ') + .join(', '); // links to bundle browser builds const bundles = [ @@ -47,22 +47,22 @@ async function start() { 'ui-libs', 'bg-libs', 'phishing-detect', - ] + ]; const bundleLinks = bundles .map((bundle) => { - const url = `${BUILD_LINK_BASE}/build-artifacts/source-map-explorer/${bundle}.html` - return `${bundle}` + const url = `${BUILD_LINK_BASE}/build-artifacts/source-map-explorer/${bundle}.html`; + return `${bundle}`; }) - .join(', ') + .join(', '); - const coverageUrl = `${BUILD_LINK_BASE}/coverage/index.html` - const coverageLink = `Report` + const coverageUrl = `${BUILD_LINK_BASE}/coverage/index.html`; + const coverageLink = `Report`; - const storybookUrl = `${BUILD_LINK_BASE}/storybook/index.html` - const storybookLink = `Storybook` + const storybookUrl = `${BUILD_LINK_BASE}/storybook/index.html`; + const storybookLink = `Storybook`; // link to artifacts - const allArtifactsUrl = `https://circleci.com/gh/MetaMask/metamask-extension/${CIRCLE_BUILD_NUM}#artifacts/containers/0` + const allArtifactsUrl = `https://circleci.com/gh/MetaMask/metamask-extension/${CIRCLE_BUILD_NUM}#artifacts/containers/0`; const contentRows = [ `builds: ${buildLinks}`, @@ -70,124 +70,124 @@ async function start() { `code coverage: ${coverageLink}`, `storybook: ${storybookLink}`, `all artifacts`, - ] + ]; const hiddenContent = `
    ${contentRows .map((row) => `
  • ${row}
  • `) - .join('\n')}
` - const exposedContent = `Builds ready [${SHORT_SHA1}]` - const artifactsBody = `
${exposedContent}${hiddenContent}
` + .join('\n')}`; + const exposedContent = `Builds ready [${SHORT_SHA1}]`; + const artifactsBody = `
${exposedContent}${hiddenContent}
`; - const benchmarkResults = {} + const benchmarkResults = {}; for (const platform of platforms) { const benchmarkPath = path.resolve( __dirname, '..', path.join('test-artifacts', platform, 'benchmark', 'pageload.json'), - ) + ); try { - const data = await fs.readFile(benchmarkPath, 'utf8') - const benchmark = JSON.parse(data) - benchmarkResults[platform] = benchmark + const data = await fs.readFile(benchmarkPath, 'utf8'); + const benchmark = JSON.parse(data); + benchmarkResults[platform] = benchmark; } catch (error) { if (error.code === 'ENOENT') { - console.log(`No benchmark data found for ${platform}; skipping`) + console.log(`No benchmark data found for ${platform}; skipping`); } else { console.error( `Error encountered processing benchmark data for '${platform}': '${error}'`, - ) + ); } } } - const summaryPlatform = 'chrome' - const summaryPage = 'home' - let commentBody + const summaryPlatform = 'chrome'; + const summaryPage = 'home'; + let commentBody; if (benchmarkResults[summaryPlatform]) { try { const summaryPageLoad = Math.round( parseFloat(benchmarkResults[summaryPlatform][summaryPage].average.load), - ) + ); const summaryPageLoadMarginOfError = Math.round( parseFloat( benchmarkResults[summaryPlatform][summaryPage].marginOfError.load, ), - ) - const benchmarkSummary = `Page Load Metrics (${summaryPageLoad} ± ${summaryPageLoadMarginOfError} ms)` + ); + const benchmarkSummary = `Page Load Metrics (${summaryPageLoad} ± ${summaryPageLoadMarginOfError} ms)`; - const allPlatforms = new Set() - const allPages = new Set() - const allMetrics = new Set() - const allMeasures = new Set() + const allPlatforms = new Set(); + const allPages = new Set(); + const allMetrics = new Set(); + const allMeasures = new Set(); for (const platform of Object.keys(benchmarkResults)) { - allPlatforms.add(platform) - const platformBenchmark = benchmarkResults[platform] - const pages = Object.keys(platformBenchmark) + allPlatforms.add(platform); + const platformBenchmark = benchmarkResults[platform]; + const pages = Object.keys(platformBenchmark); for (const page of pages) { - allPages.add(page) - const pageBenchmark = platformBenchmark[page] - const measures = Object.keys(pageBenchmark) + allPages.add(page); + const pageBenchmark = platformBenchmark[page]; + const measures = Object.keys(pageBenchmark); for (const measure of measures) { - allMeasures.add(measure) - const measureBenchmark = pageBenchmark[measure] - const metrics = Object.keys(measureBenchmark) + allMeasures.add(measure); + const measureBenchmark = pageBenchmark[measure]; + const metrics = Object.keys(measureBenchmark); for (const metric of metrics) { - allMetrics.add(metric) + allMetrics.add(metric); } } } } - const tableRows = [] + const tableRows = []; for (const platform of allPlatforms) { - const pageRows = [] + const pageRows = []; for (const page of allPages) { - const metricRows = [] + const metricRows = []; for (const metric of allMetrics) { - let metricData = `${metric}` + let metricData = `${metric}`; for (const measure of allMeasures) { metricData += `${Math.round( parseFloat(benchmarkResults[platform][page][measure][metric]), - )}` + )}`; } - metricRows.push(metricData) + metricRows.push(metricData); } metricRows[0] = `${capitalizeFirstLetter(page)}${metricRows[0]}` - pageRows.push(...metricRows) + }">${capitalizeFirstLetter(page)}${metricRows[0]}`; + pageRows.push(...metricRows); } pageRows[0] = `${capitalizeFirstLetter(platform)}${pageRows[0]}` + }">${capitalizeFirstLetter(platform)}${pageRows[0]}`; for (const row of pageRows) { - tableRows.push(`${row}`) + tableRows.push(`${row}`); } } - const benchmarkTableHeaders = ['Platform', 'Page', 'Metric'] + const benchmarkTableHeaders = ['Platform', 'Page', 'Metric']; for (const measure of allMeasures) { - benchmarkTableHeaders.push(`${capitalizeFirstLetter(measure)} (ms)`) + benchmarkTableHeaders.push(`${capitalizeFirstLetter(measure)} (ms)`); } const benchmarkTableHeader = `${benchmarkTableHeaders .map((header) => `${header}`) - .join('')}` - const benchmarkTableBody = `${tableRows.join('')}` - const benchmarkTable = `${benchmarkTableHeader}${benchmarkTableBody}
` - const benchmarkBody = `
${benchmarkSummary}${benchmarkTable}
` - commentBody = `${artifactsBody}${benchmarkBody}` + .join('')}`; + const benchmarkTableBody = `${tableRows.join('')}`; + const benchmarkTable = `${benchmarkTableHeader}${benchmarkTableBody}
`; + const benchmarkBody = `
${benchmarkSummary}${benchmarkTable}
`; + commentBody = `${artifactsBody}${benchmarkBody}`; } catch (error) { - console.error(`Error constructing benchmark results: '${error}'`) - commentBody = artifactsBody + console.error(`Error constructing benchmark results: '${error}'`); + commentBody = artifactsBody; } } else { - console.log(`No results for ${summaryPlatform} found; skipping benchmark`) - commentBody = artifactsBody + console.log(`No results for ${summaryPlatform} found; skipping benchmark`); + commentBody = artifactsBody; } - const JSON_PAYLOAD = JSON.stringify({ body: commentBody }) - const POST_COMMENT_URI = `https://api.github.com/repos/metamask/metamask-extension/issues/${CIRCLE_PR_NUMBER}/comments` - console.log(`Announcement:\n${commentBody}`) - console.log(`Posting to: ${POST_COMMENT_URI}`) + const JSON_PAYLOAD = JSON.stringify({ body: commentBody }); + const POST_COMMENT_URI = `https://api.github.com/repos/metamask/metamask-extension/issues/${CIRCLE_PR_NUMBER}/comments`; + console.log(`Announcement:\n${commentBody}`); + console.log(`Posting to: ${POST_COMMENT_URI}`); const response = await fetch(POST_COMMENT_URI, { method: 'POST', @@ -196,8 +196,8 @@ async function start() { 'User-Agent': 'metamaskbot', Authorization: `token ${GITHUB_COMMENT_TOKEN}`, }, - }) + }); if (!response.ok) { - throw new Error(`Post comment failed with status '${response.statusText}'`) + throw new Error(`Post comment failed with status '${response.statusText}'`); } } diff --git a/development/missing-locale-strings.js b/development/missing-locale-strings.js index 74f26b8bd..387e13501 100644 --- a/development/missing-locale-strings.js +++ b/development/missing-locale-strings.js @@ -15,64 +15,64 @@ // // ////////////////////////////////////////////////////////////////////////////// -const log = require('loglevel') -const localeIndex = require('../app/_locales/index.json') -const { compareLocalesForMissingItems, getLocale } = require('./lib/locales') +const log = require('loglevel'); +const localeIndex = require('../app/_locales/index.json'); +const { compareLocalesForMissingItems, getLocale } = require('./lib/locales'); -log.setDefaultLevel('info') +log.setDefaultLevel('info'); -let verbose = false -let specifiedLocale +let verbose = false; +let specifiedLocale; for (const arg of process.argv.slice(2)) { if (arg === '--verbose') { - verbose = true + verbose = true; } else { - specifiedLocale = arg + specifiedLocale = arg; } } main().catch((error) => { - log.error(error) - process.exit(1) -}) + log.error(error); + process.exit(1); +}); async function main() { if (specifiedLocale === 'en') { throw new Error( `Can't compare 'en' locale to itself to find missing messages`, - ) + ); } else if (specifiedLocale) { - await reportMissingMessages(specifiedLocale) + await reportMissingMessages(specifiedLocale); } else { const localeCodes = localeIndex .filter((localeMeta) => localeMeta.code !== 'en') - .map((localeMeta) => localeMeta.code) + .map((localeMeta) => localeMeta.code); for (const code of localeCodes) { - await reportMissingMessages(code) + await reportMissingMessages(code); } } } async function reportMissingMessages(code) { - const englishLocale = await getLocale('en') - const targetLocale = await getLocale(code) + const englishLocale = await getLocale('en'); + const targetLocale = await getLocale(code); const missingItems = compareLocalesForMissingItems({ base: englishLocale, subject: targetLocale, - }) + }); - const englishEntryCount = Object.keys(englishLocale).length + const englishEntryCount = Object.keys(englishLocale).length; const coveragePercent = - (100 * (englishEntryCount - missingItems.length)) / englishEntryCount + (100 * (englishEntryCount - missingItems.length)) / englishEntryCount; - log.info(`**${code}**: ${coveragePercent.toFixed(2)}% coverage`) + log.info(`**${code}**: ${coveragePercent.toFixed(2)}% coverage`); if (missingItems.length && verbose) { - console.log(`**${code}**: ${missingItems.length} missing messages`) - log.info('Extra items that should not be localized:') + console.log(`**${code}**: ${missingItems.length} missing messages`); + log.info('Extra items that should not be localized:'); missingItems.forEach(function (key) { - log.info(` - [ ] ${key}`) - }) + log.info(` - [ ] ${key}`); + }); } } diff --git a/development/mock-3box.js b/development/mock-3box.js index 14c888f86..ebbbe325d 100644 --- a/development/mock-3box.js +++ b/development/mock-3box.js @@ -1,11 +1,11 @@ function delay(time) { - return new Promise((resolve) => setTimeout(resolve, time)) + return new Promise((resolve) => setTimeout(resolve, time)); } async function loadFromMock3Box(key) { - const res = await window.fetch(`http://localhost:8889?key=${key}`) - const text = await res.text() - return text.length ? JSON.parse(text) : null + const res = await window.fetch(`http://localhost:8889?key=${key}`); + const text = await res.text(); + return text.length ? JSON.parse(text) : null; } async function saveToMock3Box(key, newDataAtKey) { @@ -15,54 +15,54 @@ async function saveToMock3Box(key, newDataAtKey) { key, data: newDataAtKey, }), - }) + }); - return res.text() + return res.text(); } class Mock3Box { static openBox(address) { - this.address = address + this.address = address; return Promise.resolve({ onSyncDone: (cb) => { - setTimeout(cb, 200) + setTimeout(cb, 200); }, openSpace: async (spaceName, config) => { - const { onSyncDone } = config - this.spaceName = spaceName + const { onSyncDone } = config; + this.spaceName = spaceName; - setTimeout(onSyncDone, 150) + setTimeout(onSyncDone, 150); - await delay(50) + await delay(50); return { private: { get: async (key) => { - await delay(50) + await delay(50); const res = await loadFromMock3Box( `${this.address}-${this.spaceName}-${key}`, - ) - return res + ); + return res; }, set: async (key, data) => { await saveToMock3Box( `${this.address}-${this.spaceName}-${key}`, data, - ) - await delay(50) - return null + ); + await delay(50); + return null; }, }, - } + }; }, logout: () => undefined, - }) + }); } static async getConfig(address) { - const backup = await loadFromMock3Box(`${address}-metamask-metamaskBackup`) - return backup ? { spaces: { metamask: {} } } : {} + const backup = await loadFromMock3Box(`${address}-metamask-metamaskBackup`); + return backup ? { spaces: { metamask: {} } } : {}; } } -module.exports = Mock3Box +module.exports = Mock3Box; diff --git a/development/mock-segment.js b/development/mock-segment.js index f4e2acb58..b05e661d6 100644 --- a/development/mock-segment.js +++ b/development/mock-segment.js @@ -1,28 +1,28 @@ -const { createSegmentServer } = require('./lib/create-segment-server') -const { parsePort } = require('./lib/parse-port') +const { createSegmentServer } = require('./lib/create-segment-server'); +const { parsePort } = require('./lib/parse-port'); -const DEFAULT_PORT = 9090 -const prefix = '[mock-segment]' +const DEFAULT_PORT = 9090; +const prefix = '[mock-segment]'; function onRequest(request, response, events) { - console.log(`${prefix}: ${request.method} ${request.url}`) + console.log(`${prefix}: ${request.method} ${request.url}`); const eventDescriptions = events.map((event) => { if (event.type === 'track') { - return event.event + return event.event; } else if (event.type === 'page') { - return event.name + return event.name; } - return `[Unrecognized event type: ${event.type}]` - }) - console.log(`${prefix}: Events received: ${eventDescriptions.join(', ')}`) + return `[Unrecognized event type: ${event.type}]`; + }); + console.log(`${prefix}: Events received: ${eventDescriptions.join(', ')}`); - response.statusCode = 200 - response.end() + response.statusCode = 200; + response.end(); } function onError(error) { - console.error(error) - process.exit(1) + console.error(error); + process.exit(1); } /** @@ -45,24 +45,24 @@ function onError(error) { * metric events. */ const main = async () => { - const args = process.argv.slice(2) + const args = process.argv.slice(2); - let port = process.env.port || DEFAULT_PORT + let port = process.env.port || DEFAULT_PORT; while (args.length) { if (/^(--port|-p)$/u.test(args[0])) { if (args[1] === undefined) { - throw new Error('Missing port argument') + throw new Error('Missing port argument'); } - port = parsePort(args[1]) - args.splice(0, 2) + port = parsePort(args[1]); + args.splice(0, 2); } } - const server = createSegmentServer(onRequest, onError) + const server = createSegmentServer(onRequest, onError); - await server.start(port) - console.log(`${prefix}: Listening on port ${port}`) -} + await server.start(port); + console.log(`${prefix}: Listening on port ${port}`); +}; -main().catch(onError) +main().catch(onError); diff --git a/development/require-react-devtools.js b/development/require-react-devtools.js index 9d0b1f46d..9af12aa87 100644 --- a/development/require-react-devtools.js +++ b/development/require-react-devtools.js @@ -1 +1 @@ -require('react-devtools') +require('react-devtools'); diff --git a/development/sentry-publish.js b/development/sentry-publish.js index aad6e4ac4..6fee0f950 100644 --- a/development/sentry-publish.js +++ b/development/sentry-publish.js @@ -1,84 +1,86 @@ #!/usr/bin/env node -const childProcess = require('child_process') -const pify = require('pify') +const childProcess = require('child_process'); +const pify = require('pify'); -const exec = pify(childProcess.exec, { multiArgs: true }) -const VERSION = require('../dist/chrome/manifest.json').version // eslint-disable-line import/no-unresolved +const exec = pify(childProcess.exec, { multiArgs: true }); +const VERSION = require('../dist/chrome/manifest.json').version; // eslint-disable-line import/no-unresolved start().catch((error) => { - console.error(error) - process.exit(1) -}) + console.error(error); + process.exit(1); +}); async function start() { - const authWorked = await checkIfAuthWorks() + const authWorked = await checkIfAuthWorks(); if (!authWorked) { - throw new Error(`Sentry auth failed`) + throw new Error(`Sentry auth failed`); } // check if version exists or not - const versionAlreadyExists = await checkIfVersionExists() + const versionAlreadyExists = await checkIfVersionExists(); // abort if versions exists if (versionAlreadyExists) { console.log( `Version "${VERSION}" already exists on Sentry, skipping version creation`, - ) + ); } else { // create sentry release - console.log(`creating Sentry release for "${VERSION}"...`) + console.log(`creating Sentry release for "${VERSION}"...`); await exec( `sentry-cli releases --org 'metamask' --project 'metamask' new ${VERSION}`, - ) + ); console.log( `removing any existing files from Sentry release "${VERSION}"...`, - ) + ); await exec( `sentry-cli releases --org 'metamask' --project 'metamask' files ${VERSION} delete --all`, - ) + ); } // check if version has artifacts or not const versionHasArtifacts = - versionAlreadyExists && (await checkIfVersionHasArtifacts()) + versionAlreadyExists && (await checkIfVersionHasArtifacts()); if (versionHasArtifacts) { console.log( `Version "${VERSION}" already has artifacts on Sentry, skipping sourcemap upload`, - ) - return + ); + return; } // upload sentry source and sourcemaps - await exec(`./development/sentry-upload-artifacts.sh --release ${VERSION}`) + await exec(`./development/sentry-upload-artifacts.sh --release ${VERSION}`); } async function checkIfAuthWorks() { const itWorked = await doesNotFail(async () => { - await exec(`sentry-cli releases --org 'metamask' --project 'metamask' list`) - }) - return itWorked + await exec( + `sentry-cli releases --org 'metamask' --project 'metamask' list`, + ); + }); + return itWorked; } async function checkIfVersionExists() { const versionAlreadyExists = await doesNotFail(async () => { await exec( `sentry-cli releases --org 'metamask' --project 'metamask' info ${VERSION}`, - ) - }) - return versionAlreadyExists + ); + }); + return versionAlreadyExists; } async function checkIfVersionHasArtifacts() { const artifacts = await exec( `sentry-cli releases --org 'metamask' --project 'metamask' files ${VERSION} list`, - ) + ); // When there's no artifacts, we get a response from the shell like this ['', ''] - return artifacts[0] && artifacts[0].length > 0 + return artifacts[0] && artifacts[0].length > 0; } async function doesNotFail(asyncFn) { try { - await asyncFn() - return true + await asyncFn(); + return true; } catch (err) { - return false + return false; } } diff --git a/development/show-deps-install-scripts.js b/development/show-deps-install-scripts.js index 3421ed351..dca698b10 100644 --- a/development/show-deps-install-scripts.js +++ b/development/show-deps-install-scripts.js @@ -1,40 +1,40 @@ // This script lists all dependencies that have package install scripts -const path = require('path') -const readInstalled = require('read-installed') +const path = require('path'); +const readInstalled = require('read-installed'); -const installScripts = ['preinstall', 'install', 'postinstall'] +const installScripts = ['preinstall', 'install', 'postinstall']; readInstalled('./', { dev: true }, function (err, data) { if (err) { - throw err + throw err; } - const deps = data.dependencies + const deps = data.dependencies; Object.entries(deps).forEach(([packageName, packageData]) => { - const packageScripts = packageData.scripts || {} - const scriptKeys = Reflect.ownKeys(packageScripts) + const packageScripts = packageData.scripts || {}; + const scriptKeys = Reflect.ownKeys(packageScripts); const hasInstallScript = installScripts.some((installKey) => scriptKeys.includes(installKey), - ) + ); if (!hasInstallScript) { - return + return; } - const matchingScripts = {} + const matchingScripts = {}; if (packageScripts.preinstall) { - matchingScripts.preinstall = packageScripts.preinstall + matchingScripts.preinstall = packageScripts.preinstall; } if (packageScripts.install) { - matchingScripts.install = packageScripts.install + matchingScripts.install = packageScripts.install; } if (packageScripts.postinstall) { - matchingScripts.postinstall = packageScripts.postinstall + matchingScripts.postinstall = packageScripts.postinstall; } - const scriptNames = Reflect.ownKeys(matchingScripts) + const scriptNames = Reflect.ownKeys(matchingScripts); - const relativePath = path.relative(process.cwd(), packageData.path) + const relativePath = path.relative(process.cwd(), packageData.path); - console.log(`${packageName}: ${relativePath} ${scriptNames}`) - }) -}) + console.log(`${packageName}: ${relativePath} ${scriptNames}`); + }); +}); diff --git a/development/sourcemap-validator.js b/development/sourcemap-validator.js index 6730b8785..15feb56f1 100644 --- a/development/sourcemap-validator.js +++ b/development/sourcemap-validator.js @@ -1,9 +1,9 @@ -const fs = require('fs') -const path = require('path') -const { SourceMapConsumer } = require('source-map') -const pify = require('pify') +const fs = require('fs'); +const path = require('path'); +const { SourceMapConsumer } = require('source-map'); +const pify = require('pify'); -const fsAsync = pify(fs) +const fsAsync = pify(fs); // // Utility to help check if sourcemaps are working @@ -14,9 +14,9 @@ const fsAsync = pify(fs) // start().catch((error) => { - console.error(error) - process.exit(1) -}) + console.error(error); + process.exit(1); +}); async function start() { const targetFiles = [ @@ -27,48 +27,48 @@ async function start() { 'phishing-detect.js', `ui.js`, // `ui-libs.js`, skipped because source maps are invalid due to browserify bug: https://github.com/browserify/browserify/issues/1971 - ] - let valid = true + ]; + let valid = true; for (const buildName of targetFiles) { - const fileIsValid = await validateSourcemapForFile({ buildName }) - valid = valid && fileIsValid + const fileIsValid = await validateSourcemapForFile({ buildName }); + valid = valid && fileIsValid; } if (!valid) { - process.exit(1) + process.exit(1); } } async function validateSourcemapForFile({ buildName }) { - console.log(`build "${buildName}"`) - const platform = `chrome` + console.log(`build "${buildName}"`); + const platform = `chrome`; // load build and sourcemaps - let rawBuild + let rawBuild; try { const filePath = path.join( __dirname, `/../dist/${platform}/`, `${buildName}`, - ) - rawBuild = await fsAsync.readFile(filePath, 'utf8') + ); + rawBuild = await fsAsync.readFile(filePath, 'utf8'); } catch (_) { // empty } if (!rawBuild) { throw new Error( `SourcemapValidator - failed to load source file for "${buildName}"`, - ) + ); } // attempt to load in dist mode - let rawSourceMap + let rawSourceMap; try { const filePath = path.join( __dirname, `/../dist/sourcemaps/`, `${buildName}.map`, - ) - rawSourceMap = await fsAsync.readFile(filePath, 'utf8') + ); + rawSourceMap = await fsAsync.readFile(filePath, 'utf8'); } catch (_) { // empty } @@ -78,94 +78,96 @@ async function validateSourcemapForFile({ buildName }) { __dirname, `/../dist/${platform}/`, `${buildName}.map`, - ) - rawSourceMap = await fsAsync.readFile(filePath, 'utf8') + ); + rawSourceMap = await fsAsync.readFile(filePath, 'utf8'); } catch (_) { // empty } if (!rawSourceMap) { throw new Error( `SourcemapValidator - failed to load sourcemaps for "${buildName}"`, - ) + ); } - const consumer = await new SourceMapConsumer(rawSourceMap) + const consumer = await new SourceMapConsumer(rawSourceMap); - const hasContentsOfAllSources = consumer.hasContentsOfAllSources() + const hasContentsOfAllSources = consumer.hasContentsOfAllSources(); if (!hasContentsOfAllSources) { - console.warn('SourcemapValidator - missing content of some sources...') + console.warn('SourcemapValidator - missing content of some sources...'); } - console.log(` sampling from ${consumer.sources.length} files`) - let sampleCount = 0 - let valid = true + console.log(` sampling from ${consumer.sources.length} files`); + let sampleCount = 0; + let valid = true; - const buildLines = rawBuild.split('\n') - const targetString = 'new Error' + const buildLines = rawBuild.split('\n'); + const targetString = 'new Error'; // const targetString = 'null' - const matchesPerLine = buildLines.map((line) => indicesOf(targetString, line)) + const matchesPerLine = buildLines.map((line) => + indicesOf(targetString, line), + ); matchesPerLine.forEach((matchIndices, lineIndex) => { matchIndices.forEach((matchColumn) => { - sampleCount += 1 - const position = { line: lineIndex + 1, column: matchColumn } - const result = consumer.originalPositionFor(position) + sampleCount += 1; + const position = { line: lineIndex + 1, column: matchColumn }; + const result = consumer.originalPositionFor(position); // warn if source content is missing if (!result.source) { - valid = false + valid = false; console.warn( `!! missing source for position: ${JSON.stringify(position)}`, - ) + ); // const buildLine = buildLines[position.line - 1] - console.warn(` origin in build:`) - console.warn(` ${buildLines[position.line - 2]}`) - console.warn(`-> ${buildLines[position.line - 1]}`) - console.warn(` ${buildLines[position.line - 0]}`) - return + console.warn(` origin in build:`); + console.warn(` ${buildLines[position.line - 2]}`); + console.warn(`-> ${buildLines[position.line - 1]}`); + console.warn(` ${buildLines[position.line - 0]}`); + return; } - const sourceContent = consumer.sourceContentFor(result.source) - const sourceLines = sourceContent.split('\n') - const line = sourceLines[result.line - 1] + const sourceContent = consumer.sourceContentFor(result.source); + const sourceLines = sourceContent.split('\n'); + const line = sourceLines[result.line - 1]; // this sometimes includes the whole line though we tried to match somewhere in the middle - const portion = line.slice(result.column) - const isMaybeValid = portion.includes(targetString) + const portion = line.slice(result.column); + const isMaybeValid = portion.includes(targetString); if (!isMaybeValid) { - valid = false + valid = false; console.error( `Sourcemap seems invalid:\n${getFencedCode(result.source, line)}`, - ) + ); } - }) - }) - console.log(` checked ${sampleCount} samples`) - return valid + }); + }); + console.log(` checked ${sampleCount} samples`); + return valid; } -const CODE_FENCE_LENGTH = 80 -const TITLE_PADDING_LENGTH = 1 +const CODE_FENCE_LENGTH = 80; +const TITLE_PADDING_LENGTH = 1; function getFencedCode(filename, code) { const title = `${' '.repeat(TITLE_PADDING_LENGTH)}${filename}${' '.repeat( TITLE_PADDING_LENGTH, - )}` + )}`; const openingFenceLength = Math.max( CODE_FENCE_LENGTH - (filename.length + TITLE_PADDING_LENGTH * 2), 0, - ) - const startOpeningFenceLength = Math.floor(openingFenceLength / 2) - const endOpeningFenceLength = Math.ceil(openingFenceLength / 2) + ); + const startOpeningFenceLength = Math.floor(openingFenceLength / 2); + const endOpeningFenceLength = Math.ceil(openingFenceLength / 2); const openingFence = `${'='.repeat( startOpeningFenceLength, - )}${title}${'='.repeat(endOpeningFenceLength)}` - const closingFence = '='.repeat(CODE_FENCE_LENGTH) + )}${title}${'='.repeat(endOpeningFenceLength)}`; + const closingFence = '='.repeat(CODE_FENCE_LENGTH); - return `${openingFence}\n${code}\n${closingFence}\n` + return `${openingFence}\n${code}\n${closingFence}\n`; } function indicesOf(substring, string) { - const a = [] - let i = -1 + const a = []; + let i = -1; while ((i = string.indexOf(substring, i + 1)) >= 0) { - a.push(i) + a.push(i); } - return a + return a; } diff --git a/development/static-server.js b/development/static-server.js index 1690fc0e2..de994aec3 100644 --- a/development/static-server.js +++ b/development/static-server.js @@ -1,77 +1,79 @@ -const fs = require('fs') -const path = require('path') +const fs = require('fs'); +const path = require('path'); -const chalk = require('chalk') -const pify = require('pify') +const chalk = require('chalk'); +const pify = require('pify'); -const createStaticServer = require('./create-static-server') -const { parsePort } = require('./lib/parse-port') +const createStaticServer = require('./create-static-server'); +const { parsePort } = require('./lib/parse-port'); -const fsStat = pify(fs.stat) -const DEFAULT_PORT = 9080 +const fsStat = pify(fs.stat); +const DEFAULT_PORT = 9080; const onResponse = (request, response) => { if (response.statusCode >= 400) { - console.log(chalk`{gray '-->'} {red ${response.statusCode}} ${request.url}`) + console.log( + chalk`{gray '-->'} {red ${response.statusCode}} ${request.url}`, + ); } else if (response.statusCode >= 200 && response.statusCode < 300) { console.log( chalk`{gray '-->'} {green ${response.statusCode}} ${request.url}`, - ) + ); } else { console.log( chalk`{gray '-->'} {green.dim ${response.statusCode}} ${request.url}`, - ) + ); } -} +}; const onRequest = (request, response) => { - console.log(chalk`{gray '<--'} {blue [${request.method}]} ${request.url}`) - response.on('finish', () => onResponse(request, response)) -} + console.log(chalk`{gray '<--'} {blue [${request.method}]} ${request.url}`); + response.on('finish', () => onResponse(request, response)); +}; const startServer = ({ port, rootDirectory }) => { - const server = createStaticServer(rootDirectory) + const server = createStaticServer(rootDirectory); - server.on('request', onRequest) + server.on('request', onRequest); server.listen(port, () => { - console.log(`Running at http://localhost:${port}`) - }) -} + console.log(`Running at http://localhost:${port}`); + }); +}; const parseDirectoryArgument = async (pathString) => { - const resolvedPath = path.resolve(pathString) - const directoryStats = await fsStat(resolvedPath) + const resolvedPath = path.resolve(pathString); + const directoryStats = await fsStat(resolvedPath); if (!directoryStats.isDirectory()) { - throw new Error(`Invalid path '${pathString}'; must be a directory`) + throw new Error(`Invalid path '${pathString}'; must be a directory`); } - return resolvedPath -} + return resolvedPath; +}; const main = async () => { - const args = process.argv.slice(2) + const args = process.argv.slice(2); const options = { port: process.env.port || DEFAULT_PORT, rootDirectory: path.resolve('.'), - } + }; while (args.length) { if (/^(--port|-p)$/u.test(args[0])) { if (args[1] === undefined) { - throw new Error('Missing port argument') + throw new Error('Missing port argument'); } - options.port = parsePort(args[1]) - args.splice(0, 2) + options.port = parsePort(args[1]); + args.splice(0, 2); } else { - options.rootDirectory = await parseDirectoryArgument(args[0]) - args.splice(0, 1) + options.rootDirectory = await parseDirectoryArgument(args[0]); + args.splice(0, 1); } } - startServer(options) -} + startServer(options); +}; main().catch((error) => { - console.error(error) - process.exit(1) -}) + console.error(error); + process.exit(1); +}); diff --git a/development/verify-locale-strings.js b/development/verify-locale-strings.js index 7a0aa6281..d49b60095 100644 --- a/development/verify-locale-strings.js +++ b/development/verify-locale-strings.js @@ -21,238 +21,239 @@ // // ////////////////////////////////////////////////////////////////////////////// -const fs = require('fs') -const path = require('path') -const { promisify } = require('util') -const log = require('loglevel') -const matchAll = require('string.prototype.matchall').getPolyfill() -const localeIndex = require('../app/_locales/index.json') +const fs = require('fs'); +const path = require('path'); +const { promisify } = require('util'); +const log = require('loglevel'); +const matchAll = require('string.prototype.matchall').getPolyfill(); +const localeIndex = require('../app/_locales/index.json'); const { compareLocalesForMissingDescriptions, compareLocalesForMissingItems, getLocale, getLocalePath, -} = require('./lib/locales') +} = require('./lib/locales'); -const readdir = promisify(fs.readdir) -const readFile = promisify(fs.readFile) -const writeFile = promisify(fs.writeFile) +const readdir = promisify(fs.readdir); +const readFile = promisify(fs.readFile); +const writeFile = promisify(fs.writeFile); -log.setDefaultLevel('info') +log.setDefaultLevel('info'); -let fix = false -let specifiedLocale +let fix = false; +let specifiedLocale; for (const arg of process.argv.slice(2)) { if (arg === '--fix') { - fix = true + fix = true; } else if (arg === '--quiet') { - log.setLevel('error') + log.setLevel('error'); } else { - specifiedLocale = arg + specifiedLocale = arg; } } main().catch((error) => { - log.error(error) - process.exit(1) -}) + log.error(error); + process.exit(1); +}); async function main() { if (specifiedLocale) { - log.info(`Verifying selected locale "${specifiedLocale}":\n`) + log.info(`Verifying selected locale "${specifiedLocale}":\n`); const localeEntry = localeIndex.find( (localeMeta) => localeMeta.code === specifiedLocale, - ) + ); if (!localeEntry) { - throw new Error(`No localize entry found for ${specifiedLocale}`) + throw new Error(`No localize entry found for ${specifiedLocale}`); } const failed = specifiedLocale === 'en' ? await verifyEnglishLocale() - : await verifyLocale(specifiedLocale) + : await verifyLocale(specifiedLocale); if (failed) { - process.exit(1) + process.exit(1); } else { - console.log('No invalid entries!') + console.log('No invalid entries!'); } } else { - log.info('Verifying all locales:\n') - let failed = await verifyEnglishLocale(fix) + log.info('Verifying all locales:\n'); + let failed = await verifyEnglishLocale(fix); const localeCodes = localeIndex .filter((localeMeta) => localeMeta.code !== 'en') - .map((localeMeta) => localeMeta.code) + .map((localeMeta) => localeMeta.code); for (const code of localeCodes) { - const localeFailed = await verifyLocale(code, fix) - failed = failed || localeFailed + const localeFailed = await verifyLocale(code, fix); + failed = failed || localeFailed; } if (failed) { - process.exit(1) + process.exit(1); } else { - console.log('No invalid entries!') + console.log('No invalid entries!'); } } } async function writeLocale(code, locale) { try { - const localeFilePath = getLocalePath(code) + const localeFilePath = getLocalePath(code); return writeFile( localeFilePath, `${JSON.stringify(locale, null, 2)}\n`, 'utf8', - ) + ); } catch (e) { if (e.code === 'ENOENT') { - log.error('Locale file not found') + log.error('Locale file not found'); } else { - log.error(`Error writing your locale ("${code}") file: `, e) + log.error(`Error writing your locale ("${code}") file: `, e); } - process.exit(1) + process.exit(1); } } async function verifyLocale(code) { - const englishLocale = await getLocale('en') - const targetLocale = await getLocale(code) + const englishLocale = await getLocale('en'); + const targetLocale = await getLocale(code); const extraItems = compareLocalesForMissingItems({ base: targetLocale, subject: englishLocale, - }) + }); if (extraItems.length) { - console.log(`**${code}**: ${extraItems.length} unused messages`) - log.info('Extra items that should not be localized:') + console.log(`**${code}**: ${extraItems.length} unused messages`); + log.info('Extra items that should not be localized:'); extraItems.forEach(function (key) { - log.info(` - [ ] ${key}`) - }) + log.info(` - [ ] ${key}`); + }); } const missingDescriptions = compareLocalesForMissingDescriptions({ englishLocale, targetLocale, - }) + }); if (missingDescriptions.length) { console.log( `**${code}**: ${missingDescriptions.length} missing descriptions`, - ) - log.info('Messages with missing descriptions:') + ); + log.info('Messages with missing descriptions:'); missingDescriptions.forEach(function (key) { - log.info(` - [ ] ${key}`) - }) + log.info(` - [ ] ${key}`); + }); } if (extraItems.length > 0 || missingDescriptions.length > 0) { if (fix) { - const newLocale = { ...targetLocale } + const newLocale = { ...targetLocale }; for (const item of extraItems) { - delete newLocale[item] + delete newLocale[item]; } for (const message of Object.keys(englishLocale)) { if (englishLocale[message].description && targetLocale[message]) { - targetLocale[message].description = englishLocale[message].description + targetLocale[message].description = + englishLocale[message].description; } } - await writeLocale(code, newLocale) + await writeLocale(code, newLocale); } - return true + return true; } - return false + return false; } async function verifyEnglishLocale() { - const englishLocale = await getLocale('en') + const englishLocale = await getLocale('en'); const uiJSFiles = await findJavascriptFiles( path.resolve(__dirname, '..', 'ui'), - ) + ); const sharedJSFiles = await findJavascriptFiles( path.resolve(__dirname, '..', 'shared'), - ) + ); - const javascriptFiles = sharedJSFiles.concat(uiJSFiles) + const javascriptFiles = sharedJSFiles.concat(uiJSFiles); // match "t(`...`)" because constructing message keys from template strings // prevents this script from finding the messages, and then inappropriately // deletes them - const templateStringRegex = /\bt\(`.*`\)/gu - const templateUsage = [] + const templateStringRegex = /\bt\(`.*`\)/gu; + const templateUsage = []; // match the keys from the locale file - const keyRegex = /'(\w+)'|"(\w+)"/gu - const usedMessages = new Set() + const keyRegex = /'(\w+)'|"(\w+)"/gu; + const usedMessages = new Set(); for await (const fileContents of getFileContents(javascriptFiles)) { for (const match of matchAll.call(fileContents, keyRegex)) { - usedMessages.add(match[1] || match[2]) + usedMessages.add(match[1] || match[2]); } - const templateMatches = fileContents.match(templateStringRegex) + const templateMatches = fileContents.match(templateStringRegex); if (templateMatches) { // concat doesn't work here for some reason - templateMatches.forEach((match) => templateUsage.push(match)) + templateMatches.forEach((match) => templateUsage.push(match)); } } // never consider these messages as unused - const messageExceptions = ['appName', 'appDescription'] + const messageExceptions = ['appName', 'appDescription']; - const englishMessages = Object.keys(englishLocale) + const englishMessages = Object.keys(englishLocale); const unusedMessages = englishMessages.filter( (message) => !messageExceptions.includes(message) && !usedMessages.has(message), - ) + ); if (unusedMessages.length) { - console.log(`**en**: ${unusedMessages.length} unused messages`) - log.info(`Messages not present in UI:`) + console.log(`**en**: ${unusedMessages.length} unused messages`); + log.info(`Messages not present in UI:`); unusedMessages.forEach(function (key) { - log.info(` - [ ] ${key}`) - }) + log.info(` - [ ] ${key}`); + }); } if (templateUsage.length) { - log.info(`Forbidden use of template strings in 't' function:`) + log.info(`Forbidden use of template strings in 't' function:`); templateUsage.forEach(function (occurrence) { - log.info(` - ${occurrence}`) - }) + log.info(` - ${occurrence}`); + }); } if (!unusedMessages.length && !templateUsage.length) { - return false // failed === false + return false; // failed === false } if (unusedMessages.length > 0 && fix) { - const newLocale = { ...englishLocale } + const newLocale = { ...englishLocale }; for (const key of unusedMessages) { - delete newLocale[key] + delete newLocale[key]; } - await writeLocale('en', newLocale) + await writeLocale('en', newLocale); } - return true // failed === true + return true; // failed === true } async function findJavascriptFiles(rootDir) { - const javascriptFiles = [] - const contents = await readdir(rootDir, { withFileTypes: true }) + const javascriptFiles = []; + const contents = await readdir(rootDir, { withFileTypes: true }); for (const file of contents) { if (file.isDirectory()) { javascriptFiles.push( ...(await findJavascriptFiles(path.join(rootDir, file.name))), - ) + ); } else if (file.isFile() && file.name.endsWith('.js')) { - javascriptFiles.push(path.join(rootDir, file.name)) + javascriptFiles.push(path.join(rootDir, file.name)); } } - return javascriptFiles + return javascriptFiles; } async function* getFileContents(filenames) { for (const filename of filenames) { - yield readFile(filename, 'utf8') + yield readFile(filename, 'utf8'); } } diff --git a/nyc.config.js b/nyc.config.js index 8902e0571..ee1e2055a 100644 --- a/nyc.config.js +++ b/nyc.config.js @@ -3,4 +3,4 @@ module.exports = { lines: 95, functions: 95, statements: 95, -} +}; diff --git a/package.json b/package.json index cb6ae4c97..fde50dfbb 100644 --- a/package.json +++ b/package.json @@ -192,7 +192,7 @@ "@babel/preset-react": "^7.0.0", "@babel/register": "^7.5.5", "@lavamoat/allow-scripts": "^1.0.3", - "@metamask/eslint-config": "^4.1.0", + "@metamask/eslint-config": "^5.0.0", "@metamask/forwarder": "^1.1.0", "@metamask/test-dapp": "^4.0.1", "@sentry/cli": "^1.58.0", diff --git a/shared/constants/alerts.js b/shared/constants/alerts.js index 4b2bed147..99ef70f4c 100644 --- a/shared/constants/alerts.js +++ b/shared/constants/alerts.js @@ -2,7 +2,7 @@ export const ALERT_TYPES = { unconnectedAccount: 'unconnectedAccount', web3ShimUsage: 'web3ShimUsage', invalidCustomNetwork: 'invalidCustomNetwork', -} +}; /** * Alerts that can be enabled or disabled by the user. @@ -10,9 +10,9 @@ export const ALERT_TYPES = { export const TOGGLEABLE_ALERT_TYPES = [ ALERT_TYPES.unconnectedAccount, ALERT_TYPES.web3ShimUsage, -] +]; export const WEB3_SHIM_USAGE_ALERT_STATES = { RECORDED: 1, DISMISSED: 2, -} +}; diff --git a/shared/constants/app.js b/shared/constants/app.js index 90e4726b0..d0369cd82 100644 --- a/shared/constants/app.js +++ b/shared/constants/app.js @@ -6,16 +6,16 @@ * background - The background process that powers the extension * @typedef {'popup' | 'notification' | 'fullscreen' | 'background'} EnvironmentType */ -export const ENVIRONMENT_TYPE_POPUP = 'popup' -export const ENVIRONMENT_TYPE_NOTIFICATION = 'notification' -export const ENVIRONMENT_TYPE_FULLSCREEN = 'fullscreen' -export const ENVIRONMENT_TYPE_BACKGROUND = 'background' +export const ENVIRONMENT_TYPE_POPUP = 'popup'; +export const ENVIRONMENT_TYPE_NOTIFICATION = 'notification'; +export const ENVIRONMENT_TYPE_FULLSCREEN = 'fullscreen'; +export const ENVIRONMENT_TYPE_BACKGROUND = 'background'; -export const PLATFORM_BRAVE = 'Brave' -export const PLATFORM_CHROME = 'Chrome' -export const PLATFORM_EDGE = 'Edge' -export const PLATFORM_FIREFOX = 'Firefox' -export const PLATFORM_OPERA = 'Opera' +export const PLATFORM_BRAVE = 'Brave'; +export const PLATFORM_CHROME = 'Chrome'; +export const PLATFORM_EDGE = 'Edge'; +export const PLATFORM_FIREFOX = 'Firefox'; +export const PLATFORM_OPERA = 'Opera'; export const MESSAGE_TYPE = { ETH_DECRYPT: 'eth_decrypt', @@ -27,4 +27,4 @@ export const MESSAGE_TYPE = { PERSONAL_SIGN: 'personal_sign', WATCH_ASSET: 'wallet_watchAsset', WATCH_ASSET_LEGACY: 'metamask_watchAsset', -} +}; diff --git a/shared/constants/metametrics.js b/shared/constants/metametrics.js index edb37a2a1..ab71141bc 100644 --- a/shared/constants/metametrics.js +++ b/shared/constants/metametrics.js @@ -110,7 +110,7 @@ * the page view */ -export const METAMETRICS_ANONYMOUS_ID = '0x0000000000000000' +export const METAMETRICS_ANONYMOUS_ID = '0x0000000000000000'; /** * This object is used to identify events that are triggered by the background @@ -121,7 +121,7 @@ export const METAMETRICS_BACKGROUND_PAGE_OBJECT = { path: '/background-process', title: 'Background Process', url: '/background-process', -} +}; /** * @typedef {Object} SegmentInterface diff --git a/shared/constants/network.js b/shared/constants/network.js index 7a0f6daf0..d3a53e519 100644 --- a/shared/constants/network.js +++ b/shared/constants/network.js @@ -1,35 +1,35 @@ -export const ROPSTEN = 'ropsten' -export const RINKEBY = 'rinkeby' -export const KOVAN = 'kovan' -export const MAINNET = 'mainnet' -export const GOERLI = 'goerli' -export const NETWORK_TYPE_RPC = 'rpc' +export const ROPSTEN = 'ropsten'; +export const RINKEBY = 'rinkeby'; +export const KOVAN = 'kovan'; +export const MAINNET = 'mainnet'; +export const GOERLI = 'goerli'; +export const NETWORK_TYPE_RPC = 'rpc'; -export const MAINNET_NETWORK_ID = '1' -export const ROPSTEN_NETWORK_ID = '3' -export const RINKEBY_NETWORK_ID = '4' -export const GOERLI_NETWORK_ID = '5' -export const KOVAN_NETWORK_ID = '42' +export const MAINNET_NETWORK_ID = '1'; +export const ROPSTEN_NETWORK_ID = '3'; +export const RINKEBY_NETWORK_ID = '4'; +export const GOERLI_NETWORK_ID = '5'; +export const KOVAN_NETWORK_ID = '42'; -export const MAINNET_CHAIN_ID = '0x1' -export const ROPSTEN_CHAIN_ID = '0x3' -export const RINKEBY_CHAIN_ID = '0x4' -export const GOERLI_CHAIN_ID = '0x5' -export const KOVAN_CHAIN_ID = '0x2a' +export const MAINNET_CHAIN_ID = '0x1'; +export const ROPSTEN_CHAIN_ID = '0x3'; +export const RINKEBY_CHAIN_ID = '0x4'; +export const GOERLI_CHAIN_ID = '0x5'; +export const KOVAN_CHAIN_ID = '0x2a'; /** * The largest possible chain ID we can handle. * Explanation: https://gist.github.com/rekmarks/a47bd5f2525936c4b8eee31a16345553 */ -export const MAX_SAFE_CHAIN_ID = 4503599627370476 +export const MAX_SAFE_CHAIN_ID = 4503599627370476; -export const ROPSTEN_DISPLAY_NAME = 'Ropsten' -export const RINKEBY_DISPLAY_NAME = 'Rinkeby' -export const KOVAN_DISPLAY_NAME = 'Kovan' -export const MAINNET_DISPLAY_NAME = 'Ethereum Mainnet' -export const GOERLI_DISPLAY_NAME = 'Goerli' +export const ROPSTEN_DISPLAY_NAME = 'Ropsten'; +export const RINKEBY_DISPLAY_NAME = 'Rinkeby'; +export const KOVAN_DISPLAY_NAME = 'Kovan'; +export const MAINNET_DISPLAY_NAME = 'Ethereum Mainnet'; +export const GOERLI_DISPLAY_NAME = 'Goerli'; -export const INFURA_PROVIDER_TYPES = [ROPSTEN, RINKEBY, KOVAN, MAINNET, GOERLI] +export const INFURA_PROVIDER_TYPES = [ROPSTEN, RINKEBY, KOVAN, MAINNET, GOERLI]; export const NETWORK_TYPE_TO_ID_MAP = { [ROPSTEN]: { networkId: ROPSTEN_NETWORK_ID, chainId: ROPSTEN_CHAIN_ID }, @@ -37,7 +37,7 @@ export const NETWORK_TYPE_TO_ID_MAP = { [KOVAN]: { networkId: KOVAN_NETWORK_ID, chainId: KOVAN_CHAIN_ID }, [GOERLI]: { networkId: GOERLI_NETWORK_ID, chainId: GOERLI_CHAIN_ID }, [MAINNET]: { networkId: MAINNET_NETWORK_ID, chainId: MAINNET_CHAIN_ID }, -} +}; export const NETWORK_TO_NAME_MAP = { [ROPSTEN]: ROPSTEN_DISPLAY_NAME, @@ -57,18 +57,18 @@ export const NETWORK_TO_NAME_MAP = { [KOVAN_CHAIN_ID]: KOVAN_DISPLAY_NAME, [GOERLI_CHAIN_ID]: GOERLI_DISPLAY_NAME, [MAINNET_CHAIN_ID]: MAINNET_DISPLAY_NAME, -} +}; export const CHAIN_ID_TO_TYPE_MAP = Object.entries( NETWORK_TYPE_TO_ID_MAP, ).reduce((chainIdToTypeMap, [networkType, { chainId }]) => { - chainIdToTypeMap[chainId] = networkType - return chainIdToTypeMap -}, {}) + chainIdToTypeMap[chainId] = networkType; + return chainIdToTypeMap; +}, {}); export const CHAIN_ID_TO_NETWORK_ID_MAP = Object.values( NETWORK_TYPE_TO_ID_MAP, ).reduce((chainIdToNetworkIdMap, { chainId, networkId }) => { - chainIdToNetworkIdMap[chainId] = networkId - return chainIdToNetworkIdMap -}, {}) + chainIdToNetworkIdMap[chainId] = networkId; + return chainIdToNetworkIdMap; +}, {}); diff --git a/shared/constants/permissions.js b/shared/constants/permissions.js index f396fbeba..443ba2c29 100644 --- a/shared/constants/permissions.js +++ b/shared/constants/permissions.js @@ -1,4 +1,4 @@ export const CAVEAT_NAMES = { exposedAccounts: 'exposedAccounts', primaryAccountOnly: 'primaryAccountOnly', -} +}; diff --git a/shared/constants/tokens.js b/shared/constants/tokens.js index 27b240f7b..1772cbf33 100644 --- a/shared/constants/tokens.js +++ b/shared/constants/tokens.js @@ -1,4 +1,4 @@ -import contractMap from '@metamask/contract-metadata' +import contractMap from '@metamask/contract-metadata'; /** * A normalized list of addresses exported as part of the contractMap in @@ -7,4 +7,4 @@ import contractMap from '@metamask/contract-metadata' */ export const LISTED_CONTRACT_ADDRESSES = Object.keys( contractMap, -).map((address) => address.toLowerCase()) +).map((address) => address.toLowerCase()); diff --git a/shared/constants/transaction.js b/shared/constants/transaction.js index cce09fb8d..833463a60 100644 --- a/shared/constants/transaction.js +++ b/shared/constants/transaction.js @@ -19,7 +19,7 @@ export const TRANSACTION_TYPES = { STANDARD: 'standard', CANCEL: 'cancel', RETRY: 'retry', -} +}; /** * Transaction Status is a mix of Ethereum and MetaMask terminology, used internally @@ -51,7 +51,7 @@ export const TRANSACTION_STATUSES = { FAILED: 'failed', DROPPED: 'dropped', CONFIRMED: 'confirmed', -} +}; /** * @typedef {Object} TransactionCategories @@ -90,7 +90,7 @@ export const TRANSACTION_CATEGORIES = { DEPLOY_CONTRACT: 'contractDeployment', SWAP: 'swap', SWAP_APPROVAL: 'swapApproval', -} +}; /** * Transaction Group Status is a MetaMask construct to track the status of groups @@ -109,7 +109,7 @@ export const TRANSACTION_CATEGORIES = { export const TRANSACTION_GROUP_STATUSES = { CANCELLED: 'cancelled', PENDING: 'pending', -} +}; /** * Transaction Group Category is a MetaMask construct to categorize the intent @@ -144,4 +144,4 @@ export const TRANSACTION_GROUP_CATEGORIES = { APPROVAL: 'approval', SIGNATURE_REQUEST: 'signature-request', SWAP: 'swap', -} +}; diff --git a/shared/modules/fetch-with-timeout.js b/shared/modules/fetch-with-timeout.js index e97ae3402..b12e8cba5 100644 --- a/shared/modules/fetch-with-timeout.js +++ b/shared/modules/fetch-with-timeout.js @@ -1,29 +1,29 @@ -import { memoize } from 'lodash' +import { memoize } from 'lodash'; const getFetchWithTimeout = memoize((timeout) => { if (!Number.isInteger(timeout) || timeout < 1) { - throw new Error('Must specify positive integer timeout.') + throw new Error('Must specify positive integer timeout.'); } return async function _fetch(url, opts) { - const abortController = new window.AbortController() - const { signal } = abortController + const abortController = new window.AbortController(); + const { signal } = abortController; const f = window.fetch(url, { ...opts, signal, - }) + }); - const timer = setTimeout(() => abortController.abort(), timeout) + const timer = setTimeout(() => abortController.abort(), timeout); try { - const res = await f - clearTimeout(timer) - return res + const res = await f; + clearTimeout(timer); + return res; } catch (e) { - clearTimeout(timer) - throw e + clearTimeout(timer); + throw e; } - } -}) + }; +}); -export default getFetchWithTimeout +export default getFetchWithTimeout; diff --git a/shared/modules/utils.js b/shared/modules/utils.js index b9778b40b..7d72d18f7 100644 --- a/shared/modules/utils.js +++ b/shared/modules/utils.js @@ -1,4 +1,4 @@ -import { MAX_SAFE_CHAIN_ID } from '../constants/network' +import { MAX_SAFE_CHAIN_ID } from '../constants/network'; /** * Checks whether the given number primitive chain ID is safe. @@ -11,7 +11,7 @@ import { MAX_SAFE_CHAIN_ID } from '../constants/network' export function isSafeChainId(chainId) { return ( Number.isSafeInteger(chainId) && chainId > 0 && chainId <= MAX_SAFE_CHAIN_ID - ) + ); } /** @@ -24,7 +24,7 @@ export function isSafeChainId(chainId) { */ export function isPrefixedFormattedHexString(value) { if (typeof value !== 'string') { - return false + return false; } - return /^0x[1-9a-f]+[0-9a-f]*$/iu.test(value) + return /^0x[1-9a-f]+[0-9a-f]*$/iu.test(value); } diff --git a/stylelint.config.js b/stylelint.config.js index e73223863..b27e13ec9 100644 --- a/stylelint.config.js +++ b/stylelint.config.js @@ -131,4 +131,4 @@ module.exports = { // 'max-nesting-depth': 3, 'no-unknown-animations': true, }, -} +}; diff --git a/test/e2e/address-book.spec.js b/test/e2e/address-book.spec.js index 3d0e2712b..4ac0d1722 100644 --- a/test/e2e/address-book.spec.js +++ b/test/e2e/address-book.spec.js @@ -1,21 +1,21 @@ -const assert = require('assert') -const { By, until } = require('selenium-webdriver') +const assert = require('assert'); +const { By, until } = require('selenium-webdriver'); -const enLocaleMessages = require('../../app/_locales/en/messages.json') -const { tinyDelayMs, regularDelayMs, largeDelayMs } = require('./helpers') -const { buildWebDriver } = require('./webdriver') -const Ganache = require('./ganache') +const enLocaleMessages = require('../../app/_locales/en/messages.json'); +const { tinyDelayMs, regularDelayMs, largeDelayMs } = require('./helpers'); +const { buildWebDriver } = require('./webdriver'); +const Ganache = require('./ganache'); -const ganacheServer = new Ganache() +const ganacheServer = new Ganache(); describe('MetaMask', function () { - let driver + let driver; const testSeedPhrase = - 'forum vessel pink push lonely enact gentle tail admit parrot grunt dress' + 'forum vessel pink push lonely enact gentle tail admit parrot grunt dress'; - this.timeout(0) - this.bail(true) + this.timeout(0); + this.bail(true); before(async function () { await ganacheServer.start({ @@ -26,279 +26,283 @@ describe('MetaMask', function () { balance: 25000000000000000000, }, ], - }) - const result = await buildWebDriver() - driver = result.driver - await driver.navigate() - }) + }); + const result = await buildWebDriver(); + driver = result.driver; + await driver.navigate(); + }); afterEach(async function () { if (process.env.SELENIUM_BROWSER === 'chrome') { - const errors = await driver.checkBrowserForConsoleErrors() + const errors = await driver.checkBrowserForConsoleErrors(); if (errors.length) { - const errorReports = errors.map((err) => err.message) + const errorReports = errors.map((err) => err.message); const errorMessage = `Errors found in browser console:\n${errorReports.join( '\n', - )}` - console.error(new Error(errorMessage)) + )}`; + console.error(new Error(errorMessage)); } } if (this.currentTest.state === 'failed') { - await driver.verboseReportOnFailure(this.currentTest.title) + await driver.verboseReportOnFailure(this.currentTest.title); } - }) + }); after(async function () { - await ganacheServer.quit() - await driver.quit() - }) + await ganacheServer.quit(); + await driver.quit(); + }); describe('Going through the first time flow', function () { it('clicks the continue button on the welcome screen', async function () { - await driver.findElement(By.css('.welcome-page__header')) + await driver.findElement(By.css('.welcome-page__header')); await driver.clickElement( By.xpath( `//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`, ), - ) - await driver.delay(largeDelayMs) - }) + ); + await driver.delay(largeDelayMs); + }); it('clicks the "Create New Wallet" option', async function () { await driver.clickElement( By.xpath(`//button[contains(text(), 'Create a Wallet')]`), - ) - await driver.delay(largeDelayMs) - }) + ); + await driver.delay(largeDelayMs); + }); it('clicks the "No thanks" option on the metametrics opt-in screen', async function () { - await driver.clickElement(By.css('.btn-default')) - await driver.delay(largeDelayMs) - }) + await driver.clickElement(By.css('.btn-default')); + await driver.delay(largeDelayMs); + }); it('accepts a secure password', async function () { const passwordBox = await driver.findElement( By.css('.first-time-flow__form #create-password'), - ) + ); const passwordBoxConfirm = await driver.findElement( By.css('.first-time-flow__form #confirm-password'), - ) + ); - await passwordBox.sendKeys('correct horse battery staple') - await passwordBoxConfirm.sendKeys('correct horse battery staple') + await passwordBox.sendKeys('correct horse battery staple'); + await passwordBoxConfirm.sendKeys('correct horse battery staple'); - await driver.clickElement(By.css('.first-time-flow__checkbox')) - await driver.clickElement(By.css('.first-time-flow__form button')) - await driver.delay(regularDelayMs) - }) + await driver.clickElement(By.css('.first-time-flow__checkbox')); + await driver.clickElement(By.css('.first-time-flow__form button')); + await driver.delay(regularDelayMs); + }); - let seedPhrase + let seedPhrase; it('reveals the seed phrase', async function () { const byRevealButton = By.css( '.reveal-seed-phrase__secret-blocker .reveal-seed-phrase__reveal-button', - ) - await driver.clickElement(byRevealButton) - await driver.delay(regularDelayMs) + ); + await driver.clickElement(byRevealButton); + await driver.delay(regularDelayMs); const revealedSeedPhrase = await driver.findElement( By.css('.reveal-seed-phrase__secret-words'), - ) - seedPhrase = await revealedSeedPhrase.getText() - assert.equal(seedPhrase.split(' ').length, 12) - await driver.delay(regularDelayMs) + ); + seedPhrase = await revealedSeedPhrase.getText(); + assert.equal(seedPhrase.split(' ').length, 12); + await driver.delay(regularDelayMs); await driver.clickElement( By.xpath( `//button[contains(text(), '${enLocaleMessages.next.message}')]`, ), - ) - await driver.delay(regularDelayMs) - }) + ); + await driver.delay(regularDelayMs); + }); async function clickWordAndWait(word) { await driver.clickElement( By.css( `[data-testid="seed-phrase-sorted"] [data-testid="draggable-seed-${word}"]`, ), - ) - await driver.delay(tinyDelayMs) + ); + await driver.delay(tinyDelayMs); } it('can retype the seed phrase', async function () { - const words = seedPhrase.split(' ') + const words = seedPhrase.split(' '); for (const word of words) { - await clickWordAndWait(word) + await clickWordAndWait(word); } await driver.clickElement( By.xpath(`//button[contains(text(), 'Confirm')]`), - ) - await driver.delay(regularDelayMs) - }) + ); + await driver.delay(regularDelayMs); + }); it('clicks through the success screen', async function () { await driver.findElement( By.xpath(`//div[contains(text(), 'Congratulations')]`), - ) + ); await driver.clickElement( By.xpath( `//button[contains(text(), '${enLocaleMessages.endOfFlowMessage10.message}')]`, ), - ) - await driver.delay(regularDelayMs) - }) - }) + ); + await driver.delay(regularDelayMs); + }); + }); describe('Import seed phrase', function () { it('logs out of the vault', async function () { - await driver.clickElement(By.css('.account-menu__icon')) - await driver.delay(regularDelayMs) + await driver.clickElement(By.css('.account-menu__icon')); + await driver.delay(regularDelayMs); const lockButton = await driver.findClickableElement( By.css('.account-menu__lock-button'), - ) - assert.equal(await lockButton.getText(), 'Lock') - await lockButton.click() - await driver.delay(regularDelayMs) - }) + ); + assert.equal(await lockButton.getText(), 'Lock'); + await lockButton.click(); + await driver.delay(regularDelayMs); + }); it('imports seed phrase', async function () { const restoreSeedLink = await driver.findClickableElement( By.css('.unlock-page__link--import'), - ) + ); assert.equal( await restoreSeedLink.getText(), 'Import using account seed phrase', - ) - await restoreSeedLink.click() - await driver.delay(regularDelayMs) + ); + await restoreSeedLink.click(); + await driver.delay(regularDelayMs); - await driver.clickElement(By.css('.import-account__checkbox-container')) + await driver.clickElement(By.css('.import-account__checkbox-container')); - const seedTextArea = await driver.findElement(By.css('textarea')) - await seedTextArea.sendKeys(testSeedPhrase) - await driver.delay(regularDelayMs) + const seedTextArea = await driver.findElement(By.css('textarea')); + await seedTextArea.sendKeys(testSeedPhrase); + await driver.delay(regularDelayMs); - const passwordInputs = await driver.findElements(By.css('input')) - await driver.delay(regularDelayMs) + const passwordInputs = await driver.findElements(By.css('input')); + await driver.delay(regularDelayMs); - await passwordInputs[0].sendKeys('correct horse battery staple') - await passwordInputs[1].sendKeys('correct horse battery staple') + await passwordInputs[0].sendKeys('correct horse battery staple'); + await passwordInputs[1].sendKeys('correct horse battery staple'); await driver.clickElement( By.xpath( `//button[contains(text(), '${enLocaleMessages.restore.message}')]`, ), - ) - await driver.delay(regularDelayMs) - }) + ); + await driver.delay(regularDelayMs); + }); it('balance renders', async function () { const balance = await driver.findElement( By.css('[data-testid="wallet-balance"] .list-item__heading'), - ) - await driver.wait(until.elementTextMatches(balance, /25\s*ETH/u)) - await driver.delay(regularDelayMs) - }) - }) + ); + await driver.wait(until.elementTextMatches(balance, /25\s*ETH/u)); + await driver.delay(regularDelayMs); + }); + }); describe('Adds an entry to the address book and sends eth to that address', function () { it('starts a send transaction', async function () { - await driver.clickElement(By.css('[data-testid="eth-overview-send"]')) - await driver.delay(regularDelayMs) + await driver.clickElement(By.css('[data-testid="eth-overview-send"]')); + await driver.delay(regularDelayMs); const inputAddress = await driver.findElement( By.css('input[placeholder="Search, public address (0x), or ENS"]'), - ) - await inputAddress.sendKeys('0x2f318C334780961FB129D2a6c30D0763d9a5C970') - await driver.delay(regularDelayMs) + ); + await inputAddress.sendKeys('0x2f318C334780961FB129D2a6c30D0763d9a5C970'); + await driver.delay(regularDelayMs); - await driver.clickElement(By.css('.dialog.send__dialog.dialog--message')) + await driver.clickElement(By.css('.dialog.send__dialog.dialog--message')); const addressBookAddModal = await driver.findElement( By.css('span .modal'), - ) - await driver.findElement(By.css('.add-to-address-book-modal')) + ); + await driver.findElement(By.css('.add-to-address-book-modal')); const addressBookInput = await driver.findElement( By.css('.add-to-address-book-modal__input'), - ) - await addressBookInput.sendKeys('Test Name 1') - await driver.delay(tinyDelayMs) + ); + await addressBookInput.sendKeys('Test Name 1'); + await driver.delay(tinyDelayMs); await driver.clickElement( By.css('.add-to-address-book-modal__footer .btn-primary'), - ) + ); - await driver.wait(until.stalenessOf(addressBookAddModal)) + await driver.wait(until.stalenessOf(addressBookAddModal)); - const inputAmount = await driver.findElement(By.css('.unit-input__input')) - await inputAmount.sendKeys('1') + const inputAmount = await driver.findElement( + By.css('.unit-input__input'), + ); + await inputAmount.sendKeys('1'); - const inputValue = await inputAmount.getAttribute('value') - assert.equal(inputValue, '1') - await driver.delay(regularDelayMs) + const inputValue = await inputAmount.getAttribute('value'); + assert.equal(inputValue, '1'); + await driver.delay(regularDelayMs); // Continue to next screen - await driver.clickElement(By.xpath(`//button[contains(text(), 'Next')]`)) - await driver.delay(regularDelayMs) - }) + await driver.clickElement(By.xpath(`//button[contains(text(), 'Next')]`)); + await driver.delay(regularDelayMs); + }); it('confirms the transaction', async function () { await driver.clickElement( By.xpath(`//button[contains(text(), 'Confirm')]`), - ) - await driver.delay(largeDelayMs * 2) - }) + ); + await driver.delay(largeDelayMs * 2); + }); it('finds the transaction in the transactions list', async function () { - await driver.clickElement(By.css('[data-testid="home__activity-tab"]')) + await driver.clickElement(By.css('[data-testid="home__activity-tab"]')); await driver.wait(async () => { const confirmedTxes = await driver.findElements( By.css( '.transaction-list__completed-transactions .transaction-list-item', ), - ) - return confirmedTxes.length === 1 - }, 10000) + ); + return confirmedTxes.length === 1; + }, 10000); const txValues = await driver.findElement( By.css('.transaction-list-item__primary-currency'), - ) - await driver.wait(until.elementTextMatches(txValues, /-1\s*ETH/u), 10000) - }) - }) + ); + await driver.wait(until.elementTextMatches(txValues, /-1\s*ETH/u), 10000); + }); + }); describe('Sends to an address book entry', function () { it('starts a send transaction by clicking address book entry', async function () { - await driver.clickElement(By.css('[data-testid="eth-overview-send"]')) - await driver.delay(regularDelayMs) + await driver.clickElement(By.css('[data-testid="eth-overview-send"]')); + await driver.delay(regularDelayMs); const recipientRowTitle = await driver.findElement( By.css('.send__select-recipient-wrapper__group-item__title'), - ) - const recipientRowTitleString = await recipientRowTitle.getText() - assert.equal(recipientRowTitleString, 'Test Name 1') + ); + const recipientRowTitleString = await recipientRowTitle.getText(); + assert.equal(recipientRowTitleString, 'Test Name 1'); await driver.clickElement( By.css('.send__select-recipient-wrapper__group-item'), - ) + ); - await driver.delay(regularDelayMs) - const inputAmount = await driver.findElement(By.css('.unit-input__input')) - await inputAmount.sendKeys('2') - await driver.delay(regularDelayMs) + await driver.delay(regularDelayMs); + const inputAmount = await driver.findElement( + By.css('.unit-input__input'), + ); + await inputAmount.sendKeys('2'); + await driver.delay(regularDelayMs); // Continue to next screen - await driver.clickElement(By.xpath(`//button[contains(text(), 'Next')]`)) - await driver.delay(regularDelayMs) - }) + await driver.clickElement(By.xpath(`//button[contains(text(), 'Next')]`)); + await driver.delay(regularDelayMs); + }); it('confirms the transaction', async function () { await driver.clickElement( By.xpath(`//button[contains(text(), 'Confirm')]`), - ) - await driver.delay(largeDelayMs * 2) - }) + ); + await driver.delay(largeDelayMs * 2); + }); it('finds the transaction in the transactions list', async function () { await driver.wait(async () => { @@ -306,14 +310,14 @@ describe('MetaMask', function () { By.css( '.transaction-list__completed-transactions .transaction-list-item', ), - ) - return confirmedTxes.length === 2 - }, 10000) + ); + return confirmedTxes.length === 2; + }, 10000); const txValues = await driver.findElement( By.css('.transaction-list-item__primary-currency'), - ) - await driver.wait(until.elementTextMatches(txValues, /-2\s*ETH/u), 10000) - }) - }) -}) + ); + await driver.wait(until.elementTextMatches(txValues, /-2\s*ETH/u), 10000); + }); + }); +}); diff --git a/test/e2e/benchmark.js b/test/e2e/benchmark.js index a364ed62a..2f02d93cc 100644 --- a/test/e2e/benchmark.js +++ b/test/e2e/benchmark.js @@ -1,66 +1,66 @@ #!/usr/bin/env node -const path = require('path') -const { promises: fs, constants: fsConstants } = require('fs') -const ttest = require('ttest') -const { By, Key } = require('selenium-webdriver') -const { withFixtures } = require('./helpers') -const { PAGES } = require('./webdriver/driver') +const path = require('path'); +const { promises: fs, constants: fsConstants } = require('fs'); +const ttest = require('ttest'); +const { By, Key } = require('selenium-webdriver'); +const { withFixtures } = require('./helpers'); +const { PAGES } = require('./webdriver/driver'); -const DEFAULT_NUM_SAMPLES = 20 -const ALL_PAGES = Object.values(PAGES) +const DEFAULT_NUM_SAMPLES = 20; +const ALL_PAGES = Object.values(PAGES); async function measurePage(pageName) { - let metrics + let metrics; await withFixtures({ fixtures: 'imported-account' }, async ({ driver }) => { - await driver.navigate() - const passwordField = await driver.findElement(By.css('#password')) - await passwordField.sendKeys('correct horse battery staple') - await passwordField.sendKeys(Key.ENTER) - await driver.findElement(By.css('.selected-account__name')) - await driver.navigate(pageName) - await driver.delay(1000) - metrics = await driver.collectMetrics() - }) - return metrics + await driver.navigate(); + const passwordField = await driver.findElement(By.css('#password')); + await passwordField.sendKeys('correct horse battery staple'); + await passwordField.sendKeys(Key.ENTER); + await driver.findElement(By.css('.selected-account__name')); + await driver.navigate(pageName); + await driver.delay(1000); + metrics = await driver.collectMetrics(); + }); + return metrics; } function calculateResult(calc) { return (result) => { - const calculatedResult = {} + const calculatedResult = {}; for (const key of Object.keys(result)) { - calculatedResult[key] = calc(result[key]) + calculatedResult[key] = calc(result[key]); } - return calculatedResult - } + return calculatedResult; + }; } -const calculateSum = (array) => array.reduce((sum, val) => sum + val) -const calculateAverage = (array) => calculateSum(array) / array.length -const minResult = calculateResult((array) => Math.min(...array)) -const maxResult = calculateResult((array) => Math.max(...array)) -const averageResult = calculateResult((array) => calculateAverage(array)) +const calculateSum = (array) => array.reduce((sum, val) => sum + val); +const calculateAverage = (array) => calculateSum(array) / array.length; +const minResult = calculateResult((array) => Math.min(...array)); +const maxResult = calculateResult((array) => Math.max(...array)); +const averageResult = calculateResult((array) => calculateAverage(array)); const standardDeviationResult = calculateResult((array) => { - const average = calculateAverage(array) - const squareDiffs = array.map((value) => Math.pow(value - average, 2)) - return Math.sqrt(calculateAverage(squareDiffs)) -}) + const average = calculateAverage(array); + const squareDiffs = array.map((value) => Math.pow(value - average, 2)); + return Math.sqrt(calculateAverage(squareDiffs)); +}); // 95% margin of error calculated using Student's t-distribution const calculateMarginOfError = (array) => - ttest(array).confidence()[1] - calculateAverage(array) + ttest(array).confidence()[1] - calculateAverage(array); const marginOfErrorResult = calculateResult((array) => calculateMarginOfError(array), -) +); async function profilePageLoad(pages, numSamples) { - const results = {} + const results = {}; for (const pageName of pages) { - const runResults = [] + const runResults = []; for (let i = 0; i < numSamples; i += 1) { - runResults.push(await measurePage(pageName)) + runResults.push(await measurePage(pageName)); } if (runResults.some((result) => result.navigation.lenth > 1)) { - throw new Error(`Multiple navigations not supported`) + throw new Error(`Multiple navigations not supported`); } else if ( runResults.some((result) => result.navigation[0].type !== 'navigate') ) { @@ -69,7 +69,7 @@ async function profilePageLoad(pages, numSamples) { runResults.find((result) => result.navigation[0].type !== 'navigate') .navigation[0].type } not supported`, - ) + ); } const result = { @@ -85,7 +85,7 @@ async function profilePageLoad(pages, numSamples) { (metrics) => metrics.navigation[0] && metrics.navigation[0].domInteractive, ), - } + }; results[pageName] = { min: minResult(result), @@ -93,101 +93,101 @@ async function profilePageLoad(pages, numSamples) { average: averageResult(result), standardDeviation: standardDeviationResult(result), marginOfError: marginOfErrorResult(result), - } + }; } - return results + return results; } async function isWritable(directory) { try { - await fs.access(directory, fsConstants.W_OK) - return true + await fs.access(directory, fsConstants.W_OK); + return true; } catch (error) { if (error.code !== 'EACCES') { - throw error + throw error; } - return false + return false; } } async function getFirstParentDirectoryThatExists(directory) { - let nextDirectory = directory + let nextDirectory = directory; for (;;) { try { - await fs.access(nextDirectory, fsConstants.F_OK) - return nextDirectory + await fs.access(nextDirectory, fsConstants.F_OK); + return nextDirectory; } catch (error) { if (error.code !== 'ENOENT') { - throw error + throw error; } else if (nextDirectory === path.dirname(nextDirectory)) { - throw new Error('Failed to find parent directory that exists') + throw new Error('Failed to find parent directory that exists'); } - nextDirectory = path.dirname(nextDirectory) + nextDirectory = path.dirname(nextDirectory); } } } async function main() { - const args = process.argv.slice(2) + const args = process.argv.slice(2); - let pages = ['home'] - let numSamples = DEFAULT_NUM_SAMPLES - let outputPath - let outputDirectory - let existingParentDirectory + let pages = ['home']; + let numSamples = DEFAULT_NUM_SAMPLES; + let outputPath; + let outputDirectory; + let existingParentDirectory; while (args.length) { if (/^(--pages|-p)$/u.test(args[0])) { if (args[1] === undefined) { - throw new Error('Missing pages argument') + throw new Error('Missing pages argument'); } - pages = args[1].split(',') + pages = args[1].split(','); for (const page of pages) { if (!ALL_PAGES.includes(page)) { - throw new Error(`Invalid page: '${page}`) + throw new Error(`Invalid page: '${page}`); } } - args.splice(0, 2) + args.splice(0, 2); } else if (/^(--samples|-s)$/u.test(args[0])) { if (args[1] === undefined) { - throw new Error('Missing number of samples') + throw new Error('Missing number of samples'); } - numSamples = parseInt(args[1], 10) + numSamples = parseInt(args[1], 10); if (isNaN(numSamples)) { - throw new Error(`Invalid 'samples' argument given: '${args[1]}'`) + throw new Error(`Invalid 'samples' argument given: '${args[1]}'`); } - args.splice(0, 2) + args.splice(0, 2); } else if (/^(--out|-o)$/u.test(args[0])) { if (args[1] === undefined) { - throw new Error('Missing output filename') + throw new Error('Missing output filename'); } - outputPath = path.resolve(args[1]) - outputDirectory = path.dirname(outputPath) + outputPath = path.resolve(args[1]); + outputDirectory = path.dirname(outputPath); existingParentDirectory = await getFirstParentDirectoryThatExists( outputDirectory, - ) + ); if (!(await isWritable(existingParentDirectory))) { - throw new Error(`Specified directory is not writable: '${args[1]}'`) + throw new Error(`Specified directory is not writable: '${args[1]}'`); } - args.splice(0, 2) + args.splice(0, 2); } else { - throw new Error(`Unrecognized argument: '${args[0]}'`) + throw new Error(`Unrecognized argument: '${args[0]}'`); } } - const results = await profilePageLoad(pages, numSamples) + const results = await profilePageLoad(pages, numSamples); if (outputPath) { if (outputDirectory !== existingParentDirectory) { - await fs.mkdir(outputDirectory, { recursive: true }) + await fs.mkdir(outputDirectory, { recursive: true }); } - await fs.writeFile(outputPath, JSON.stringify(results, null, 2)) + await fs.writeFile(outputPath, JSON.stringify(results, null, 2)); } else { - console.log(JSON.stringify(results, null, 2)) + console.log(JSON.stringify(results, null, 2)); } } main().catch((e) => { - console.error(e) - process.exit(1) -}) + console.error(e); + process.exit(1); +}); diff --git a/test/e2e/ethereum-on.spec.js b/test/e2e/ethereum-on.spec.js index 52485d76a..dfe1a5d1a 100644 --- a/test/e2e/ethereum-on.spec.js +++ b/test/e2e/ethereum-on.spec.js @@ -1,20 +1,20 @@ -const assert = require('assert') -const webdriver = require('selenium-webdriver') +const assert = require('assert'); +const webdriver = require('selenium-webdriver'); -const { By, until } = webdriver -const enLocaleMessages = require('../../app/_locales/en/messages.json') -const { regularDelayMs, largeDelayMs } = require('./helpers') -const { buildWebDriver } = require('./webdriver') -const Ganache = require('./ganache') +const { By, until } = webdriver; +const enLocaleMessages = require('../../app/_locales/en/messages.json'); +const { regularDelayMs, largeDelayMs } = require('./helpers'); +const { buildWebDriver } = require('./webdriver'); +const Ganache = require('./ganache'); -const ganacheServer = new Ganache() +const ganacheServer = new Ganache(); describe('MetaMask', function () { - let driver - let publicAddress + let driver; + let publicAddress; - this.timeout(0) - this.bail(true) + this.timeout(0); + this.bail(true); before(async function () { await ganacheServer.start({ @@ -25,175 +25,177 @@ describe('MetaMask', function () { balance: 25000000000000000000, }, ], - }) - const result = await buildWebDriver() - driver = result.driver - await driver.navigate() - }) + }); + const result = await buildWebDriver(); + driver = result.driver; + await driver.navigate(); + }); afterEach(async function () { if (process.env.SELENIUM_BROWSER === 'chrome') { - const errors = await driver.checkBrowserForConsoleErrors(driver) + const errors = await driver.checkBrowserForConsoleErrors(driver); if (errors.length) { - const errorReports = errors.map((err) => err.message) + const errorReports = errors.map((err) => err.message); const errorMessage = `Errors found in browser console:\n${errorReports.join( '\n', - )}` - console.error(new Error(errorMessage)) + )}`; + console.error(new Error(errorMessage)); } } if (this.currentTest.state === 'failed') { - await driver.verboseReportOnFailure(this.currentTest.title) + await driver.verboseReportOnFailure(this.currentTest.title); } - }) + }); after(async function () { - await ganacheServer.quit() - await driver.quit() - }) + await ganacheServer.quit(); + await driver.quit(); + }); describe('Going through the first time flow, but skipping the seed phrase challenge', function () { it('clicks the continue button on the welcome screen', async function () { - await driver.findElement(By.css('.welcome-page__header')) + await driver.findElement(By.css('.welcome-page__header')); await driver.clickElement( By.xpath( `//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`, ), - ) - await driver.delay(largeDelayMs) - }) + ); + await driver.delay(largeDelayMs); + }); it('clicks the "Create New Wallet" option', async function () { await driver.clickElement( By.xpath(`//button[contains(text(), 'Create a Wallet')]`), - ) - await driver.delay(largeDelayMs) - }) + ); + await driver.delay(largeDelayMs); + }); it('clicks the "No thanks" option on the metametrics opt-in screen', async function () { - await driver.clickElement(By.css('.btn-default')) - await driver.delay(largeDelayMs) - }) + await driver.clickElement(By.css('.btn-default')); + await driver.delay(largeDelayMs); + }); it('accepts a secure password', async function () { const passwordBox = await driver.findElement( By.css('.first-time-flow__form #create-password'), - ) + ); const passwordBoxConfirm = await driver.findElement( By.css('.first-time-flow__form #confirm-password'), - ) + ); - await passwordBox.sendKeys('correct horse battery staple') - await passwordBoxConfirm.sendKeys('correct horse battery staple') + await passwordBox.sendKeys('correct horse battery staple'); + await passwordBoxConfirm.sendKeys('correct horse battery staple'); - await driver.clickElement(By.css('.first-time-flow__checkbox')) - await driver.clickElement(By.css('.first-time-flow__form button')) - await driver.delay(largeDelayMs) - }) + await driver.clickElement(By.css('.first-time-flow__checkbox')); + await driver.clickElement(By.css('.first-time-flow__form button')); + await driver.delay(largeDelayMs); + }); it('skips the seed phrase challenge', async function () { await driver.clickElement( By.xpath( `//button[contains(text(), '${enLocaleMessages.remindMeLater.message}')]`, ), - ) - await driver.delay(regularDelayMs) + ); + await driver.delay(regularDelayMs); await driver.clickElement( By.css('[data-testid="account-options-menu-button"]'), - ) + ); await driver.clickElement( By.css('[data-testid="account-options-menu__account-details"]'), - ) - }) + ); + }); it('gets the current accounts address', async function () { const addressInput = await driver.findElement( By.css('.readonly-input__input'), - ) - publicAddress = await addressInput.getAttribute('value') - const accountModal = await driver.findElement(By.css('span .modal')) + ); + publicAddress = await addressInput.getAttribute('value'); + const accountModal = await driver.findElement(By.css('span .modal')); - await driver.clickElement(By.css('.account-modal__close')) + await driver.clickElement(By.css('.account-modal__close')); - await driver.wait(until.stalenessOf(accountModal)) - await driver.delay(regularDelayMs) - }) - }) + await driver.wait(until.stalenessOf(accountModal)); + await driver.delay(regularDelayMs); + }); + }); describe('provider listening for events', function () { - let extension - let popup - let dapp + let extension; + let popup; + let dapp; it('connects to the dapp', async function () { - await driver.openNewPage('http://127.0.0.1:8080/') - await driver.delay(regularDelayMs) + await driver.openNewPage('http://127.0.0.1:8080/'); + await driver.delay(regularDelayMs); await driver.clickElement( By.xpath(`//button[contains(text(), 'Connect')]`), - ) + ); - await driver.delay(regularDelayMs) + await driver.delay(regularDelayMs); - await driver.waitUntilXWindowHandles(3) - const windowHandles = await driver.getAllWindowHandles() + await driver.waitUntilXWindowHandles(3); + const windowHandles = await driver.getAllWindowHandles(); - extension = windowHandles[0] + extension = windowHandles[0]; dapp = await driver.switchToWindowWithTitle( 'E2E Test Dapp', windowHandles, - ) + ); popup = windowHandles.find( (handle) => handle !== extension && handle !== dapp, - ) + ); - await driver.switchToWindow(popup) + await driver.switchToWindow(popup); - await driver.delay(regularDelayMs) + await driver.delay(regularDelayMs); - await driver.clickElement(By.xpath(`//button[contains(text(), 'Next')]`)) + await driver.clickElement(By.xpath(`//button[contains(text(), 'Next')]`)); await driver.clickElement( By.xpath(`//button[contains(text(), 'Connect')]`), - ) + ); - await driver.waitUntilXWindowHandles(2) - await driver.switchToWindow(dapp) - await driver.delay(regularDelayMs) - }) + await driver.waitUntilXWindowHandles(2); + await driver.switchToWindow(dapp); + await driver.delay(regularDelayMs); + }); it('has the ganache network id within the dapp', async function () { - const networkDiv = await driver.findElement(By.css('#network')) - await driver.delay(regularDelayMs) - assert.equal(await networkDiv.getText(), '1337') - }) + const networkDiv = await driver.findElement(By.css('#network')); + await driver.delay(regularDelayMs); + assert.equal(await networkDiv.getText(), '1337'); + }); it('changes the network', async function () { - await driver.switchToWindow(extension) + await driver.switchToWindow(extension); - await driver.clickElement(By.css('.network-display')) - await driver.delay(regularDelayMs) + await driver.clickElement(By.css('.network-display')); + await driver.delay(regularDelayMs); - await driver.clickElement(By.xpath(`//span[contains(text(), 'Ropsten')]`)) - await driver.delay(largeDelayMs) - }) + await driver.clickElement( + By.xpath(`//span[contains(text(), 'Ropsten')]`), + ); + await driver.delay(largeDelayMs); + }); it('sets the network div within the dapp', async function () { - await driver.switchToWindow(dapp) - const networkDiv = await driver.findElement(By.css('#network')) - assert.equal(await networkDiv.getText(), '3') - }) + await driver.switchToWindow(dapp); + const networkDiv = await driver.findElement(By.css('#network')); + assert.equal(await networkDiv.getText(), '3'); + }); it('sets the chainId div within the dapp', async function () { - await driver.switchToWindow(dapp) - const chainIdDiv = await driver.findElement(By.css('#chainId')) - assert.equal(await chainIdDiv.getText(), '0x3') - }) + await driver.switchToWindow(dapp); + const chainIdDiv = await driver.findElement(By.css('#chainId')); + assert.equal(await chainIdDiv.getText(), '0x3'); + }); it('sets the account div within the dapp', async function () { - await driver.switchToWindow(dapp) - const accountsDiv = await driver.findElement(By.css('#accounts')) - assert.equal(await accountsDiv.getText(), publicAddress.toLowerCase()) - }) - }) -}) + await driver.switchToWindow(dapp); + const accountsDiv = await driver.findElement(By.css('#accounts')); + assert.equal(await accountsDiv.getText(), publicAddress.toLowerCase()); + }); + }); +}); diff --git a/test/e2e/fixture-server.js b/test/e2e/fixture-server.js index 7c0ea5a86..6709b9759 100644 --- a/test/e2e/fixture-server.js +++ b/test/e2e/fixture-server.js @@ -1,26 +1,26 @@ -const { promises: fs } = require('fs') -const path = require('path') -const Koa = require('koa') +const { promises: fs } = require('fs'); +const path = require('path'); +const Koa = require('koa'); -const CURRENT_STATE_KEY = '__CURRENT__' -const DEFAULT_STATE_KEY = '__DEFAULT__' +const CURRENT_STATE_KEY = '__CURRENT__'; +const DEFAULT_STATE_KEY = '__DEFAULT__'; -const FIXTURE_SERVER_HOST = 'localhost' -const FIXTURE_SERVER_PORT = 12345 +const FIXTURE_SERVER_HOST = 'localhost'; +const FIXTURE_SERVER_PORT = 12345; class FixtureServer { constructor() { - this._app = new Koa() - this._stateMap = new Map([[DEFAULT_STATE_KEY, Object.create(null)]]) - this._initialStateCache = new Map() + this._app = new Koa(); + this._stateMap = new Map([[DEFAULT_STATE_KEY, Object.create(null)]]); + this._initialStateCache = new Map(); this._app.use(async (ctx) => { // Firefox is _super_ strict about needing CORS headers - ctx.set('Access-Control-Allow-Origin', '*') + ctx.set('Access-Control-Allow-Origin', '*'); if (this._isStateRequest(ctx)) { - ctx.body = this._stateMap.get(CURRENT_STATE_KEY) + ctx.body = this._stateMap.get(CURRENT_STATE_KEY); } - }) + }); } async start() { @@ -28,45 +28,45 @@ class FixtureServer { host: FIXTURE_SERVER_HOST, port: FIXTURE_SERVER_PORT, exclusive: true, - } + }; return new Promise((resolve, reject) => { - this._server = this._app.listen(options) - this._server.once('error', reject) - this._server.once('listening', resolve) - }) + this._server = this._app.listen(options); + this._server.once('error', reject); + this._server.once('listening', resolve); + }); } async stop() { if (!this._server) { - return + return; } await new Promise((resolve, reject) => { - this._server.close() - this._server.once('error', reject) - this._server.once('close', resolve) - }) + this._server.close(); + this._server.once('error', reject); + this._server.once('close', resolve); + }); } async loadState(directory) { - const statePath = path.resolve(__dirname, directory, 'state.json') + const statePath = path.resolve(__dirname, directory, 'state.json'); - let state + let state; if (this._initialStateCache.has(statePath)) { - state = this._initialStateCache.get(statePath) + state = this._initialStateCache.get(statePath); } else { - const data = await fs.readFile(statePath) - state = JSON.parse(data.toString('utf-8')) - this._initialStateCache.set(statePath, state) + const data = await fs.readFile(statePath); + state = JSON.parse(data.toString('utf-8')); + this._initialStateCache.set(statePath, state); } - this._stateMap.set(CURRENT_STATE_KEY, state) + this._stateMap.set(CURRENT_STATE_KEY, state); } _isStateRequest(ctx) { - return ctx.method === 'GET' && ctx.path === '/state.json' + return ctx.method === 'GET' && ctx.path === '/state.json'; } } -module.exports = FixtureServer +module.exports = FixtureServer; diff --git a/test/e2e/from-import-ui.spec.js b/test/e2e/from-import-ui.spec.js index 8dbabbcac..fdea86cf8 100644 --- a/test/e2e/from-import-ui.spec.js +++ b/test/e2e/from-import-ui.spec.js @@ -1,27 +1,27 @@ -const assert = require('assert') -const webdriver = require('selenium-webdriver') +const assert = require('assert'); +const webdriver = require('selenium-webdriver'); -const { By, Key, until } = webdriver -const enLocaleMessages = require('../../app/_locales/en/messages.json') -const { regularDelayMs, largeDelayMs } = require('./helpers') -const { buildWebDriver } = require('./webdriver') -const Ganache = require('./ganache') +const { By, Key, until } = webdriver; +const enLocaleMessages = require('../../app/_locales/en/messages.json'); +const { regularDelayMs, largeDelayMs } = require('./helpers'); +const { buildWebDriver } = require('./webdriver'); +const Ganache = require('./ganache'); -const ganacheServer = new Ganache() +const ganacheServer = new Ganache(); describe('Using MetaMask with an existing account', function () { - let driver + let driver; const testSeedPhrase = - 'forum vessel pink push lonely enact gentle tail admit parrot grunt dress' - const testAddress = '0x0Cc5261AB8cE458dc977078A3623E2BaDD27afD3' + 'forum vessel pink push lonely enact gentle tail admit parrot grunt dress'; + const testAddress = '0x0Cc5261AB8cE458dc977078A3623E2BaDD27afD3'; const testPrivateKey2 = - '14abe6f4aab7f9f626fe981c864d0adeb5685f289ac9270c27b8fd790b4235d6' + '14abe6f4aab7f9f626fe981c864d0adeb5685f289ac9270c27b8fd790b4235d6'; const testPrivateKey3 = - 'F4EC2590A0C10DE95FBF4547845178910E40F5035320C516A18C117DE02B5669' + 'F4EC2590A0C10DE95FBF4547845178910E40F5035320C516A18C117DE02B5669'; - this.timeout(0) - this.bail(true) + this.timeout(0); + this.bail(true); before(async function () { await ganacheServer.start({ @@ -32,392 +32,394 @@ describe('Using MetaMask with an existing account', function () { balance: 25000000000000000000, }, ], - }) - const result = await buildWebDriver() - driver = result.driver - await driver.navigate() - }) + }); + const result = await buildWebDriver(); + driver = result.driver; + await driver.navigate(); + }); afterEach(async function () { if (process.env.SELENIUM_BROWSER === 'chrome') { - const errors = await driver.checkBrowserForConsoleErrors(driver) + const errors = await driver.checkBrowserForConsoleErrors(driver); if (errors.length) { - const errorReports = errors.map((err) => err.message) + const errorReports = errors.map((err) => err.message); const errorMessage = `Errors found in browser console:\n${errorReports.join( '\n', - )}` - console.error(new Error(errorMessage)) + )}`; + console.error(new Error(errorMessage)); } } if (this.currentTest.state === 'failed') { - await driver.verboseReportOnFailure(this.currentTest.title) + await driver.verboseReportOnFailure(this.currentTest.title); } - }) + }); after(async function () { - await ganacheServer.quit() - await driver.quit() - }) + await ganacheServer.quit(); + await driver.quit(); + }); describe('First time flow starting from an existing seed phrase', function () { it('clicks the continue button on the welcome screen', async function () { - await driver.findElement(By.css('.welcome-page__header')) + await driver.findElement(By.css('.welcome-page__header')); await driver.clickElement( By.xpath( `//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`, ), - ) - await driver.delay(largeDelayMs) - }) + ); + await driver.delay(largeDelayMs); + }); it('clicks the "Import Wallet" option', async function () { await driver.clickElement( By.xpath(`//button[contains(text(), 'Import wallet')]`), - ) - await driver.delay(largeDelayMs) - }) + ); + await driver.delay(largeDelayMs); + }); it('clicks the "No thanks" option on the metametrics opt-in screen', async function () { - await driver.clickElement(By.css('.btn-default')) - await driver.delay(largeDelayMs) - }) + await driver.clickElement(By.css('.btn-default')); + await driver.delay(largeDelayMs); + }); it('imports a seed phrase', async function () { const [seedTextArea] = await driver.findElements( By.css('input[placeholder="Paste seed phrase from clipboard"]'), - ) - await seedTextArea.sendKeys(testSeedPhrase) - await driver.delay(regularDelayMs) + ); + await seedTextArea.sendKeys(testSeedPhrase); + await driver.delay(regularDelayMs); - const [password] = await driver.findElements(By.id('password')) - await password.sendKeys('correct horse battery staple') + const [password] = await driver.findElements(By.id('password')); + await password.sendKeys('correct horse battery staple'); const [confirmPassword] = await driver.findElements( By.id('confirm-password'), - ) - confirmPassword.sendKeys('correct horse battery staple') + ); + confirmPassword.sendKeys('correct horse battery staple'); - await driver.clickElement(By.css('.first-time-flow__terms')) + await driver.clickElement(By.css('.first-time-flow__terms')); await driver.clickElement( By.xpath(`//button[contains(text(), 'Import')]`), - ) - await driver.delay(regularDelayMs) - }) + ); + await driver.delay(regularDelayMs); + }); it('clicks through the success screen', async function () { await driver.findElement( By.xpath(`//div[contains(text(), 'Congratulations')]`), - ) + ); await driver.clickElement( By.xpath( `//button[contains(text(), '${enLocaleMessages.endOfFlowMessage10.message}')]`, ), - ) - await driver.delay(regularDelayMs) - }) - }) + ); + await driver.delay(regularDelayMs); + }); + }); describe('Show account information', function () { it('shows the correct account address', async function () { await driver.clickElement( By.css('[data-testid="account-options-menu-button"]'), - ) + ); await driver.clickElement( By.css('[data-testid="account-options-menu__account-details"]'), - ) - await driver.findVisibleElement(By.css('.qr-code__wrapper')) - await driver.delay(regularDelayMs) + ); + await driver.findVisibleElement(By.css('.qr-code__wrapper')); + await driver.delay(regularDelayMs); const [address] = await driver.findElements( By.css('.readonly-input__input'), - ) - assert.equal(await address.getAttribute('value'), testAddress) + ); + assert.equal(await address.getAttribute('value'), testAddress); - await driver.clickElement(By.css('.account-modal__close')) - await driver.delay(largeDelayMs) - }) + await driver.clickElement(By.css('.account-modal__close')); + await driver.delay(largeDelayMs); + }); it('shows a QR code for the account', async function () { await driver.clickElement( By.css('[data-testid="account-options-menu-button"]'), - ) + ); await driver.clickElement( By.css('[data-testid="account-options-menu__account-details"]'), - ) - await driver.findVisibleElement(By.css('.qr-code__wrapper')) - const detailModal = await driver.findElement(By.css('span .modal')) - await driver.delay(regularDelayMs) + ); + await driver.findVisibleElement(By.css('.qr-code__wrapper')); + const detailModal = await driver.findElement(By.css('span .modal')); + await driver.delay(regularDelayMs); - await driver.clickElement(By.css('.account-modal__close')) - await driver.wait(until.stalenessOf(detailModal)) - await driver.delay(regularDelayMs) - }) - }) + await driver.clickElement(By.css('.account-modal__close')); + await driver.wait(until.stalenessOf(detailModal)); + await driver.delay(regularDelayMs); + }); + }); describe('Lock and unlock', function () { it('logs out of the account', async function () { - await driver.clickElement(By.css('.account-menu__icon .identicon')) - await driver.delay(regularDelayMs) + await driver.clickElement(By.css('.account-menu__icon .identicon')); + await driver.delay(regularDelayMs); const lockButton = await driver.findClickableElement( By.css('.account-menu__lock-button'), - ) - assert.equal(await lockButton.getText(), 'Lock') - await lockButton.click() - await driver.delay(regularDelayMs) - }) + ); + assert.equal(await lockButton.getText(), 'Lock'); + await lockButton.click(); + await driver.delay(regularDelayMs); + }); it('accepts the account password after lock', async function () { - const passwordField = await driver.findElement(By.id('password')) - await passwordField.sendKeys('correct horse battery staple') - await passwordField.sendKeys(Key.ENTER) - await driver.delay(largeDelayMs) - }) - }) + const passwordField = await driver.findElement(By.id('password')); + await passwordField.sendKeys('correct horse battery staple'); + await passwordField.sendKeys(Key.ENTER); + await driver.delay(largeDelayMs); + }); + }); describe('Add an account', function () { it('switches to localhost', async function () { - await driver.clickElement(By.css('.network-display')) - await driver.delay(regularDelayMs) + await driver.clickElement(By.css('.network-display')); + await driver.delay(regularDelayMs); await driver.clickElement( By.xpath(`//span[contains(text(), 'Localhost')]`), - ) - await driver.delay(largeDelayMs) - }) + ); + await driver.delay(largeDelayMs); + }); it('choose Create Account from the account menu', async function () { - await driver.clickElement(By.css('.account-menu__icon')) - await driver.delay(regularDelayMs) + await driver.clickElement(By.css('.account-menu__icon')); + await driver.delay(regularDelayMs); await driver.clickElement( By.xpath(`//div[contains(text(), 'Create Account')]`), - ) - await driver.delay(regularDelayMs) - }) + ); + await driver.delay(regularDelayMs); + }); it('set account name', async function () { const [accountName] = await driver.findElements( By.css('.new-account-create-form input'), - ) - await accountName.sendKeys('2nd account') - await driver.delay(regularDelayMs) + ); + await accountName.sendKeys('2nd account'); + await driver.delay(regularDelayMs); await driver.clickElement( By.xpath(`//button[contains(text(), 'Create')]`), - ) - await driver.delay(regularDelayMs) - }) + ); + await driver.delay(regularDelayMs); + }); it('should show the correct account name', async function () { const accountName = await driver.findElement( By.css('.selected-account__name'), - ) - assert.equal(await accountName.getText(), '2nd account') - await driver.delay(regularDelayMs) - }) - }) + ); + assert.equal(await accountName.getText(), '2nd account'); + await driver.delay(regularDelayMs); + }); + }); describe('Switch back to original account', function () { it('chooses the original account from the account menu', async function () { - await driver.clickElement(By.css('.account-menu__icon')) - await driver.delay(regularDelayMs) + await driver.clickElement(By.css('.account-menu__icon')); + await driver.delay(regularDelayMs); - await driver.clickElement(By.css('.account-menu__name')) - await driver.delay(regularDelayMs) - }) - }) + await driver.clickElement(By.css('.account-menu__name')); + await driver.delay(regularDelayMs); + }); + }); describe('Send ETH from inside MetaMask', function () { it('starts a send transaction', async function () { - await driver.clickElement(By.css('[data-testid="eth-overview-send"]')) - await driver.delay(regularDelayMs) + await driver.clickElement(By.css('[data-testid="eth-overview-send"]')); + await driver.delay(regularDelayMs); const inputAddress = await driver.findElement( By.css('input[placeholder="Search, public address (0x), or ENS"]'), - ) - await inputAddress.sendKeys('0x2f318C334780961FB129D2a6c30D0763d9a5C970') + ); + await inputAddress.sendKeys('0x2f318C334780961FB129D2a6c30D0763d9a5C970'); - const inputAmount = await driver.findElement(By.css('.unit-input__input')) - await inputAmount.sendKeys('1') + const inputAmount = await driver.findElement( + By.css('.unit-input__input'), + ); + await inputAmount.sendKeys('1'); // Set the gas limit - await driver.clickElement(By.css('.advanced-gas-options-btn')) - await driver.delay(regularDelayMs) + await driver.clickElement(By.css('.advanced-gas-options-btn')); + await driver.delay(regularDelayMs); - const gasModal = await driver.findElement(By.css('span .modal')) - await driver.clickElement(By.xpath(`//button[contains(text(), 'Save')]`)) - await driver.wait(until.stalenessOf(gasModal)) - await driver.delay(regularDelayMs) + const gasModal = await driver.findElement(By.css('span .modal')); + await driver.clickElement(By.xpath(`//button[contains(text(), 'Save')]`)); + await driver.wait(until.stalenessOf(gasModal)); + await driver.delay(regularDelayMs); // Continue to next screen - await driver.clickElement(By.xpath(`//button[contains(text(), 'Next')]`)) - await driver.delay(regularDelayMs) - }) + await driver.clickElement(By.xpath(`//button[contains(text(), 'Next')]`)); + await driver.delay(regularDelayMs); + }); it('confirms the transaction', async function () { await driver.clickElement( By.xpath(`//button[contains(text(), 'Confirm')]`), - ) - await driver.delay(regularDelayMs) - }) + ); + await driver.delay(regularDelayMs); + }); it('finds the transaction in the transactions list', async function () { - await driver.clickElement(By.css('[data-testid="home__activity-tab"]')) + await driver.clickElement(By.css('[data-testid="home__activity-tab"]')); await driver.wait(async () => { const confirmedTxes = await driver.findElements( By.css( '.transaction-list__completed-transactions .transaction-list-item', ), - ) - return confirmedTxes.length === 1 - }, 10000) + ); + return confirmedTxes.length === 1; + }, 10000); const txValues = await driver.findElements( By.css('.transaction-list-item__primary-currency'), - ) - assert.equal(txValues.length, 1) - assert.ok(/-1\s*ETH/u.test(await txValues[0].getText())) - }) - }) + ); + assert.equal(txValues.length, 1); + assert.ok(/-1\s*ETH/u.test(await txValues[0].getText())); + }); + }); describe('Imports an account with private key', function () { it('choose Create Account from the account menu', async function () { - await driver.clickElement(By.css('.account-menu__icon')) - await driver.delay(regularDelayMs) + await driver.clickElement(By.css('.account-menu__icon')); + await driver.delay(regularDelayMs); await driver.clickElement( By.xpath(`//div[contains(text(), 'Import Account')]`), - ) - await driver.delay(regularDelayMs) - }) + ); + await driver.delay(regularDelayMs); + }); it('enter private key', async function () { const privateKeyInput = await driver.findElement( By.css('#private-key-box'), - ) - await privateKeyInput.sendKeys(testPrivateKey2) - await driver.delay(regularDelayMs) + ); + await privateKeyInput.sendKeys(testPrivateKey2); + await driver.delay(regularDelayMs); await driver.clickElement( By.xpath(`//button[contains(text(), 'Import')]`), - ) - await driver.delay(regularDelayMs) - }) + ); + await driver.delay(regularDelayMs); + }); it('should show the correct account name', async function () { const accountName = await driver.findElement( By.css('.selected-account__name'), - ) - assert.equal(await accountName.getText(), 'Account 4') - await driver.delay(regularDelayMs) - }) + ); + assert.equal(await accountName.getText(), 'Account 4'); + await driver.delay(regularDelayMs); + }); it('should show the imported label', async function () { - await driver.clickElement(By.css('.account-menu__icon')) + await driver.clickElement(By.css('.account-menu__icon')); // confirm 4th account is account 4, as expected - const accountMenuItemSelector = '.account-menu__account:nth-child(4)' + const accountMenuItemSelector = '.account-menu__account:nth-child(4)'; const accountName = await driver.findElement( By.css(`${accountMenuItemSelector} .account-menu__name`), - ) - assert.equal(await accountName.getText(), 'Account 4') + ); + assert.equal(await accountName.getText(), 'Account 4'); // confirm label is present on the same menu item const importedLabel = await driver.findElement( By.css(`${accountMenuItemSelector} .keyring-label`), - ) - assert.equal(await importedLabel.getText(), 'IMPORTED') - }) - }) + ); + assert.equal(await importedLabel.getText(), 'IMPORTED'); + }); + }); describe('Imports and removes an account', function () { it('choose Create Account from the account menu', async function () { await driver.clickElement( By.xpath(`//div[contains(text(), 'Import Account')]`), - ) - await driver.delay(regularDelayMs) - }) + ); + await driver.delay(regularDelayMs); + }); it('enter private key', async function () { const privateKeyInput = await driver.findElement( By.css('#private-key-box'), - ) - await privateKeyInput.sendKeys(testPrivateKey3) - await driver.delay(regularDelayMs) + ); + await privateKeyInput.sendKeys(testPrivateKey3); + await driver.delay(regularDelayMs); await driver.clickElement( By.xpath(`//button[contains(text(), 'Import')]`), - ) - await driver.delay(regularDelayMs) - }) + ); + await driver.delay(regularDelayMs); + }); it('should see new account in account menu', async function () { const accountName = await driver.findElement( By.css('.selected-account__name'), - ) - assert.equal(await accountName.getText(), 'Account 5') - await driver.delay(regularDelayMs) + ); + assert.equal(await accountName.getText(), 'Account 5'); + await driver.delay(regularDelayMs); - await driver.clickElement(By.css('.account-menu__icon')) - await driver.delay(regularDelayMs) + await driver.clickElement(By.css('.account-menu__icon')); + await driver.delay(regularDelayMs); const accountListItems = await driver.findElements( By.css('.account-menu__account'), - ) - assert.equal(accountListItems.length, 5) + ); + assert.equal(accountListItems.length, 5); - await driver.clickPoint(By.css('.account-menu__icon'), 0, 0) - }) + await driver.clickPoint(By.css('.account-menu__icon'), 0, 0); + }); it('should open the remove account modal', async function () { await driver.clickElement( By.css('[data-testid="account-options-menu-button"]'), - ) + ); await driver.clickElement( By.css('[data-testid="account-options-menu__remove-account"]'), - ) + ); - await driver.findElement(By.css('.confirm-remove-account__account')) - }) + await driver.findElement(By.css('.confirm-remove-account__account')); + }); it('should remove the account', async function () { await driver.clickElement( By.xpath(`//button[contains(text(), 'Remove')]`), - ) + ); - await driver.delay(regularDelayMs) + await driver.delay(regularDelayMs); const accountName = await driver.findElement( By.css('.selected-account__name'), - ) - assert.equal(await accountName.getText(), 'Account 1') - await driver.delay(regularDelayMs) + ); + assert.equal(await accountName.getText(), 'Account 1'); + await driver.delay(regularDelayMs); - await driver.clickElement(By.css('.account-menu__icon')) + await driver.clickElement(By.css('.account-menu__icon')); const accountListItems = await driver.findElements( By.css('.account-menu__account'), - ) - assert.equal(accountListItems.length, 4) - }) - }) + ); + assert.equal(accountListItems.length, 4); + }); + }); describe('Connects to a Hardware wallet', function () { it('choose Connect Hardware Wallet from the account menu', async function () { await driver.clickElement( By.xpath(`//div[contains(text(), 'Connect Hardware Wallet')]`), - ) - await driver.delay(regularDelayMs) - }) + ); + await driver.delay(regularDelayMs); + }); it('should open the TREZOR Connect popup', async function () { - await driver.clickElement(By.css('.hw-connect__btn:nth-of-type(2)')) - await driver.delay(regularDelayMs) + await driver.clickElement(By.css('.hw-connect__btn:nth-of-type(2)')); + await driver.delay(regularDelayMs); await driver.clickElement( By.xpath(`//button[contains(text(), 'Connect')]`), - ) - await driver.delay(regularDelayMs) - const allWindows = await driver.getAllWindowHandles() - assert.equal(allWindows.length, 2) - }) - }) -}) + ); + await driver.delay(regularDelayMs); + const allWindows = await driver.getAllWindowHandles(); + assert.equal(allWindows.length, 2); + }); + }); +}); diff --git a/test/e2e/ganache.js b/test/e2e/ganache.js index 279473766..8f9974da1 100644 --- a/test/e2e/ganache.js +++ b/test/e2e/ganache.js @@ -1,5 +1,5 @@ -const { promisify } = require('util') -const ganache = require('ganache-core') +const { promisify } = require('util'); +const ganache = require('ganache-core'); const defaultOptions = { blockTime: 2, @@ -8,30 +8,30 @@ const defaultOptions = { 'phrase upgrade clock rough situate wedding elder clever doctor stamp excess tent', port: 8545, vmErrorsOnRPCResponse: false, -} +}; class Ganache { async start(opts) { - const options = { ...defaultOptions, ...opts } - const { port } = options - this._server = ganache.server(options) + const options = { ...defaultOptions, ...opts }; + const { port } = options; + this._server = ganache.server(options); - const listen = promisify(this._server.listen).bind(this._server) - const blockchain = await listen(port) + const listen = promisify(this._server.listen).bind(this._server); + const blockchain = await listen(port); return { ...blockchain, port, - } + }; } async quit() { if (!this._server) { - throw new Error('Server not running yet') + throw new Error('Server not running yet'); } - const close = promisify(this._server.close).bind(this._server) - await close() + const close = promisify(this._server.close).bind(this._server); + await close(); } } -module.exports = Ganache +module.exports = Ganache; diff --git a/test/e2e/helpers.js b/test/e2e/helpers.js index 926f67177..5daadbb0d 100644 --- a/test/e2e/helpers.js +++ b/test/e2e/helpers.js @@ -1,18 +1,18 @@ -const path = require('path') -const sinon = require('sinon') -const createStaticServer = require('../../development/create-static-server') +const path = require('path'); +const sinon = require('sinon'); +const createStaticServer = require('../../development/create-static-server'); const { createSegmentServer, -} = require('../../development/lib/create-segment-server') -const Ganache = require('./ganache') -const FixtureServer = require('./fixture-server') -const { buildWebDriver } = require('./webdriver') +} = require('../../development/lib/create-segment-server'); +const Ganache = require('./ganache'); +const FixtureServer = require('./fixture-server'); +const { buildWebDriver } = require('./webdriver'); -const tinyDelayMs = 200 -const regularDelayMs = tinyDelayMs * 2 -const largeDelayMs = regularDelayMs * 2 +const tinyDelayMs = 200; +const regularDelayMs = tinyDelayMs * 2; +const largeDelayMs = regularDelayMs * 2; -const dappPort = 8080 +const dappPort = 8080; async function withFixtures(options, testSuite) { const { @@ -22,18 +22,18 @@ async function withFixtures(options, testSuite) { driverOptions, mockSegment, title, - } = options - const fixtureServer = new FixtureServer() - const ganacheServer = new Ganache() - let dappServer - let segmentServer - let segmentStub + } = options; + const fixtureServer = new FixtureServer(); + const ganacheServer = new Ganache(); + let dappServer; + let segmentServer; + let segmentStub; - let webDriver + let webDriver; try { - await ganacheServer.start(ganacheOptions) - await fixtureServer.start() - await fixtureServer.loadState(path.join(__dirname, 'fixtures', fixtures)) + await ganacheServer.start(ganacheOptions); + await fixtureServer.start(); + await fixtureServer.loadState(path.join(__dirname, 'fixtures', fixtures)); if (dapp) { const dappDirectory = path.resolve( __dirname, @@ -43,70 +43,70 @@ async function withFixtures(options, testSuite) { '@metamask', 'test-dapp', 'dist', - ) - dappServer = createStaticServer(dappDirectory) - dappServer.listen(dappPort) + ); + dappServer = createStaticServer(dappDirectory); + dappServer.listen(dappPort); await new Promise((resolve, reject) => { - dappServer.on('listening', resolve) - dappServer.on('error', reject) - }) + dappServer.on('listening', resolve); + dappServer.on('error', reject); + }); } if (mockSegment) { - segmentStub = sinon.stub() + segmentStub = sinon.stub(); segmentServer = createSegmentServer((_request, response, events) => { for (const event of events) { - segmentStub(event) + segmentStub(event); } - response.statusCode = 200 - response.end() - }) - await segmentServer.start(9090) + response.statusCode = 200; + response.end(); + }); + await segmentServer.start(9090); } - const { driver } = await buildWebDriver(driverOptions) - webDriver = driver + const { driver } = await buildWebDriver(driverOptions); + webDriver = driver; await testSuite({ driver, segmentStub, - }) + }); if (process.env.SELENIUM_BROWSER === 'chrome') { - const errors = await driver.checkBrowserForConsoleErrors(driver) + const errors = await driver.checkBrowserForConsoleErrors(driver); if (errors.length) { - const errorReports = errors.map((err) => err.message) + const errorReports = errors.map((err) => err.message); const errorMessage = `Errors found in browser console:\n${errorReports.join( '\n', - )}` - throw new Error(errorMessage) + )}`; + throw new Error(errorMessage); } } } catch (error) { if (webDriver) { try { - await webDriver.verboseReportOnFailure(title) + await webDriver.verboseReportOnFailure(title); } catch (verboseReportError) { - console.error(verboseReportError) + console.error(verboseReportError); } } - throw error + throw error; } finally { - await fixtureServer.stop() - await ganacheServer.quit() + await fixtureServer.stop(); + await ganacheServer.quit(); if (webDriver) { - await webDriver.quit() + await webDriver.quit(); } if (dappServer) { await new Promise((resolve, reject) => { dappServer.close((error) => { if (error) { - return reject(error) + return reject(error); } - return resolve() - }) - }) + return resolve(); + }); + }); } if (segmentServer) { - await segmentServer.stop() + await segmentServer.stop(); } } } @@ -116,4 +116,4 @@ module.exports = { regularDelayMs, largeDelayMs, withFixtures, -} +}; diff --git a/test/e2e/incremental-security.spec.js b/test/e2e/incremental-security.spec.js index cb0c67e3c..7f9b99665 100644 --- a/test/e2e/incremental-security.spec.js +++ b/test/e2e/incremental-security.spec.js @@ -1,20 +1,20 @@ -const assert = require('assert') -const webdriver = require('selenium-webdriver') +const assert = require('assert'); +const webdriver = require('selenium-webdriver'); -const { By, until } = webdriver -const enLocaleMessages = require('../../app/_locales/en/messages.json') -const { tinyDelayMs, regularDelayMs, largeDelayMs } = require('./helpers') -const { buildWebDriver } = require('./webdriver') -const Ganache = require('./ganache') +const { By, until } = webdriver; +const enLocaleMessages = require('../../app/_locales/en/messages.json'); +const { tinyDelayMs, regularDelayMs, largeDelayMs } = require('./helpers'); +const { buildWebDriver } = require('./webdriver'); +const Ganache = require('./ganache'); -const ganacheServer = new Ganache() +const ganacheServer = new Ganache(); describe('MetaMask', function () { - let driver - let publicAddress + let driver; + let publicAddress; - this.timeout(0) - this.bail(true) + this.timeout(0); + this.bail(true); before(async function () { await ganacheServer.start({ @@ -30,140 +30,140 @@ describe('MetaMask', function () { balance: 25000000000000000000, }, ], - }) - const result = await buildWebDriver() - driver = result.driver - await driver.navigate() - }) + }); + const result = await buildWebDriver(); + driver = result.driver; + await driver.navigate(); + }); afterEach(async function () { if (process.env.SELENIUM_BROWSER === 'chrome') { - const errors = await driver.checkBrowserForConsoleErrors(driver) + const errors = await driver.checkBrowserForConsoleErrors(driver); if (errors.length) { - const errorReports = errors.map((err) => err.message) + const errorReports = errors.map((err) => err.message); const errorMessage = `Errors found in browser console:\n${errorReports.join( '\n', - )}` - console.error(new Error(errorMessage)) + )}`; + console.error(new Error(errorMessage)); } } if (this.currentTest.state === 'failed') { - await driver.verboseReportOnFailure(this.currentTest.title) + await driver.verboseReportOnFailure(this.currentTest.title); } - }) + }); after(async function () { - await ganacheServer.quit() - await driver.quit() - }) + await ganacheServer.quit(); + await driver.quit(); + }); describe('Going through the first time flow, but skipping the seed phrase challenge', function () { it('clicks the continue button on the welcome screen', async function () { - await driver.findElement(By.css('.welcome-page__header')) + await driver.findElement(By.css('.welcome-page__header')); await driver.clickElement( By.xpath( `//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`, ), - ) - await driver.delay(largeDelayMs) - }) + ); + await driver.delay(largeDelayMs); + }); it('clicks the "Create New Wallet" option', async function () { await driver.clickElement( By.xpath(`//button[contains(text(), 'Create a Wallet')]`), - ) - await driver.delay(largeDelayMs) - }) + ); + await driver.delay(largeDelayMs); + }); it('clicks the "No thanks" option on the metametrics opt-in screen', async function () { - await driver.clickElement(By.css('.btn-default')) - await driver.delay(largeDelayMs) - }) + await driver.clickElement(By.css('.btn-default')); + await driver.delay(largeDelayMs); + }); it('accepts a secure password', async function () { const passwordBox = await driver.findElement( By.css('.first-time-flow__form #create-password'), - ) + ); const passwordBoxConfirm = await driver.findElement( By.css('.first-time-flow__form #confirm-password'), - ) + ); - await passwordBox.sendKeys('correct horse battery staple') - await passwordBoxConfirm.sendKeys('correct horse battery staple') + await passwordBox.sendKeys('correct horse battery staple'); + await passwordBoxConfirm.sendKeys('correct horse battery staple'); - await driver.clickElement(By.css('.first-time-flow__checkbox')) + await driver.clickElement(By.css('.first-time-flow__checkbox')); - await driver.clickElement(By.css('.first-time-flow__form button')) - await driver.delay(regularDelayMs) - }) + await driver.clickElement(By.css('.first-time-flow__form button')); + await driver.delay(regularDelayMs); + }); it('skips the seed phrase challenge', async function () { await driver.clickElement( By.xpath( `//button[contains(text(), '${enLocaleMessages.remindMeLater.message}')]`, ), - ) - await driver.delay(regularDelayMs) + ); + await driver.delay(regularDelayMs); await driver.clickElement( By.css('[data-testid="account-options-menu-button"]'), - ) + ); await driver.clickElement( By.css('[data-testid="account-options-menu__account-details"]'), - ) - }) + ); + }); it('gets the current accounts address', async function () { const addressInput = await driver.findElement( By.css('.readonly-input__input'), - ) - publicAddress = await addressInput.getAttribute('value') + ); + publicAddress = await addressInput.getAttribute('value'); - const accountModal = await driver.findElement(By.css('span .modal')) + const accountModal = await driver.findElement(By.css('span .modal')); - await driver.clickElement(By.css('.account-modal__close')) + await driver.clickElement(By.css('.account-modal__close')); - await driver.wait(until.stalenessOf(accountModal)) - await driver.delay(regularDelayMs) - }) - }) + await driver.wait(until.stalenessOf(accountModal)); + await driver.delay(regularDelayMs); + }); + }); describe('send to current account from dapp with different provider', function () { - let extension + let extension; it('switches to dapp screen', async function () { - const windowHandles = await driver.getAllWindowHandles() - extension = windowHandles[0] + const windowHandles = await driver.getAllWindowHandles(); + extension = windowHandles[0]; - await driver.openNewPage('http://127.0.0.1:8080/') - await driver.delay(regularDelayMs) - }) + await driver.openNewPage('http://127.0.0.1:8080/'); + await driver.delay(regularDelayMs); + }); it('sends eth to the current account', async function () { - const addressInput = await driver.findElement(By.css('#address')) - await addressInput.sendKeys(publicAddress) - await driver.delay(regularDelayMs) + const addressInput = await driver.findElement(By.css('#address')); + await addressInput.sendKeys(publicAddress); + await driver.delay(regularDelayMs); - await driver.clickElement(By.css('#send')) + await driver.clickElement(By.css('#send')); - const txStatus = await driver.findElement(By.css('#success')) - await driver.wait(until.elementTextMatches(txStatus, /Success/u), 15000) - }) + const txStatus = await driver.findElement(By.css('#success')); + await driver.wait(until.elementTextMatches(txStatus, /Success/u), 15000); + }); it('switches back to MetaMask', async function () { - await driver.switchToWindow(extension) - }) + await driver.switchToWindow(extension); + }); it('should have the correct amount of eth', async function () { const balances = await driver.findElements( By.css('.currency-display-component__text'), - ) - await driver.wait(until.elementTextMatches(balances[0], /1/u), 15000) - const balance = await balances[0].getText() + ); + await driver.wait(until.elementTextMatches(balances[0], /1/u), 15000); + const balance = await balances[0].getText(); - assert.equal(balance, '1') - }) - }) + assert.equal(balance, '1'); + }); + }); describe('backs up the seed phrase', function () { it('should show a backup reminder', async function () { @@ -171,80 +171,80 @@ describe('MetaMask', function () { By.xpath( "//div[contains(@class, 'home-notification__text') and contains(text(), 'Backup your Secret Recovery code to keep your wallet and funds secure')]", ), - ) - assert.equal(backupReminder.length, 1) - }) + ); + assert.equal(backupReminder.length, 1); + }); it('should take the user to the seedphrase backup screen', async function () { - await driver.clickElement(By.css('.home-notification__accept-button')) - await driver.delay(regularDelayMs) - }) + await driver.clickElement(By.css('.home-notification__accept-button')); + await driver.delay(regularDelayMs); + }); - let seedPhrase + let seedPhrase; it('reveals the seed phrase', async function () { const byRevealButton = By.css( '.reveal-seed-phrase__secret-blocker .reveal-seed-phrase__reveal-button', - ) - await driver.clickElement(byRevealButton) - await driver.delay(regularDelayMs) + ); + await driver.clickElement(byRevealButton); + await driver.delay(regularDelayMs); const revealedSeedPhrase = await driver.findElement( By.css('.reveal-seed-phrase__secret-words'), - ) - seedPhrase = await revealedSeedPhrase.getText() - assert.equal(seedPhrase.split(' ').length, 12) - await driver.delay(regularDelayMs) + ); + seedPhrase = await revealedSeedPhrase.getText(); + assert.equal(seedPhrase.split(' ').length, 12); + await driver.delay(regularDelayMs); await driver.clickElement( By.xpath( `//button[contains(text(), '${enLocaleMessages.next.message}')]`, ), - ) - await driver.delay(regularDelayMs) - }) + ); + await driver.delay(regularDelayMs); + }); async function clickWordAndWait(word) { await driver.clickElement( By.css( `[data-testid="seed-phrase-sorted"] [data-testid="draggable-seed-${word}"]`, ), - ) - await driver.delay(tinyDelayMs) + ); + await driver.delay(tinyDelayMs); } it('can retype the seed phrase', async function () { - const words = seedPhrase.split(' ') + const words = seedPhrase.split(' '); for (const word of words) { - await clickWordAndWait(word) + await clickWordAndWait(word); } await driver.clickElement( By.xpath(`//button[contains(text(), 'Confirm')]`), - ) - await driver.delay(regularDelayMs) - }) + ); + await driver.delay(regularDelayMs); + }); it('can click through the success screen', async function () { await driver.clickElement( By.xpath(`//button[contains(text(), 'All Done')]`), - ) - await driver.delay(regularDelayMs) - }) + ); + await driver.delay(regularDelayMs); + }); it('should have the correct amount of eth', async function () { const balances = await driver.findElements( By.css('.currency-display-component__text'), - ) - await driver.wait(until.elementTextMatches(balances[0], /1/u), 15000) - const balance = await balances[0].getText() + ); + await driver.wait(until.elementTextMatches(balances[0], /1/u), 15000); + const balance = await balances[0].getText(); - assert.equal(balance, '1') - }) + assert.equal(balance, '1'); + }); it('should not show a backup reminder', async function () { - await driver.assertElementNotPresent(By.css('.backup-notification')) - }) - }) -}) + await driver.assertElementNotPresent(By.css('.backup-notification')); + }); + }); +}); diff --git a/test/e2e/metamask-responsive-ui.spec.js b/test/e2e/metamask-responsive-ui.spec.js index 60fe1c901..eab3f498e 100644 --- a/test/e2e/metamask-responsive-ui.spec.js +++ b/test/e2e/metamask-responsive-ui.spec.js @@ -1,287 +1,289 @@ -const assert = require('assert') -const webdriver = require('selenium-webdriver') +const assert = require('assert'); +const webdriver = require('selenium-webdriver'); -const { By, until } = webdriver -const enLocaleMessages = require('../../app/_locales/en/messages.json') -const { tinyDelayMs, regularDelayMs, largeDelayMs } = require('./helpers') -const { buildWebDriver } = require('./webdriver') -const Ganache = require('./ganache') +const { By, until } = webdriver; +const enLocaleMessages = require('../../app/_locales/en/messages.json'); +const { tinyDelayMs, regularDelayMs, largeDelayMs } = require('./helpers'); +const { buildWebDriver } = require('./webdriver'); +const Ganache = require('./ganache'); -const ganacheServer = new Ganache() +const ganacheServer = new Ganache(); describe('MetaMask', function () { - let driver + let driver; const testSeedPhrase = - 'phrase upgrade clock rough situate wedding elder clever doctor stamp excess tent' + 'phrase upgrade clock rough situate wedding elder clever doctor stamp excess tent'; - this.timeout(0) - this.bail(true) + this.timeout(0); + this.bail(true); before(async function () { - await ganacheServer.start() - const result = await buildWebDriver({ responsive: true }) - driver = result.driver - await driver.navigate() - }) + await ganacheServer.start(); + const result = await buildWebDriver({ responsive: true }); + driver = result.driver; + await driver.navigate(); + }); afterEach(async function () { if (process.env.SELENIUM_BROWSER === 'chrome') { - const errors = await driver.checkBrowserForConsoleErrors(driver) + const errors = await driver.checkBrowserForConsoleErrors(driver); if (errors.length) { - const errorReports = errors.map((err) => err.message) + const errorReports = errors.map((err) => err.message); const errorMessage = `Errors found in browser console:\n${errorReports.join( '\n', - )}` - console.error(new Error(errorMessage)) + )}`; + console.error(new Error(errorMessage)); } } if (this.currentTest.state === 'failed') { - await driver.verboseReportOnFailure(this.currentTest.title) + await driver.verboseReportOnFailure(this.currentTest.title); } - }) + }); after(async function () { - await ganacheServer.quit() - await driver.quit() - }) + await ganacheServer.quit(); + await driver.quit(); + }); describe('Going through the first time flow', function () { it('clicks the continue button on the welcome screen', async function () { - await driver.findElement(By.css('.welcome-page__header')) + await driver.findElement(By.css('.welcome-page__header')); await driver.clickElement( By.xpath( `//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`, ), - ) - await driver.delay(largeDelayMs) - }) + ); + await driver.delay(largeDelayMs); + }); it('clicks the "Create New Wallet" option', async function () { await driver.clickElement( By.xpath(`//button[contains(text(), 'Create a Wallet')]`), - ) - await driver.delay(largeDelayMs) - }) + ); + await driver.delay(largeDelayMs); + }); it('clicks the "I Agree" option on the metametrics opt-in screen', async function () { - await driver.clickElement(By.css('.btn-primary')) - await driver.delay(largeDelayMs) - }) + await driver.clickElement(By.css('.btn-primary')); + await driver.delay(largeDelayMs); + }); it('accepts a secure password', async function () { const passwordBox = await driver.findElement( By.css('.first-time-flow__form #create-password'), - ) + ); const passwordBoxConfirm = await driver.findElement( By.css('.first-time-flow__form #confirm-password'), - ) + ); - await passwordBox.sendKeys('correct horse battery staple') - await passwordBoxConfirm.sendKeys('correct horse battery staple') + await passwordBox.sendKeys('correct horse battery staple'); + await passwordBoxConfirm.sendKeys('correct horse battery staple'); - await driver.clickElement(By.css('.first-time-flow__checkbox')) + await driver.clickElement(By.css('.first-time-flow__checkbox')); - await driver.clickElement(By.css('.first-time-flow__form button')) - await driver.delay(regularDelayMs) - }) + await driver.clickElement(By.css('.first-time-flow__form button')); + await driver.delay(regularDelayMs); + }); - let seedPhrase + let seedPhrase; it('reveals the seed phrase', async function () { const byRevealButton = By.css( '.reveal-seed-phrase__secret-blocker .reveal-seed-phrase__reveal-button', - ) - await driver.clickElement(byRevealButton) - await driver.delay(regularDelayMs) + ); + await driver.clickElement(byRevealButton); + await driver.delay(regularDelayMs); const revealedSeedPhrase = await driver.findElement( By.css('.reveal-seed-phrase__secret-words'), - ) - seedPhrase = await revealedSeedPhrase.getText() - assert.equal(seedPhrase.split(' ').length, 12) - await driver.delay(regularDelayMs) + ); + seedPhrase = await revealedSeedPhrase.getText(); + assert.equal(seedPhrase.split(' ').length, 12); + await driver.delay(regularDelayMs); await driver.clickElement( By.xpath( `//button[contains(text(), '${enLocaleMessages.next.message}')]`, ), - ) - await driver.delay(regularDelayMs) - }) + ); + await driver.delay(regularDelayMs); + }); async function clickWordAndWait(word) { await driver.clickElement( By.css( `[data-testid="seed-phrase-sorted"] [data-testid="draggable-seed-${word}"]`, ), - ) - await driver.delay(tinyDelayMs) + ); + await driver.delay(tinyDelayMs); } it('can retype the seed phrase', async function () { - const words = seedPhrase.split(' ') + const words = seedPhrase.split(' '); for (const word of words) { - await clickWordAndWait(word) + await clickWordAndWait(word); } await driver.clickElement( By.xpath(`//button[contains(text(), 'Confirm')]`), - ) - await driver.delay(regularDelayMs) - }) + ); + await driver.delay(regularDelayMs); + }); it('clicks through the success screen', async function () { await driver.findElement( By.xpath(`//div[contains(text(), 'Congratulations')]`), - ) + ); await driver.clickElement( By.xpath( `//button[contains(text(), '${enLocaleMessages.endOfFlowMessage10.message}')]`, ), - ) - await driver.delay(regularDelayMs) - }) - }) + ); + await driver.delay(regularDelayMs); + }); + }); describe('Show account information', function () { it('show account details dropdown menu', async function () { await driver.clickElement( By.css('[data-testid="account-options-menu-button"]'), - ) + ); const options = await driver.findElements( By.css('.account-options-menu .menu-item'), - ) - assert.equal(options.length, 3) // HD Wallet type does not have to show the Remove Account option + ); + assert.equal(options.length, 3); // HD Wallet type does not have to show the Remove Account option // click outside of menu to dismiss // account menu button chosen because the menu never covers it. - await driver.clickPoint(By.css('.account-menu__icon'), 0, 0) - await driver.delay(regularDelayMs) - }) - }) + await driver.clickPoint(By.css('.account-menu__icon'), 0, 0); + await driver.delay(regularDelayMs); + }); + }); describe('Import seed phrase', function () { it('logs out of the vault', async function () { - await driver.clickElement(By.css('.account-menu__icon')) - await driver.delay(regularDelayMs) + await driver.clickElement(By.css('.account-menu__icon')); + await driver.delay(regularDelayMs); const lockButton = await driver.findClickableElement( By.css('.account-menu__lock-button'), - ) - assert.equal(await lockButton.getText(), 'Lock') - await lockButton.click() - await driver.delay(regularDelayMs) - }) + ); + assert.equal(await lockButton.getText(), 'Lock'); + await lockButton.click(); + await driver.delay(regularDelayMs); + }); it('imports seed phrase', async function () { const restoreSeedLink = await driver.findClickableElement( By.css('.unlock-page__link--import'), - ) + ); assert.equal( await restoreSeedLink.getText(), 'Import using account seed phrase', - ) - await restoreSeedLink.click() - await driver.delay(regularDelayMs) + ); + await restoreSeedLink.click(); + await driver.delay(regularDelayMs); - await driver.clickElement(By.css('.import-account__checkbox-container')) + await driver.clickElement(By.css('.import-account__checkbox-container')); - const seedTextArea = await driver.findElement(By.css('textarea')) - await seedTextArea.sendKeys(testSeedPhrase) - await driver.delay(regularDelayMs) + const seedTextArea = await driver.findElement(By.css('textarea')); + await seedTextArea.sendKeys(testSeedPhrase); + await driver.delay(regularDelayMs); - const passwordInputs = await driver.findElements(By.css('input')) - await driver.delay(regularDelayMs) + const passwordInputs = await driver.findElements(By.css('input')); + await driver.delay(regularDelayMs); - await passwordInputs[0].sendKeys('correct horse battery staple') - await passwordInputs[1].sendKeys('correct horse battery staple') + await passwordInputs[0].sendKeys('correct horse battery staple'); + await passwordInputs[1].sendKeys('correct horse battery staple'); await driver.clickElement( By.xpath( `//button[contains(text(), '${enLocaleMessages.restore.message}')]`, ), - ) - await driver.delay(regularDelayMs) - }) + ); + await driver.delay(regularDelayMs); + }); it('switches to localhost', async function () { - await driver.clickElement(By.css('.network-display')) - await driver.delay(regularDelayMs) + await driver.clickElement(By.css('.network-display')); + await driver.delay(regularDelayMs); await driver.clickElement( By.xpath( `//span[contains(@class, 'network-name-item') and contains(text(), 'Localhost 8545')]`, ), - ) - await driver.delay(largeDelayMs * 2) - }) + ); + await driver.delay(largeDelayMs * 2); + }); it('balance renders', async function () { const balance = await driver.findElement( By.css('[data-testid="eth-overview__primary-currency"]'), - ) - await driver.wait(until.elementTextMatches(balance, /100\s*ETH/u)) - await driver.delay(regularDelayMs) - }) - }) + ); + await driver.wait(until.elementTextMatches(balance, /100\s*ETH/u)); + await driver.delay(regularDelayMs); + }); + }); describe('Send ETH from inside MetaMask', function () { it('starts to send a transaction', async function () { - await driver.clickElement(By.css('[data-testid="eth-overview-send"]')) - await driver.delay(regularDelayMs) + await driver.clickElement(By.css('[data-testid="eth-overview-send"]')); + await driver.delay(regularDelayMs); const inputAddress = await driver.findElement( By.css('input[placeholder="Search, public address (0x), or ENS"]'), - ) - await inputAddress.sendKeys('0x2f318C334780961FB129D2a6c30D0763d9a5C970') + ); + await inputAddress.sendKeys('0x2f318C334780961FB129D2a6c30D0763d9a5C970'); - const inputAmount = await driver.findElement(By.css('.unit-input__input')) - await inputAmount.sendKeys('1') + const inputAmount = await driver.findElement( + By.css('.unit-input__input'), + ); + await inputAmount.sendKeys('1'); - const inputValue = await inputAmount.getAttribute('value') - assert.equal(inputValue, '1') - await driver.delay(regularDelayMs) - }) + const inputValue = await inputAmount.getAttribute('value'); + assert.equal(inputValue, '1'); + await driver.delay(regularDelayMs); + }); it('opens and closes the gas modal', async function () { // Set the gas limit - await driver.clickElement(By.css('.advanced-gas-options-btn')) - await driver.delay(regularDelayMs) + await driver.clickElement(By.css('.advanced-gas-options-btn')); + await driver.delay(regularDelayMs); - const gasModal = await driver.findElement(By.css('span .modal')) + const gasModal = await driver.findElement(By.css('span .modal')); - await driver.clickElement(By.css('.page-container__header-close-text')) - await driver.wait(until.stalenessOf(gasModal), 10000) - await driver.delay(regularDelayMs) - }) + await driver.clickElement(By.css('.page-container__header-close-text')); + await driver.wait(until.stalenessOf(gasModal), 10000); + await driver.delay(regularDelayMs); + }); it('clicks through to the confirm screen', async function () { // Continue to next screen - await driver.clickElement(By.xpath(`//button[contains(text(), 'Next')]`)) - await driver.delay(regularDelayMs) - }) + await driver.clickElement(By.xpath(`//button[contains(text(), 'Next')]`)); + await driver.delay(regularDelayMs); + }); it('confirms the transaction', async function () { await driver.clickElement( By.xpath(`//button[contains(text(), 'Confirm')]`), - ) - }) + ); + }); it('finds the transaction in the transactions list', async function () { - await driver.clickElement(By.css('[data-testid="home__activity-tab"]')) + await driver.clickElement(By.css('[data-testid="home__activity-tab"]')); await driver.wait(async () => { const confirmedTxes = await driver.findElements( By.css( '.transaction-list__completed-transactions .transaction-list-item', ), - ) - return confirmedTxes.length === 1 - }, 10000) + ); + return confirmedTxes.length === 1; + }, 10000); const txValues = await driver.findElement( By.css('.transaction-list-item__primary-currency'), - ) - await driver.wait(until.elementTextMatches(txValues, /-1\s*ETH/u), 10000) - }) - }) -}) + ); + await driver.wait(until.elementTextMatches(txValues, /-1\s*ETH/u), 10000); + }); + }); +}); diff --git a/test/e2e/metamask-ui.spec.js b/test/e2e/metamask-ui.spec.js index da6d159f6..4ac2ee14d 100644 --- a/test/e2e/metamask-ui.spec.js +++ b/test/e2e/metamask-ui.spec.js @@ -1,390 +1,394 @@ -const assert = require('assert') -const webdriver = require('selenium-webdriver') +const assert = require('assert'); +const webdriver = require('selenium-webdriver'); -const { By, Key, until } = webdriver -const enLocaleMessages = require('../../app/_locales/en/messages.json') -const { tinyDelayMs, regularDelayMs, largeDelayMs } = require('./helpers') -const { buildWebDriver } = require('./webdriver') -const Ganache = require('./ganache') +const { By, Key, until } = webdriver; +const enLocaleMessages = require('../../app/_locales/en/messages.json'); +const { tinyDelayMs, regularDelayMs, largeDelayMs } = require('./helpers'); +const { buildWebDriver } = require('./webdriver'); +const Ganache = require('./ganache'); -const ganacheServer = new Ganache() +const ganacheServer = new Ganache(); describe('MetaMask', function () { - let driver - let tokenAddress + let driver; + let tokenAddress; const testSeedPhrase = - 'phrase upgrade clock rough situate wedding elder clever doctor stamp excess tent' + 'phrase upgrade clock rough situate wedding elder clever doctor stamp excess tent'; - this.timeout(0) - this.bail(true) + this.timeout(0); + this.bail(true); before(async function () { - await ganacheServer.start() - const result = await buildWebDriver() - driver = result.driver - await driver.navigate() - }) + await ganacheServer.start(); + const result = await buildWebDriver(); + driver = result.driver; + await driver.navigate(); + }); afterEach(async function () { if (process.env.SELENIUM_BROWSER === 'chrome') { - const errors = await driver.checkBrowserForConsoleErrors(driver) + const errors = await driver.checkBrowserForConsoleErrors(driver); if (errors.length) { - const errorReports = errors.map((err) => err.message) + const errorReports = errors.map((err) => err.message); const errorMessage = `Errors found in browser console:\n${errorReports.join( '\n', - )}` - console.error(new Error(errorMessage)) + )}`; + console.error(new Error(errorMessage)); } } if (this.currentTest.state === 'failed') { - await driver.verboseReportOnFailure(this.currentTest.title) + await driver.verboseReportOnFailure(this.currentTest.title); } - }) + }); after(async function () { - await ganacheServer.quit() - await driver.quit() - }) + await ganacheServer.quit(); + await driver.quit(); + }); describe('Going through the first time flow', function () { it('clicks the continue button on the welcome screen', async function () { - await driver.findElement(By.css('.welcome-page__header')) + await driver.findElement(By.css('.welcome-page__header')); await driver.clickElement( By.xpath( `//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`, ), - ) - await driver.delay(largeDelayMs) - }) + ); + await driver.delay(largeDelayMs); + }); it('clicks the "Create New Wallet" option', async function () { await driver.clickElement( By.xpath(`//button[contains(text(), 'Create a Wallet')]`), - ) - await driver.delay(largeDelayMs) - }) + ); + await driver.delay(largeDelayMs); + }); it('clicks the "No thanks" option on the metametrics opt-in screen', async function () { - await driver.clickElement(By.css('.btn-default')) - await driver.delay(largeDelayMs) - }) + await driver.clickElement(By.css('.btn-default')); + await driver.delay(largeDelayMs); + }); it('accepts a secure password', async function () { const passwordBox = await driver.findElement( By.css('.first-time-flow__form #create-password'), - ) + ); const passwordBoxConfirm = await driver.findElement( By.css('.first-time-flow__form #confirm-password'), - ) + ); - await passwordBox.sendKeys('correct horse battery staple') - await passwordBoxConfirm.sendKeys('correct horse battery staple') + await passwordBox.sendKeys('correct horse battery staple'); + await passwordBoxConfirm.sendKeys('correct horse battery staple'); - await driver.clickElement(By.css('.first-time-flow__checkbox')) + await driver.clickElement(By.css('.first-time-flow__checkbox')); - await driver.clickElement(By.css('.first-time-flow__form button')) - await driver.delay(regularDelayMs) - }) + await driver.clickElement(By.css('.first-time-flow__form button')); + await driver.delay(regularDelayMs); + }); - let seedPhrase + let seedPhrase; it('reveals the seed phrase', async function () { const byRevealButton = By.css( '.reveal-seed-phrase__secret-blocker .reveal-seed-phrase__reveal-button', - ) - await driver.findElement(byRevealButton) - await driver.clickElement(byRevealButton) - await driver.delay(regularDelayMs) + ); + await driver.findElement(byRevealButton); + await driver.clickElement(byRevealButton); + await driver.delay(regularDelayMs); const revealedSeedPhrase = await driver.findElement( By.css('.reveal-seed-phrase__secret-words'), - ) - seedPhrase = await revealedSeedPhrase.getText() - assert.equal(seedPhrase.split(' ').length, 12) - await driver.delay(regularDelayMs) + ); + seedPhrase = await revealedSeedPhrase.getText(); + assert.equal(seedPhrase.split(' ').length, 12); + await driver.delay(regularDelayMs); await driver.clickElement( By.xpath( `//button[contains(text(), '${enLocaleMessages.next.message}')]`, ), - ) - await driver.delay(regularDelayMs) - }) + ); + await driver.delay(regularDelayMs); + }); async function clickWordAndWait(word) { await driver.clickElement( By.css( `[data-testid="seed-phrase-sorted"] [data-testid="draggable-seed-${word}"]`, ), - ) - await driver.delay(tinyDelayMs) + ); + await driver.delay(tinyDelayMs); } it('can retype the seed phrase', async function () { - const words = seedPhrase.split(' ') + const words = seedPhrase.split(' '); for (const word of words) { - await clickWordAndWait(word) + await clickWordAndWait(word); } await driver.clickElement( By.xpath(`//button[contains(text(), 'Confirm')]`), - ) - await driver.delay(regularDelayMs) - }) + ); + await driver.delay(regularDelayMs); + }); it('clicks through the success screen', async function () { await driver.findElement( By.xpath(`//div[contains(text(), 'Congratulations')]`), - ) + ); await driver.clickElement( By.xpath( `//button[contains(text(), '${enLocaleMessages.endOfFlowMessage10.message}')]`, ), - ) - await driver.delay(regularDelayMs) - }) - }) + ); + await driver.delay(regularDelayMs); + }); + }); describe('Show account information', function () { it('shows the QR code for the account', async function () { await driver.clickElement( By.css('[data-testid="account-options-menu-button"]'), - ) + ); await driver.clickElement( By.css('[data-testid="account-options-menu__account-details"]'), - ) - await driver.findVisibleElement(By.css('.qr-code__wrapper')) - await driver.delay(regularDelayMs) + ); + await driver.findVisibleElement(By.css('.qr-code__wrapper')); + await driver.delay(regularDelayMs); - const accountModal = await driver.findElement(By.css('span .modal')) - await driver.clickElement(By.css('.account-modal__close')) + const accountModal = await driver.findElement(By.css('span .modal')); + await driver.clickElement(By.css('.account-modal__close')); - await driver.wait(until.stalenessOf(accountModal)) - await driver.delay(regularDelayMs) - }) - }) + await driver.wait(until.stalenessOf(accountModal)); + await driver.delay(regularDelayMs); + }); + }); describe('Lock an unlock', function () { it('logs out of the account', async function () { - await driver.clickElement(By.css('.account-menu__icon')) - await driver.delay(regularDelayMs) + await driver.clickElement(By.css('.account-menu__icon')); + await driver.delay(regularDelayMs); const lockButton = await driver.findClickableElement( By.css('.account-menu__lock-button'), - ) - assert.equal(await lockButton.getText(), 'Lock') - await lockButton.click() - await driver.delay(regularDelayMs) - }) + ); + assert.equal(await lockButton.getText(), 'Lock'); + await lockButton.click(); + await driver.delay(regularDelayMs); + }); it('accepts the account password after lock', async function () { - const passwordField = await driver.findElement(By.id('password')) - await passwordField.sendKeys('correct horse battery staple') - await passwordField.sendKeys(Key.ENTER) - await driver.delay(largeDelayMs * 4) - }) - }) + const passwordField = await driver.findElement(By.id('password')); + await passwordField.sendKeys('correct horse battery staple'); + await passwordField.sendKeys(Key.ENTER); + await driver.delay(largeDelayMs * 4); + }); + }); describe('Add account', function () { it('choose Create Account from the account menu', async function () { - await driver.clickElement(By.css('.account-menu__icon')) - await driver.delay(regularDelayMs) + await driver.clickElement(By.css('.account-menu__icon')); + await driver.delay(regularDelayMs); await driver.clickElement( By.xpath(`//div[contains(text(), 'Create Account')]`), - ) - await driver.delay(regularDelayMs) - }) + ); + await driver.delay(regularDelayMs); + }); it('set account name', async function () { const accountName = await driver.findElement( By.css('.new-account-create-form input'), - ) - await accountName.sendKeys('2nd account') - await driver.delay(regularDelayMs) + ); + await accountName.sendKeys('2nd account'); + await driver.delay(regularDelayMs); await driver.clickElement( By.xpath(`//button[contains(text(), 'Create')]`), - ) - await driver.delay(largeDelayMs) - }) + ); + await driver.delay(largeDelayMs); + }); it('should display correct account name', async function () { const accountName = await driver.findElement( By.css('.selected-account__name'), - ) - assert.equal(await accountName.getText(), '2nd account') - await driver.delay(regularDelayMs) - }) - }) + ); + assert.equal(await accountName.getText(), '2nd account'); + await driver.delay(regularDelayMs); + }); + }); describe('Import seed phrase', function () { it('logs out of the vault', async function () { - await driver.clickElement(By.css('.account-menu__icon')) - await driver.delay(regularDelayMs) + await driver.clickElement(By.css('.account-menu__icon')); + await driver.delay(regularDelayMs); const lockButton = await driver.findClickableElement( By.css('.account-menu__lock-button'), - ) - assert.equal(await lockButton.getText(), 'Lock') - await lockButton.click() - await driver.delay(regularDelayMs) - }) + ); + assert.equal(await lockButton.getText(), 'Lock'); + await lockButton.click(); + await driver.delay(regularDelayMs); + }); it('imports seed phrase', async function () { const restoreSeedLink = await driver.findClickableElement( By.css('.unlock-page__link--import'), - ) + ); assert.equal( await restoreSeedLink.getText(), 'Import using account seed phrase', - ) - await restoreSeedLink.click() - await driver.delay(regularDelayMs) + ); + await restoreSeedLink.click(); + await driver.delay(regularDelayMs); - await driver.clickElement(By.css('.import-account__checkbox-container')) + await driver.clickElement(By.css('.import-account__checkbox-container')); - const seedTextArea = await driver.findElement(By.css('textarea')) - await seedTextArea.sendKeys(testSeedPhrase) - await driver.delay(regularDelayMs) + const seedTextArea = await driver.findElement(By.css('textarea')); + await seedTextArea.sendKeys(testSeedPhrase); + await driver.delay(regularDelayMs); - const passwordInputs = await driver.findElements(By.css('input')) - await driver.delay(regularDelayMs) + const passwordInputs = await driver.findElements(By.css('input')); + await driver.delay(regularDelayMs); - await passwordInputs[0].sendKeys('correct horse battery staple') - await passwordInputs[1].sendKeys('correct horse battery staple') + await passwordInputs[0].sendKeys('correct horse battery staple'); + await passwordInputs[1].sendKeys('correct horse battery staple'); await driver.clickElement( By.xpath( `//button[contains(text(), '${enLocaleMessages.restore.message}')]`, ), - ) - await driver.delay(regularDelayMs) - }) + ); + await driver.delay(regularDelayMs); + }); it('balance renders', async function () { const balance = await driver.findElement( By.css('[data-testid="wallet-balance"] .list-item__heading'), - ) - await driver.wait(until.elementTextMatches(balance, /100\s*ETH/u)) - await driver.delay(regularDelayMs) - }) - }) + ); + await driver.wait(until.elementTextMatches(balance, /100\s*ETH/u)); + await driver.delay(regularDelayMs); + }); + }); describe('Send ETH from inside MetaMask using default gas', function () { it('starts a send transaction', async function () { - await driver.clickElement(By.css('[data-testid="eth-overview-send"]')) - await driver.delay(regularDelayMs) + await driver.clickElement(By.css('[data-testid="eth-overview-send"]')); + await driver.delay(regularDelayMs); const inputAddress = await driver.findElement( By.css('input[placeholder="Search, public address (0x), or ENS"]'), - ) - await inputAddress.sendKeys('0x2f318C334780961FB129D2a6c30D0763d9a5C970') + ); + await inputAddress.sendKeys('0x2f318C334780961FB129D2a6c30D0763d9a5C970'); - const inputAmount = await driver.findElement(By.css('.unit-input__input')) - await inputAmount.sendKeys('1000') + const inputAmount = await driver.findElement( + By.css('.unit-input__input'), + ); + await inputAmount.sendKeys('1000'); const errorAmount = await driver.findElement( By.css('.send-v2__error-amount'), - ) + ); assert.equal( await errorAmount.getText(), 'Insufficient funds.', 'send screen should render an insufficient fund error message', - ) + ); - await inputAmount.sendKeys(Key.BACK_SPACE) - await driver.delay(50) - await inputAmount.sendKeys(Key.BACK_SPACE) - await driver.delay(50) - await inputAmount.sendKeys(Key.BACK_SPACE) - await driver.delay(tinyDelayMs) + await inputAmount.sendKeys(Key.BACK_SPACE); + await driver.delay(50); + await inputAmount.sendKeys(Key.BACK_SPACE); + await driver.delay(50); + await inputAmount.sendKeys(Key.BACK_SPACE); + await driver.delay(tinyDelayMs); - await driver.assertElementNotPresent(By.css('.send-v2__error-amount')) + await driver.assertElementNotPresent(By.css('.send-v2__error-amount')); const amountMax = await driver.findClickableElement( By.css('.send-v2__amount-max'), - ) - await amountMax.click() + ); + await amountMax.click(); - let inputValue = await inputAmount.getAttribute('value') + let inputValue = await inputAmount.getAttribute('value'); - assert(Number(inputValue) > 99) + assert(Number(inputValue) > 99); - await amountMax.click() + await amountMax.click(); - assert.equal(await inputAmount.isEnabled(), true) + assert.equal(await inputAmount.isEnabled(), true); - await inputAmount.sendKeys('1') + await inputAmount.sendKeys('1'); - inputValue = await inputAmount.getAttribute('value') - assert.equal(inputValue, '1') - await driver.delay(regularDelayMs) + inputValue = await inputAmount.getAttribute('value'); + assert.equal(inputValue, '1'); + await driver.delay(regularDelayMs); // Continue to next screen - await driver.clickElement(By.xpath(`//button[contains(text(), 'Next')]`)) - await driver.delay(regularDelayMs) - }) + await driver.clickElement(By.xpath(`//button[contains(text(), 'Next')]`)); + await driver.delay(regularDelayMs); + }); it('confirms the transaction', async function () { await driver.clickElement( By.xpath(`//button[contains(text(), 'Confirm')]`), - ) - await driver.delay(largeDelayMs * 2) - }) + ); + await driver.delay(largeDelayMs * 2); + }); it('finds the transaction in the transactions list', async function () { - await driver.clickElement(By.css('[data-testid="home__activity-tab"]')) + await driver.clickElement(By.css('[data-testid="home__activity-tab"]')); await driver.wait(async () => { const confirmedTxes = await driver.findElements( By.css( '.transaction-list__completed-transactions .transaction-list-item', ), - ) - return confirmedTxes.length === 1 - }, 10000) + ); + return confirmedTxes.length === 1; + }, 10000); const txValues = await driver.findElement( By.css('.transaction-list-item__primary-currency'), - ) - await driver.wait(until.elementTextMatches(txValues, /-1\s*ETH/u), 10000) - }) - }) + ); + await driver.wait(until.elementTextMatches(txValues, /-1\s*ETH/u), 10000); + }); + }); describe('Send ETH from inside MetaMask using fast gas option', function () { it('starts a send transaction', async function () { - await driver.clickElement(By.css('[data-testid="eth-overview-send"]')) - await driver.delay(regularDelayMs) + await driver.clickElement(By.css('[data-testid="eth-overview-send"]')); + await driver.delay(regularDelayMs); const inputAddress = await driver.findElement( By.css('input[placeholder="Search, public address (0x), or ENS"]'), - ) - await inputAddress.sendKeys('0x2f318C334780961FB129D2a6c30D0763d9a5C970') + ); + await inputAddress.sendKeys('0x2f318C334780961FB129D2a6c30D0763d9a5C970'); - const inputAmount = await driver.findElement(By.css('.unit-input__input')) - await inputAmount.sendKeys('1') + const inputAmount = await driver.findElement( + By.css('.unit-input__input'), + ); + await inputAmount.sendKeys('1'); - const inputValue = await inputAmount.getAttribute('value') - assert.equal(inputValue, '1') + const inputValue = await inputAmount.getAttribute('value'); + assert.equal(inputValue, '1'); // Set the gas price await driver.clickElement( By.xpath(`//button/div/div[contains(text(), "Fast")]`), - ) - await driver.delay(regularDelayMs) + ); + await driver.delay(regularDelayMs); // Continue to next screen - await driver.clickElement(By.xpath(`//button[contains(text(), 'Next')]`)) - await driver.delay(regularDelayMs) - }) + await driver.clickElement(By.xpath(`//button[contains(text(), 'Next')]`)); + await driver.delay(regularDelayMs); + }); it('confirms the transaction', async function () { await driver.clickElement( By.xpath(`//button[contains(text(), 'Confirm')]`), - ) - await driver.delay(largeDelayMs) - }) + ); + await driver.delay(largeDelayMs); + }); it('finds the transaction in the transactions list', async function () { await driver.wait(async () => { @@ -392,59 +396,61 @@ describe('MetaMask', function () { By.css( '.transaction-list__completed-transactions .transaction-list-item', ), - ) - return confirmedTxes.length === 2 - }, 10000) + ); + return confirmedTxes.length === 2; + }, 10000); const txValues = await driver.findElement( By.css('.transaction-list-item__primary-currency'), - ) - await driver.wait(until.elementTextMatches(txValues, /-1\s*ETH/u), 10000) - }) - }) + ); + await driver.wait(until.elementTextMatches(txValues, /-1\s*ETH/u), 10000); + }); + }); describe('Send ETH from inside MetaMask using advanced gas modal', function () { it('starts a send transaction', async function () { - await driver.clickElement(By.css('[data-testid="eth-overview-send"]')) - await driver.delay(regularDelayMs) + await driver.clickElement(By.css('[data-testid="eth-overview-send"]')); + await driver.delay(regularDelayMs); const inputAddress = await driver.findElement( By.css('input[placeholder="Search, public address (0x), or ENS"]'), - ) - await inputAddress.sendKeys('0x2f318C334780961FB129D2a6c30D0763d9a5C970') + ); + await inputAddress.sendKeys('0x2f318C334780961FB129D2a6c30D0763d9a5C970'); - const inputAmount = await driver.findElement(By.css('.unit-input__input')) - await inputAmount.sendKeys('1') + const inputAmount = await driver.findElement( + By.css('.unit-input__input'), + ); + await inputAmount.sendKeys('1'); - const inputValue = await inputAmount.getAttribute('value') - assert.equal(inputValue, '1') + const inputValue = await inputAmount.getAttribute('value'); + assert.equal(inputValue, '1'); // Set the gas limit - await driver.clickElement(By.css('.advanced-gas-options-btn')) - await driver.delay(regularDelayMs) + await driver.clickElement(By.css('.advanced-gas-options-btn')); + await driver.delay(regularDelayMs); - const gasModal = await driver.findElement(By.css('span .modal')) - await driver.clickElement(By.xpath(`//button[contains(text(), 'Save')]`)) - await driver.wait(until.stalenessOf(gasModal)) - await driver.delay(regularDelayMs) + const gasModal = await driver.findElement(By.css('span .modal')); + await driver.clickElement(By.xpath(`//button[contains(text(), 'Save')]`)); + await driver.wait(until.stalenessOf(gasModal)); + await driver.delay(regularDelayMs); // Continue to next screen - await driver.clickElement(By.xpath(`//button[contains(text(), 'Next')]`)) - await driver.delay(regularDelayMs) - }) + await driver.clickElement(By.xpath(`//button[contains(text(), 'Next')]`)); + await driver.delay(regularDelayMs); + }); it('confirms the transaction', async function () { const transactionAmounts = await driver.findElements( By.css('.currency-display-component__text'), - ) - const transactionAmount = transactionAmounts[0] - assert.equal(await transactionAmount.getText(), '1') + ); + const transactionAmount = transactionAmounts[0]; + assert.equal(await transactionAmount.getText(), '1'); await driver.clickElement( By.xpath(`//button[contains(text(), 'Confirm')]`), - ) - await driver.delay(largeDelayMs) - }) + ); + await driver.delay(largeDelayMs); + }); it('finds the transaction in the transactions list', async function () { await driver.wait(async () => { @@ -452,140 +458,144 @@ describe('MetaMask', function () { By.css( '.transaction-list__completed-transactions .transaction-list-item', ), - ) - return confirmedTxes.length === 3 - }, 10000) + ); + return confirmedTxes.length === 3; + }, 10000); const txValues = await driver.findElement( By.css('.transaction-list-item__primary-currency'), - ) - await driver.wait(until.elementTextMatches(txValues, /-1\s*ETH/u), 10000) - }) - }) + ); + await driver.wait(until.elementTextMatches(txValues, /-1\s*ETH/u), 10000); + }); + }); describe('Send ETH from dapp using advanced gas controls', function () { - let windowHandles - let extension - let popup - let dapp + let windowHandles; + let extension; + let popup; + let dapp; it('goes to the settings screen', async function () { - await driver.clickElement(By.css('.account-menu__icon')) - await driver.delay(regularDelayMs) + await driver.clickElement(By.css('.account-menu__icon')); + await driver.delay(regularDelayMs); - await driver.clickElement(By.xpath(`//div[contains(text(), 'Settings')]`)) + await driver.clickElement( + By.xpath(`//div[contains(text(), 'Settings')]`), + ); // await driver.findElement(By.css('.tab-bar')) - await driver.clickElement(By.xpath(`//div[contains(text(), 'Advanced')]`)) - await driver.delay(regularDelayMs) + await driver.clickElement( + By.xpath(`//div[contains(text(), 'Advanced')]`), + ); + await driver.delay(regularDelayMs); await driver.clickElement( By.css( '[data-testid="advanced-setting-show-testnet-conversion"] .settings-page__content-item-col > div > div', ), - ) + ); const advancedGasTitle = await driver.findElement( By.xpath(`//span[contains(text(), 'Advanced gas controls')]`), - ) - await driver.scrollToElement(advancedGasTitle) + ); + await driver.scrollToElement(advancedGasTitle); await driver.clickElement( By.css( '[data-testid="advanced-setting-advanced-gas-inline"] .settings-page__content-item-col > div > div', ), - ) - windowHandles = await driver.getAllWindowHandles() - extension = windowHandles[0] - await driver.closeAllWindowHandlesExcept([extension]) + ); + windowHandles = await driver.getAllWindowHandles(); + extension = windowHandles[0]; + await driver.closeAllWindowHandlesExcept([extension]); - await driver.clickElement(By.css('.app-header__logo-container')) + await driver.clickElement(By.css('.app-header__logo-container')); - await driver.delay(largeDelayMs) - }) + await driver.delay(largeDelayMs); + }); it('connects the dapp', async function () { - await driver.openNewPage('http://127.0.0.1:8080/') - await driver.delay(regularDelayMs) + await driver.openNewPage('http://127.0.0.1:8080/'); + await driver.delay(regularDelayMs); await driver.clickElement( By.xpath(`//button[contains(text(), 'Connect')]`), - ) + ); - await driver.delay(regularDelayMs) + await driver.delay(regularDelayMs); - await driver.waitUntilXWindowHandles(3) - windowHandles = await driver.getAllWindowHandles() + await driver.waitUntilXWindowHandles(3); + windowHandles = await driver.getAllWindowHandles(); - extension = windowHandles[0] + extension = windowHandles[0]; dapp = await driver.switchToWindowWithTitle( 'E2E Test Dapp', windowHandles, - ) + ); popup = windowHandles.find( (handle) => handle !== extension && handle !== dapp, - ) + ); - await driver.switchToWindow(popup) + await driver.switchToWindow(popup); - await driver.delay(regularDelayMs) + await driver.delay(regularDelayMs); - await driver.clickElement(By.xpath(`//button[contains(text(), 'Next')]`)) + await driver.clickElement(By.xpath(`//button[contains(text(), 'Next')]`)); await driver.clickElement( By.xpath(`//button[contains(text(), 'Connect')]`), - ) + ); - await driver.waitUntilXWindowHandles(2) - await driver.switchToWindow(dapp) - await driver.delay(regularDelayMs) - }) + await driver.waitUntilXWindowHandles(2); + await driver.switchToWindow(dapp); + await driver.delay(regularDelayMs); + }); it('initiates a send from the dapp', async function () { await driver.clickElement( By.xpath(`//button[contains(text(), 'Send')]`), 10000, - ) - await driver.delay(2000) + ); + await driver.delay(2000); - windowHandles = await driver.getAllWindowHandles() + windowHandles = await driver.getAllWindowHandles(); await driver.switchToWindowWithTitle( 'MetaMask Notification', windowHandles, - ) - await driver.delay(regularDelayMs) + ); + await driver.delay(regularDelayMs); await driver.assertElementNotPresent( By.xpath(`//li[contains(text(), 'Data')]`), - ) + ); const [gasPriceInput, gasLimitInput] = await driver.findElements( By.css('.advanced-gas-inputs__gas-edit-row__input'), - ) + ); - await gasPriceInput.clear() - await driver.delay(50) - await gasPriceInput.sendKeys('10') - await driver.delay(50) - await driver.delay(tinyDelayMs) - await driver.delay(50) + await gasPriceInput.clear(); + await driver.delay(50); + await gasPriceInput.sendKeys('10'); + await driver.delay(50); + await driver.delay(tinyDelayMs); + await driver.delay(50); - await gasLimitInput.clear() - await driver.delay(50) - await gasLimitInput.sendKeys('25000') + await gasLimitInput.clear(); + await driver.delay(50); + await gasLimitInput.sendKeys('25000'); - await driver.delay(1000) + await driver.delay(1000); await driver.clickElement( By.xpath(`//button[contains(text(), 'Confirm')]`), 10000, - ) - await driver.delay(regularDelayMs) + ); + await driver.delay(regularDelayMs); - await driver.waitUntilXWindowHandles(2) - await driver.switchToWindow(extension) - await driver.delay(regularDelayMs) - }) + await driver.waitUntilXWindowHandles(2); + await driver.switchToWindow(extension); + await driver.delay(regularDelayMs); + }); it('finds the transaction in the transactions list', async function () { await driver.wait(async () => { @@ -593,620 +603,624 @@ describe('MetaMask', function () { By.css( '.transaction-list__completed-transactions .transaction-list-item', ), - ) - return confirmedTxes.length === 4 - }, 10000) + ); + return confirmedTxes.length === 4; + }, 10000); const txValue = await driver.findClickableElement( By.css('.transaction-list-item__primary-currency'), - ) - await driver.wait(until.elementTextMatches(txValue, /-3\s*ETH/u), 10000) - }) + ); + await driver.wait(until.elementTextMatches(txValue, /-3\s*ETH/u), 10000); + }); it('the transaction has the expected gas price', async function () { const txValue = await driver.findClickableElement( By.css('.transaction-list-item__primary-currency'), - ) - await txValue.click() + ); + await txValue.click(); const popoverCloseButton = await driver.findClickableElement( By.css('.popover-header__button'), - ) + ); const txGasPrice = await driver.findElement( By.css('[data-testid="transaction-breakdown__gas-price"]'), - ) - await driver.wait(until.elementTextMatches(txGasPrice, /^10$/u), 10000) - await popoverCloseButton.click() - }) - }) + ); + await driver.wait(until.elementTextMatches(txGasPrice, /^10$/u), 10000); + await popoverCloseButton.click(); + }); + }); describe('Navigate transactions', function () { it('adds multiple transactions', async function () { - await driver.delay(regularDelayMs) + await driver.delay(regularDelayMs); - await driver.waitUntilXWindowHandles(2) - const windowHandles = await driver.getAllWindowHandles() - const extension = windowHandles[0] - const dapp = windowHandles[1] + await driver.waitUntilXWindowHandles(2); + const windowHandles = await driver.getAllWindowHandles(); + const extension = windowHandles[0]; + const dapp = windowHandles[1]; - await driver.switchToWindow(dapp) - await driver.delay(largeDelayMs) + await driver.switchToWindow(dapp); + await driver.delay(largeDelayMs); const send3eth = await driver.findClickableElement( By.xpath(`//button[contains(text(), 'Send')]`), - ) - await send3eth.click() - await driver.delay(largeDelayMs) + ); + await send3eth.click(); + await driver.delay(largeDelayMs); const contractDeployment = await driver.findClickableElement( By.xpath(`//button[contains(text(), 'Deploy Contract')]`), - ) - await contractDeployment.click() - await driver.delay(largeDelayMs) + ); + await contractDeployment.click(); + await driver.delay(largeDelayMs); - await send3eth.click() - await driver.delay(largeDelayMs) - await contractDeployment.click() - await driver.delay(largeDelayMs) + await send3eth.click(); + await driver.delay(largeDelayMs); + await contractDeployment.click(); + await driver.delay(largeDelayMs); - await driver.switchToWindow(extension) - await driver.delay(regularDelayMs) + await driver.switchToWindow(extension); + await driver.delay(regularDelayMs); - await driver.clickElement(By.css('.transaction-list-item')) - await driver.delay(largeDelayMs) - }) + await driver.clickElement(By.css('.transaction-list-item')); + await driver.delay(largeDelayMs); + }); it('navigates the transactions', async function () { - await driver.clickElement(By.css('[data-testid="next-page"]')) + await driver.clickElement(By.css('[data-testid="next-page"]')); let navigationElement = await driver.findElement( By.css('.confirm-page-container-navigation'), - ) - let navigationText = await navigationElement.getText() + ); + let navigationText = await navigationElement.getText(); assert.equal( navigationText.includes('2'), true, 'changed transaction right', - ) + ); - await driver.clickElement(By.css('[data-testid="next-page"]')) + await driver.clickElement(By.css('[data-testid="next-page"]')); navigationElement = await driver.findElement( By.css('.confirm-page-container-navigation'), - ) - navigationText = await navigationElement.getText() + ); + navigationText = await navigationElement.getText(); assert.equal( navigationText.includes('3'), true, 'changed transaction right', - ) + ); - await driver.clickElement(By.css('[data-testid="next-page"]')) + await driver.clickElement(By.css('[data-testid="next-page"]')); navigationElement = await driver.findElement( By.css('.confirm-page-container-navigation'), - ) - navigationText = await navigationElement.getText() + ); + navigationText = await navigationElement.getText(); assert.equal( navigationText.includes('4'), true, 'changed transaction right', - ) + ); - await driver.clickElement(By.css('[data-testid="first-page"]')) + await driver.clickElement(By.css('[data-testid="first-page"]')); navigationElement = await driver.findElement( By.css('.confirm-page-container-navigation'), - ) - navigationText = await navigationElement.getText() + ); + navigationText = await navigationElement.getText(); assert.equal( navigationText.includes('1'), true, 'navigate to first transaction', - ) + ); - await driver.clickElement(By.css('[data-testid="last-page"]')) + await driver.clickElement(By.css('[data-testid="last-page"]')); navigationElement = await driver.findElement( By.css('.confirm-page-container-navigation'), - ) - navigationText = await navigationElement.getText() + ); + navigationText = await navigationElement.getText(); assert.equal( navigationText.split('4').length, 3, 'navigate to last transaction', - ) + ); - await driver.clickElement(By.css('[data-testid="previous-page"]')) + await driver.clickElement(By.css('[data-testid="previous-page"]')); navigationElement = await driver.findElement( By.css('.confirm-page-container-navigation'), - ) - navigationText = await navigationElement.getText() + ); + navigationText = await navigationElement.getText(); assert.equal( navigationText.includes('3'), true, 'changed transaction left', - ) + ); - await driver.clickElement(By.css('[data-testid="previous-page"]')) + await driver.clickElement(By.css('[data-testid="previous-page"]')); navigationElement = await driver.findElement( By.css('.confirm-page-container-navigation'), - ) - navigationText = await navigationElement.getText() + ); + navigationText = await navigationElement.getText(); assert.equal( navigationText.includes('2'), true, 'changed transaction left', - ) - }) + ); + }); it('adds a transaction while confirm screen is in focus', async function () { let navigationElement = await driver.findElement( By.css('.confirm-page-container-navigation'), - ) - let navigationText = await navigationElement.getText() + ); + let navigationText = await navigationElement.getText(); assert.equal( navigationText.includes('2'), true, 'second transaction in focus', - ) + ); - const windowHandles = await driver.getAllWindowHandles() - const extension = windowHandles[0] - const dapp = windowHandles[1] + const windowHandles = await driver.getAllWindowHandles(); + const extension = windowHandles[0]; + const dapp = windowHandles[1]; - await driver.switchToWindow(dapp) - await driver.delay(regularDelayMs) + await driver.switchToWindow(dapp); + await driver.delay(regularDelayMs); - await driver.clickElement(By.xpath(`//button[contains(text(), 'Send')]`)) - await driver.delay(regularDelayMs) + await driver.clickElement(By.xpath(`//button[contains(text(), 'Send')]`)); + await driver.delay(regularDelayMs); - await driver.switchToWindow(extension) - await driver.delay(regularDelayMs) + await driver.switchToWindow(extension); + await driver.delay(regularDelayMs); navigationElement = await driver.findElement( By.css('.confirm-page-container-navigation'), - ) - navigationText = await navigationElement.getText() + ); + navigationText = await navigationElement.getText(); assert.equal( navigationText.includes('2'), true, 'correct (same) transaction in focus', - ) - }) + ); + }); it('rejects a transaction', async function () { - await driver.delay(tinyDelayMs) + await driver.delay(tinyDelayMs); await driver.clickElement( By.xpath(`//button[contains(text(), 'Reject')]`), - ) - await driver.delay(largeDelayMs * 2) + ); + await driver.delay(largeDelayMs * 2); const navigationElement = await driver.findElement( By.css('.confirm-page-container-navigation'), - ) - await driver.delay(tinyDelayMs) - const navigationText = await navigationElement.getText() - assert.equal(navigationText.includes('4'), true, 'transaction rejected') - }) + ); + await driver.delay(tinyDelayMs); + const navigationText = await navigationElement.getText(); + assert.equal(navigationText.includes('4'), true, 'transaction rejected'); + }); it('confirms a transaction', async function () { - await driver.delay(tinyDelayMs / 2) + await driver.delay(tinyDelayMs / 2); await driver.clickElement( By.xpath(`//button[contains(text(), 'Confirm')]`), - ) - await driver.delay(regularDelayMs) + ); + await driver.delay(regularDelayMs); const navigationElement = await driver.findElement( By.css('.confirm-page-container-navigation'), - ) - await driver.delay(tinyDelayMs / 2) - const navigationText = await navigationElement.getText() - await driver.delay(tinyDelayMs / 2) - assert.equal(navigationText.includes('3'), true, 'transaction confirmed') - }) + ); + await driver.delay(tinyDelayMs / 2); + const navigationText = await navigationElement.getText(); + await driver.delay(tinyDelayMs / 2); + assert.equal(navigationText.includes('3'), true, 'transaction confirmed'); + }); it('rejects the rest of the transactions', async function () { - await driver.clickElement(By.xpath(`//a[contains(text(), 'Reject 3')]`)) - await driver.delay(regularDelayMs) + await driver.clickElement(By.xpath(`//a[contains(text(), 'Reject 3')]`)); + await driver.delay(regularDelayMs); await driver.clickElement( By.xpath(`//button[contains(text(), 'Reject All')]`), - ) - await driver.delay(largeDelayMs * 2) + ); + await driver.delay(largeDelayMs * 2); await driver.wait(async () => { const confirmedTxes = await driver.findElements( By.css( '.transaction-list__completed-transactions .transaction-list-item', ), - ) - return confirmedTxes.length === 5 - }, 10000) - }) - }) + ); + return confirmedTxes.length === 5; + }, 10000); + }); + }); describe('Deploy contract and call contract methods', function () { - let extension - let dapp + let extension; + let dapp; it('creates a deploy contract transaction', async function () { - const windowHandles = await driver.getAllWindowHandles() - extension = windowHandles[0] - dapp = windowHandles[1] - await driver.delay(tinyDelayMs) + const windowHandles = await driver.getAllWindowHandles(); + extension = windowHandles[0]; + dapp = windowHandles[1]; + await driver.delay(tinyDelayMs); - await driver.switchToWindow(dapp) - await driver.delay(regularDelayMs) + await driver.switchToWindow(dapp); + await driver.delay(regularDelayMs); - await driver.clickElement(By.css('#deployButton')) - await driver.delay(regularDelayMs) + await driver.clickElement(By.css('#deployButton')); + await driver.delay(regularDelayMs); - await driver.switchToWindow(extension) - await driver.delay(regularDelayMs) + await driver.switchToWindow(extension); + await driver.delay(regularDelayMs); await driver.clickElement( By.xpath(`//h2[contains(text(), 'Contract Deployment')]`), - ) - await driver.delay(largeDelayMs) - }) + ); + await driver.delay(largeDelayMs); + }); it('displays the contract creation data', async function () { - await driver.clickElement(By.xpath(`//button[contains(text(), 'Data')]`)) - await driver.delay(regularDelayMs) + await driver.clickElement(By.xpath(`//button[contains(text(), 'Data')]`)); + await driver.delay(regularDelayMs); - await driver.findElement(By.xpath(`//div[contains(text(), '127.0.0.1')]`)) + await driver.findElement( + By.xpath(`//div[contains(text(), '127.0.0.1')]`), + ); const confirmDataDiv = await driver.findElement( By.css('.confirm-page-container-content__data-box'), - ) - const confirmDataText = await confirmDataDiv.getText() - assert.ok(confirmDataText.includes('Origin:')) - assert.ok(confirmDataText.includes('127.0.0.1')) - assert.ok(confirmDataText.includes('Bytes:')) - assert.ok(confirmDataText.includes('675')) + ); + const confirmDataText = await confirmDataDiv.getText(); + assert.ok(confirmDataText.includes('Origin:')); + assert.ok(confirmDataText.includes('127.0.0.1')); + assert.ok(confirmDataText.includes('Bytes:')); + assert.ok(confirmDataText.includes('675')); await driver.clickElement( By.xpath(`//button[contains(text(), 'Details')]`), - ) - await driver.delay(regularDelayMs) - }) + ); + await driver.delay(regularDelayMs); + }); it('confirms a deploy contract transaction', async function () { await driver.clickElement( By.xpath(`//button[contains(text(), 'Confirm')]`), - ) - await driver.delay(largeDelayMs) + ); + await driver.delay(largeDelayMs); await driver.wait(async () => { const confirmedTxes = await driver.findElements( By.css( '.transaction-list__completed-transactions .transaction-list-item', ), - ) - return confirmedTxes.length === 6 - }, 10000) + ); + return confirmedTxes.length === 6; + }, 10000); - const txAction = await driver.findElements(By.css('.list-item__heading')) + const txAction = await driver.findElements(By.css('.list-item__heading')); await driver.wait( until.elementTextMatches(txAction[0], /Contract\sDeployment/u), 10000, - ) - await driver.delay(regularDelayMs) - }) + ); + await driver.delay(regularDelayMs); + }); it('calls and confirms a contract method where ETH is sent', async function () { - await driver.switchToWindow(dapp) - await driver.delay(regularDelayMs) + await driver.switchToWindow(dapp); + await driver.delay(regularDelayMs); - let contractStatus = await driver.findElement(By.css('#contractStatus')) + let contractStatus = await driver.findElement(By.css('#contractStatus')); await driver.wait( until.elementTextMatches(contractStatus, /Deployed/u), 15000, - ) + ); - await driver.clickElement(By.css('#depositButton')) - await driver.delay(largeDelayMs) + await driver.clickElement(By.css('#depositButton')); + await driver.delay(largeDelayMs); - contractStatus = await driver.findElement(By.css('#contractStatus')) + contractStatus = await driver.findElement(By.css('#contractStatus')); await driver.wait( until.elementTextMatches(contractStatus, /Deposit\sinitiated/u), 10000, - ) + ); - await driver.switchToWindow(extension) - await driver.delay(largeDelayMs * 2) + await driver.switchToWindow(extension); + await driver.delay(largeDelayMs * 2); - await driver.findElements(By.css('.transaction-list-item--unconfirmed')) + await driver.findElements(By.css('.transaction-list-item--unconfirmed')); const txListValue = await driver.findClickableElement( By.css('.transaction-list-item__primary-currency'), - ) + ); await driver.wait( until.elementTextMatches(txListValue, /-4\s*ETH/u), 10000, - ) - await txListValue.click() - await driver.delay(regularDelayMs) + ); + await txListValue.click(); + await driver.delay(regularDelayMs); // Set the gas limit await driver.clickElement( By.css('.confirm-detail-row__header-text--edit'), - ) - await driver.delay(regularDelayMs) + ); + await driver.delay(regularDelayMs); - const gasModal = await driver.findElement(By.css('span .modal')) - await driver.delay(regularDelayMs) - await driver.clickElement(By.css('.page-container__tab:nth-of-type(2)')) - await driver.delay(regularDelayMs) + const gasModal = await driver.findElement(By.css('span .modal')); + await driver.delay(regularDelayMs); + await driver.clickElement(By.css('.page-container__tab:nth-of-type(2)')); + await driver.delay(regularDelayMs); const [gasPriceInput, gasLimitInput] = await driver.findElements( By.css('.advanced-gas-inputs__gas-edit-row__input'), - ) - const gasLimitValue = await gasLimitInput.getAttribute('value') - assert(Number(gasLimitValue) < 100000, 'Gas Limit too high') + ); + const gasLimitValue = await gasLimitInput.getAttribute('value'); + assert(Number(gasLimitValue) < 100000, 'Gas Limit too high'); - await gasPriceInput.clear() - await driver.delay(50) - await gasPriceInput.sendKeys('10') - await driver.delay(50) + await gasPriceInput.clear(); + await driver.delay(50); + await gasPriceInput.sendKeys('10'); + await driver.delay(50); - await gasLimitInput.clear() - await driver.delay(50) - await gasLimitInput.sendKeys('60001') + await gasLimitInput.clear(); + await driver.delay(50); + await gasLimitInput.sendKeys('60001'); - await driver.delay(1000) + await driver.delay(1000); - await driver.clickElement(By.xpath(`//button[contains(text(), 'Save')]`)) - await driver.delay(regularDelayMs) + await driver.clickElement(By.xpath(`//button[contains(text(), 'Save')]`)); + await driver.delay(regularDelayMs); - await driver.wait(until.stalenessOf(gasModal)) + await driver.wait(until.stalenessOf(gasModal)); await driver.clickElement( By.xpath(`//button[contains(text(), 'Confirm')]`), - ) - await driver.delay(regularDelayMs) + ); + await driver.delay(regularDelayMs); await driver.wait(async () => { const confirmedTxes = await driver.findElements( By.css( '.transaction-list__completed-transactions .transaction-list-item', ), - ) - return confirmedTxes.length === 7 - }, 10000) + ); + return confirmedTxes.length === 7; + }, 10000); const txValues = await driver.findElements( By.css('.transaction-list-item__primary-currency'), - ) + ); await driver.wait( until.elementTextMatches(txValues[0], /-4\s*ETH/u), 10000, - ) - }) + ); + }); it('calls and confirms a contract method where ETH is received', async function () { - await driver.switchToWindow(dapp) - await driver.delay(regularDelayMs) + await driver.switchToWindow(dapp); + await driver.delay(regularDelayMs); - await driver.clickElement(By.css('#withdrawButton')) - await driver.delay(regularDelayMs) + await driver.clickElement(By.css('#withdrawButton')); + await driver.delay(regularDelayMs); - await driver.switchToWindow(extension) - await driver.delay(largeDelayMs * 2) + await driver.switchToWindow(extension); + await driver.delay(largeDelayMs * 2); await driver.clickElement( By.css( '.transaction-list__pending-transactions .transaction-list-item', ), - ) - await driver.delay(regularDelayMs) + ); + await driver.delay(regularDelayMs); await driver.clickElement( By.xpath(`//button[contains(text(), 'Confirm')]`), - ) - await driver.delay(regularDelayMs) + ); + await driver.delay(regularDelayMs); await driver.wait(async () => { const confirmedTxes = await driver.findElements( By.css( '.transaction-list__completed-transactions .transaction-list-item', ), - ) - return confirmedTxes.length === 8 - }, 10000) + ); + return confirmedTxes.length === 8; + }, 10000); const txValues = await driver.findElement( By.css('.transaction-list-item__primary-currency'), - ) - await driver.wait(until.elementTextMatches(txValues, /-0\s*ETH/u), 10000) + ); + await driver.wait(until.elementTextMatches(txValues, /-0\s*ETH/u), 10000); - await driver.closeAllWindowHandlesExcept([extension, dapp]) - await driver.switchToWindow(extension) - }) + await driver.closeAllWindowHandlesExcept([extension, dapp]); + await driver.switchToWindow(extension); + }); it('renders the correct ETH balance', async function () { const balance = await driver.findElement( By.css('[data-testid="eth-overview__primary-currency"]'), - ) - await driver.delay(regularDelayMs) + ); + await driver.delay(regularDelayMs); await driver.wait( until.elementTextMatches(balance, /^87.*\s*ETH.*$/u), 10000, - ) - const tokenAmount = await balance.getText() - assert.ok(/^87.*\s*ETH.*$/u.test(tokenAmount)) - await driver.delay(regularDelayMs) - }) - }) + ); + const tokenAmount = await balance.getText(); + assert.ok(/^87.*\s*ETH.*$/u.test(tokenAmount)); + await driver.delay(regularDelayMs); + }); + }); describe('Add a custom token from a dapp', function () { it('creates a new token', async function () { - let windowHandles = await driver.getAllWindowHandles() - const extension = windowHandles[0] - const dapp = windowHandles[1] - await driver.delay(regularDelayMs * 2) + let windowHandles = await driver.getAllWindowHandles(); + const extension = windowHandles[0]; + const dapp = windowHandles[1]; + await driver.delay(regularDelayMs * 2); - await driver.switchToWindow(dapp) - await driver.delay(regularDelayMs * 2) + await driver.switchToWindow(dapp); + await driver.delay(regularDelayMs * 2); await driver.clickElement( By.xpath(`//button[contains(text(), 'Create Token')]`), - ) - windowHandles = await driver.waitUntilXWindowHandles(3) + ); + windowHandles = await driver.waitUntilXWindowHandles(3); - const popup = windowHandles[2] - await driver.switchToWindow(popup) - await driver.delay(regularDelayMs) + const popup = windowHandles[2]; + await driver.switchToWindow(popup); + await driver.delay(regularDelayMs); await driver.clickElement( By.css('.confirm-detail-row__header-text--edit'), - ) - await driver.delay(regularDelayMs) + ); + await driver.delay(regularDelayMs); await driver.clickElement( By.xpath(`//button[contains(text(), 'Advanced')]`), - ) - await driver.delay(tinyDelayMs) + ); + await driver.delay(tinyDelayMs); const [gasPriceInput, gasLimitInput] = await driver.findElements( By.css('.advanced-gas-inputs__gas-edit-row__input'), - ) - assert(gasPriceInput.getAttribute('value'), 20) - assert(gasLimitInput.getAttribute('value'), 4700000) + ); + assert(gasPriceInput.getAttribute('value'), 20); + assert(gasLimitInput.getAttribute('value'), 4700000); - await driver.clickElement(By.xpath(`//button[contains(text(), 'Save')]`)) - await driver.delay(regularDelayMs) + await driver.clickElement(By.xpath(`//button[contains(text(), 'Save')]`)); + await driver.delay(regularDelayMs); await driver.clickElement( By.xpath(`//button[contains(text(), 'Confirm')]`), - ) - await driver.delay(regularDelayMs) + ); + await driver.delay(regularDelayMs); - await driver.switchToWindow(dapp) - await driver.delay(tinyDelayMs) + await driver.switchToWindow(dapp); + await driver.delay(tinyDelayMs); const tokenContractAddress = await driver.findElement( By.css('#tokenAddress'), - ) - await driver.wait(until.elementTextMatches(tokenContractAddress, /0x/u)) - tokenAddress = await tokenContractAddress.getText() + ); + await driver.wait(until.elementTextMatches(tokenContractAddress, /0x/u)); + tokenAddress = await tokenContractAddress.getText(); - await driver.delay(regularDelayMs) - await driver.closeAllWindowHandlesExcept([extension, dapp]) - await driver.delay(regularDelayMs) - await driver.switchToWindow(extension) - await driver.delay(largeDelayMs) - }) + await driver.delay(regularDelayMs); + await driver.closeAllWindowHandlesExcept([extension, dapp]); + await driver.delay(regularDelayMs); + await driver.switchToWindow(extension); + await driver.delay(largeDelayMs); + }); it('clicks on the Add Token button', async function () { - await driver.clickElement(By.css(`[data-testid="home__asset-tab"]`)) + await driver.clickElement(By.css(`[data-testid="home__asset-tab"]`)); await driver.clickElement( By.xpath(`//button[contains(text(), 'Add Token')]`), - ) - await driver.delay(regularDelayMs) - }) + ); + await driver.delay(regularDelayMs); + }); it('picks the newly created Test token', async function () { await driver.clickElement( By.xpath("//button[contains(text(), 'Custom Token')]"), - ) - await driver.delay(regularDelayMs) + ); + await driver.delay(regularDelayMs); const newTokenAddress = await driver.findElement( By.css('#custom-address'), - ) - await newTokenAddress.sendKeys(tokenAddress) - await driver.delay(regularDelayMs) + ); + await newTokenAddress.sendKeys(tokenAddress); + await driver.delay(regularDelayMs); - await driver.clickElement(By.xpath(`//button[contains(text(), 'Next')]`)) - await driver.delay(regularDelayMs) + await driver.clickElement(By.xpath(`//button[contains(text(), 'Next')]`)); + await driver.delay(regularDelayMs); await driver.clickElement( By.xpath(`//button[contains(text(), 'Add Tokens')]`), - ) - await driver.delay(regularDelayMs) - }) + ); + await driver.delay(regularDelayMs); + }); it('renders the balance for the new token', async function () { const balance = await driver.findElement( By.css('.wallet-overview .token-overview__primary-balance'), - ) - await driver.wait(until.elementTextMatches(balance, /^10\s*TST\s*$/u)) - const tokenAmount = await balance.getText() - assert.ok(/^10\s*TST\s*$/u.test(tokenAmount)) - await driver.delay(regularDelayMs) - }) - }) + ); + await driver.wait(until.elementTextMatches(balance, /^10\s*TST\s*$/u)); + const tokenAmount = await balance.getText(); + assert.ok(/^10\s*TST\s*$/u.test(tokenAmount)); + await driver.delay(regularDelayMs); + }); + }); describe('Send token from inside MetaMask', function () { - let gasModal + let gasModal; it('starts to send a transaction', async function () { - await driver.clickElement(By.css('[data-testid="eth-overview-send"]')) - await driver.delay(regularDelayMs) + await driver.clickElement(By.css('[data-testid="eth-overview-send"]')); + await driver.delay(regularDelayMs); const inputAddress = await driver.findElement( By.css('input[placeholder="Search, public address (0x), or ENS"]'), - ) - await inputAddress.sendKeys('0x2f318C334780961FB129D2a6c30D0763d9a5C970') + ); + await inputAddress.sendKeys('0x2f318C334780961FB129D2a6c30D0763d9a5C970'); - const inputAmount = await driver.findElement(By.css('.unit-input__input')) - await inputAmount.sendKeys('1') + const inputAmount = await driver.findElement( + By.css('.unit-input__input'), + ); + await inputAmount.sendKeys('1'); // Set the gas limit - await driver.clickElement(By.css('.advanced-gas-options-btn')) - await driver.delay(regularDelayMs) + await driver.clickElement(By.css('.advanced-gas-options-btn')); + await driver.delay(regularDelayMs); - gasModal = await driver.findElement(By.css('span .modal')) - await driver.delay(regularDelayMs) - }) + gasModal = await driver.findElement(By.css('span .modal')); + await driver.delay(regularDelayMs); + }); it('opens customize gas modal', async function () { - await driver.findElement(By.css('.page-container__title')) - await driver.clickElement(By.xpath(`//button[contains(text(), 'Save')]`)) - await driver.delay(regularDelayMs) - }) + await driver.findElement(By.css('.page-container__title')); + await driver.clickElement(By.xpath(`//button[contains(text(), 'Save')]`)); + await driver.delay(regularDelayMs); + }); it('transitions to the confirm screen', async function () { - await driver.wait(until.stalenessOf(gasModal)) + await driver.wait(until.stalenessOf(gasModal)); // Continue to next screen - await driver.clickElement(By.xpath(`//button[contains(text(), 'Next')]`)) - await driver.delay(regularDelayMs) - }) + await driver.clickElement(By.xpath(`//button[contains(text(), 'Next')]`)); + await driver.delay(regularDelayMs); + }); it('displays the token transfer data', async function () { - await driver.clickElement(By.xpath(`//button[contains(text(), 'Data')]`)) - await driver.delay(regularDelayMs) + await driver.clickElement(By.xpath(`//button[contains(text(), 'Data')]`)); + await driver.delay(regularDelayMs); const functionType = await driver.findElement( By.css('.confirm-page-container-content__function-type'), - ) - const functionTypeText = await functionType.getText() - assert.equal(functionTypeText, 'Transfer') + ); + const functionTypeText = await functionType.getText(); + assert.equal(functionTypeText, 'Transfer'); const tokenAmount = await driver.findElement( By.css('.confirm-page-container-summary__title-text'), - ) - const tokenAmountText = await tokenAmount.getText() - assert.equal(tokenAmountText, '1 TST') + ); + const tokenAmountText = await tokenAmount.getText(); + assert.equal(tokenAmountText, '1 TST'); const confirmDataDiv = await driver.findElement( By.css('.confirm-page-container-content__data-box'), - ) - const confirmDataText = await confirmDataDiv.getText() + ); + const confirmDataText = await confirmDataDiv.getText(); - await driver.delay(regularDelayMs) + await driver.delay(regularDelayMs); assert( confirmDataText.match( /0xa9059cbb0000000000000000000000002f318c334780961fb129d2a6c30d0763d9a5c97/u, ), - ) + ); await driver.clickElement( By.xpath(`//button[contains(text(), 'Details')]`), - ) - await driver.delay(regularDelayMs) - }) + ); + await driver.delay(regularDelayMs); + }); it('submits the transaction', async function () { await driver.clickElement( By.xpath(`//button[contains(text(), 'Confirm')]`), - ) - await driver.delay(regularDelayMs) - }) + ); + await driver.delay(regularDelayMs); + }); it('finds the transaction in the transactions list', async function () { await driver.wait(async () => { @@ -1214,119 +1228,119 @@ describe('MetaMask', function () { By.css( '.transaction-list__completed-transactions .transaction-list-item', ), - ) - return confirmedTxes.length === 1 - }, 10000) + ); + return confirmedTxes.length === 1; + }, 10000); const txValues = await driver.findElements( By.css('.transaction-list-item__primary-currency'), - ) - assert.equal(txValues.length, 1) + ); + assert.equal(txValues.length, 1); await driver.wait( until.elementTextMatches(txValues[0], /-1\s*TST/u), 10000, - ) + ); const txStatuses = await driver.findElements( By.css('.list-item__heading'), - ) + ); await driver.wait( until.elementTextMatches(txStatuses[0], /Send\sTST/u), 10000, - ) - }) - }) + ); + }); + }); describe('Send a custom token from dapp', function () { - let gasModal + let gasModal; it('sends an already created token', async function () { - const windowHandles = await driver.getAllWindowHandles() - const extension = windowHandles[0] + const windowHandles = await driver.getAllWindowHandles(); + const extension = windowHandles[0]; const dapp = await driver.switchToWindowWithTitle( 'E2E Test Dapp', windowHandles, - ) - await driver.delay(regularDelayMs) + ); + await driver.delay(regularDelayMs); - await driver.switchToWindow(dapp) - await driver.delay(tinyDelayMs) + await driver.switchToWindow(dapp); + await driver.delay(tinyDelayMs); await driver.clickElement( By.xpath(`//button[contains(text(), 'Transfer Tokens')]`), - ) + ); - await driver.switchToWindow(extension) - await driver.delay(largeDelayMs) + await driver.switchToWindow(extension); + await driver.delay(largeDelayMs); await driver.findElements( By.css('.transaction-list__pending-transactions'), - ) + ); const txListValue = await driver.findClickableElement( By.css('.transaction-list-item__primary-currency'), - ) + ); await driver.wait( until.elementTextMatches(txListValue, /-1.5\s*TST/u), 10000, - ) - await txListValue.click() - await driver.delay(regularDelayMs) + ); + await txListValue.click(); + await driver.delay(regularDelayMs); const transactionAmounts = await driver.findElements( By.css('.currency-display-component__text'), - ) - const transactionAmount = transactionAmounts[0] - assert(await transactionAmount.getText(), '1.5 TST') + ); + const transactionAmount = transactionAmounts[0]; + assert(await transactionAmount.getText(), '1.5 TST'); // Set the gas limit await driver.clickElement( By.css('.confirm-detail-row__header-text--edit'), - ) - await driver.delay(regularDelayMs) + ); + await driver.delay(regularDelayMs); - gasModal = await driver.findElement(By.css('span .modal')) - }) + gasModal = await driver.findElement(By.css('span .modal')); + }); it('customizes gas', async function () { - await driver.clickElement(By.css('.page-container__tab:nth-of-type(2)')) - await driver.delay(regularDelayMs) + await driver.clickElement(By.css('.page-container__tab:nth-of-type(2)')); + await driver.delay(regularDelayMs); const [gasPriceInput, gasLimitInput] = await driver.findElements( By.css('.advanced-gas-inputs__gas-edit-row__input'), - ) + ); - await gasPriceInput.clear() - await driver.delay(50) - await gasPriceInput.sendKeys('10') - await driver.delay(50) + await gasPriceInput.clear(); + await driver.delay(50); + await gasPriceInput.sendKeys('10'); + await driver.delay(50); - await gasLimitInput.clear() - await driver.delay(50) - await gasLimitInput.sendKeys('60000') + await gasLimitInput.clear(); + await driver.delay(50); + await gasLimitInput.sendKeys('60000'); - await driver.delay(1000) + await driver.delay(1000); - await driver.clickElement(By.css('.page-container__footer-button')) - await driver.wait(until.stalenessOf(gasModal)) + await driver.clickElement(By.css('.page-container__footer-button')); + await driver.wait(until.stalenessOf(gasModal)); const gasFeeInputs = await driver.findElements( By.css('.confirm-detail-row__primary'), - ) - const renderedGasFee = await gasFeeInputs[0].getText() - assert.equal(renderedGasFee, '0.0006') - }) + ); + const renderedGasFee = await gasFeeInputs[0].getText(); + assert.equal(renderedGasFee, '0.0006'); + }); it('submits the transaction', async function () { const tokenAmount = await driver.findElement( By.css('.confirm-page-container-summary__title-text'), - ) - const tokenAmountText = await tokenAmount.getText() - assert.equal(tokenAmountText, '1.5 TST') + ); + const tokenAmountText = await tokenAmount.getText(); + assert.equal(tokenAmountText, '1.5 TST'); await driver.clickElement( By.xpath(`//button[contains(text(), 'Confirm')]`), - ) - await driver.delay(regularDelayMs) - }) + ); + await driver.delay(regularDelayMs); + }); it('finds the transaction in the transactions list', async function () { await driver.wait(async () => { @@ -1334,174 +1348,174 @@ describe('MetaMask', function () { By.css( '.transaction-list__completed-transactions .transaction-list-item', ), - ) - return confirmedTxes.length === 2 - }, 10000) + ); + return confirmedTxes.length === 2; + }, 10000); const txValues = await driver.findElements( By.css('.transaction-list-item__primary-currency'), - ) - await driver.wait(until.elementTextMatches(txValues[0], /-1.5\s*TST/u)) + ); + await driver.wait(until.elementTextMatches(txValues[0], /-1.5\s*TST/u)); const txStatuses = await driver.findElements( By.css('.list-item__heading'), - ) + ); await driver.wait( until.elementTextMatches(txStatuses[0], /Send\sTST/u), 10000, - ) + ); const tokenBalanceAmount = await driver.findElements( By.css('.token-overview__primary-balance'), - ) + ); await driver.wait( until.elementTextMatches(tokenBalanceAmount[0], /7.5\s*TST/u), 10000, - ) - }) - }) + ); + }); + }); describe('Approves a custom token from dapp', function () { - let gasModal + let gasModal; it('approves an already created token', async function () { - const windowHandles = await driver.getAllWindowHandles() - const extension = windowHandles[0] + const windowHandles = await driver.getAllWindowHandles(); + const extension = windowHandles[0]; const dapp = await driver.switchToWindowWithTitle( 'E2E Test Dapp', windowHandles, - ) - await driver.closeAllWindowHandlesExcept([extension, dapp]) - await driver.delay(regularDelayMs) + ); + await driver.closeAllWindowHandlesExcept([extension, dapp]); + await driver.delay(regularDelayMs); - await driver.switchToWindow(dapp) - await driver.delay(tinyDelayMs) + await driver.switchToWindow(dapp); + await driver.delay(tinyDelayMs); await driver.clickElement( By.xpath(`//button[contains(text(), 'Approve Tokens')]`), - ) + ); - await driver.switchToWindow(extension) - await driver.delay(regularDelayMs) + await driver.switchToWindow(extension); + await driver.delay(regularDelayMs); await driver.wait(async () => { const pendingTxes = await driver.findElements( By.css( '.transaction-list__pending-transactions .transaction-list-item', ), - ) - return pendingTxes.length === 1 - }, 10000) + ); + return pendingTxes.length === 1; + }, 10000); const [txtListHeading] = await driver.findElements( By.css('.transaction-list-item .list-item__heading'), - ) + ); await driver.wait( until.elementTextMatches(txtListHeading, /Approve TST spend limit/u), - ) - await driver.clickElement(By.css('.transaction-list-item')) - await driver.delay(regularDelayMs) - }) + ); + await driver.clickElement(By.css('.transaction-list-item')); + await driver.delay(regularDelayMs); + }); it('displays the token approval data', async function () { await driver.clickElement( By.css('.confirm-approve-content__view-full-tx-button'), - ) - await driver.delay(regularDelayMs) + ); + await driver.delay(regularDelayMs); const functionType = await driver.findElement( By.css( '.confirm-approve-content__data .confirm-approve-content__small-text', ), - ) - const functionTypeText = await functionType.getText() - assert.equal(functionTypeText, 'Function: Approve') + ); + const functionTypeText = await functionType.getText(); + assert.equal(functionTypeText, 'Function: Approve'); const confirmDataDiv = await driver.findElement( By.css('.confirm-approve-content__data__data-block'), - ) - const confirmDataText = await confirmDataDiv.getText() + ); + const confirmDataText = await confirmDataDiv.getText(); assert( confirmDataText.match( /0x095ea7b30000000000000000000000009bc5baf874d2da8d216ae9f137804184ee5afef4/u, ), - ) - }) + ); + }); it('opens the gas edit modal', async function () { await driver.clickElement( By.css('.confirm-approve-content__small-blue-text.cursor-pointer'), - ) - await driver.delay(regularDelayMs) + ); + await driver.delay(regularDelayMs); - gasModal = await driver.findElement(By.css('span .modal')) - }) + gasModal = await driver.findElement(By.css('span .modal')); + }); it('customizes gas', async function () { - await driver.clickElement(By.css('.page-container__tab:nth-of-type(2)')) - await driver.delay(regularDelayMs) + await driver.clickElement(By.css('.page-container__tab:nth-of-type(2)')); + await driver.delay(regularDelayMs); const [gasPriceInput, gasLimitInput] = await driver.findElements( By.css('.advanced-gas-inputs__gas-edit-row__input'), - ) + ); - await gasPriceInput.clear() - await driver.delay(50) - await gasPriceInput.sendKeys('10') - await driver.delay(50) + await gasPriceInput.clear(); + await driver.delay(50); + await gasPriceInput.sendKeys('10'); + await driver.delay(50); - await gasLimitInput.clear() - await driver.delay(50) - await gasLimitInput.sendKeys('60001') + await gasLimitInput.clear(); + await driver.delay(50); + await gasLimitInput.sendKeys('60001'); - await driver.delay(1000) + await driver.delay(1000); - await driver.clickElement(By.css('.page-container__footer-button')) - await driver.wait(until.stalenessOf(gasModal)) + await driver.clickElement(By.css('.page-container__footer-button')); + await driver.wait(until.stalenessOf(gasModal)); const gasFeeInEth = await driver.findElement( By.css( '.confirm-approve-content__transaction-details-content__secondary-fee', ), - ) - assert.equal(await gasFeeInEth.getText(), '0.0006 ETH') - }) + ); + assert.equal(await gasFeeInEth.getText(), '0.0006 ETH'); + }); it('edits the permission', async function () { const editButtons = await driver.findClickableElements( By.css('.confirm-approve-content__small-blue-text.cursor-pointer'), - ) - await editButtons[1].click() - await driver.delay(regularDelayMs) + ); + await editButtons[1].click(); + await driver.delay(regularDelayMs); - const permissionModal = await driver.findElement(By.css('span .modal')) + const permissionModal = await driver.findElement(By.css('span .modal')); const radioButtons = await driver.findClickableElements( By.css('.edit-approval-permission__edit-section__radio-button'), - ) - await radioButtons[1].click() + ); + await radioButtons[1].click(); - const customInput = await driver.findElement(By.css('input')) - await driver.delay(50) - await customInput.sendKeys('5') - await driver.delay(regularDelayMs) + const customInput = await driver.findElement(By.css('input')); + await driver.delay(50); + await customInput.sendKeys('5'); + await driver.delay(regularDelayMs); - await driver.clickElement(By.xpath(`//button[contains(text(), 'Save')]`)) - await driver.delay(regularDelayMs) + await driver.clickElement(By.xpath(`//button[contains(text(), 'Save')]`)); + await driver.delay(regularDelayMs); - await driver.wait(until.stalenessOf(permissionModal)) + await driver.wait(until.stalenessOf(permissionModal)); const permissionInfo = await driver.findElements( By.css('.confirm-approve-content__medium-text'), - ) - const amountDiv = permissionInfo[0] - assert.equal(await amountDiv.getText(), '5 TST') - }) + ); + const amountDiv = permissionInfo[0]; + assert.equal(await amountDiv.getText(), '5 TST'); + }); it('submits the transaction', async function () { await driver.clickElement( By.xpath(`//button[contains(text(), 'Confirm')]`), - ) - await driver.delay(regularDelayMs) - }) + ); + await driver.delay(regularDelayMs); + }); it('finds the transaction in the transactions list', async function () { await driver.wait(async () => { @@ -1509,63 +1523,63 @@ describe('MetaMask', function () { By.css( '.transaction-list__completed-transactions .transaction-list-item', ), - ) - return confirmedTxes.length === 3 - }, 10000) + ); + return confirmedTxes.length === 3; + }, 10000); const txStatuses = await driver.findElements( By.css('.list-item__heading'), - ) + ); await driver.wait( until.elementTextMatches(txStatuses[0], /Approve TST spend limit/u), - ) - }) - }) + ); + }); + }); describe('Transfers a custom token from dapp when no gas value is specified', function () { it('transfers an already created token, without specifying gas', async function () { - const windowHandles = await driver.getAllWindowHandles() - const extension = windowHandles[0] + const windowHandles = await driver.getAllWindowHandles(); + const extension = windowHandles[0]; const dapp = await driver.switchToWindowWithTitle( 'E2E Test Dapp', windowHandles, - ) - await driver.closeAllWindowHandlesExcept([extension, dapp]) - await driver.delay(regularDelayMs) + ); + await driver.closeAllWindowHandlesExcept([extension, dapp]); + await driver.delay(regularDelayMs); - await driver.switchToWindow(dapp) + await driver.switchToWindow(dapp); await driver.clickElement( By.xpath(`//button[contains(text(), 'Transfer Tokens Without Gas')]`), - ) + ); - await driver.switchToWindow(extension) - await driver.delay(regularDelayMs) + await driver.switchToWindow(extension); + await driver.delay(regularDelayMs); await driver.wait(async () => { const pendingTxes = await driver.findElements( By.css( '.transaction-list__pending-transactions .transaction-list-item', ), - ) - return pendingTxes.length === 1 - }, 10000) + ); + return pendingTxes.length === 1; + }, 10000); const [txListValue] = await driver.findElements( By.css('.transaction-list-item__primary-currency'), - ) - await driver.wait(until.elementTextMatches(txListValue, /-1.5\s*TST/u)) - await driver.clickElement(By.css('.transaction-list-item')) - await driver.delay(regularDelayMs) - }) + ); + await driver.wait(until.elementTextMatches(txListValue, /-1.5\s*TST/u)); + await driver.clickElement(By.css('.transaction-list-item')); + await driver.delay(regularDelayMs); + }); it('submits the transaction', async function () { - await driver.delay(largeDelayMs * 2) + await driver.delay(largeDelayMs * 2); await driver.clickElement( By.xpath(`//button[contains(text(), 'Confirm')]`), - ) - await driver.delay(largeDelayMs * 2) - }) + ); + await driver.delay(largeDelayMs * 2); + }); it('finds the transaction in the transactions list', async function () { await driver.wait(async () => { @@ -1573,81 +1587,81 @@ describe('MetaMask', function () { By.css( '.transaction-list__completed-transactions .transaction-list-item', ), - ) - return confirmedTxes.length === 4 - }, 10000) + ); + return confirmedTxes.length === 4; + }, 10000); const txValues = await driver.findElements( By.css('.transaction-list-item__primary-currency'), - ) - await driver.wait(until.elementTextMatches(txValues[0], /-1.5\s*TST/u)) + ); + await driver.wait(until.elementTextMatches(txValues[0], /-1.5\s*TST/u)); const txStatuses = await driver.findElements( By.css('.list-item__heading'), - ) - await driver.wait(until.elementTextMatches(txStatuses[0], /Send TST/u)) - }) - }) + ); + await driver.wait(until.elementTextMatches(txStatuses[0], /Send TST/u)); + }); + }); describe('Approves a custom token from dapp when no gas value is specified', function () { it('approves an already created token', async function () { - const windowHandles = await driver.getAllWindowHandles() - const extension = windowHandles[0] + const windowHandles = await driver.getAllWindowHandles(); + const extension = windowHandles[0]; const dapp = await driver.switchToWindowWithTitle( 'E2E Test Dapp', windowHandles, - ) - await driver.closeAllWindowHandlesExcept([extension, dapp]) - await driver.delay(regularDelayMs) + ); + await driver.closeAllWindowHandlesExcept([extension, dapp]); + await driver.delay(regularDelayMs); - await driver.switchToWindow(dapp) - await driver.delay(tinyDelayMs) + await driver.switchToWindow(dapp); + await driver.delay(tinyDelayMs); await driver.clickElement( By.xpath(`//button[contains(text(), 'Approve Tokens Without Gas')]`), - ) + ); - await driver.switchToWindow(extension) - await driver.delay(regularDelayMs) + await driver.switchToWindow(extension); + await driver.delay(regularDelayMs); await driver.wait(async () => { const pendingTxes = await driver.findElements( By.css( '.transaction-list__pending-transactions .transaction-list-item', ), - ) - return pendingTxes.length === 1 - }, 10000) + ); + return pendingTxes.length === 1; + }, 10000); const [txtListHeading] = await driver.findElements( By.css('.transaction-list-item .list-item__heading'), - ) + ); await driver.wait( until.elementTextMatches(txtListHeading, /Approve TST spend limit/u), - ) - await driver.clickElement(By.css('.transaction-list-item')) - await driver.delay(regularDelayMs) - }) + ); + await driver.clickElement(By.css('.transaction-list-item')); + await driver.delay(regularDelayMs); + }); it('shows the correct recipient', async function () { await driver.clickElement( By.css('.confirm-approve-content__view-full-tx-button'), - ) - await driver.delay(regularDelayMs) + ); + await driver.delay(regularDelayMs); const permissionInfo = await driver.findElements( By.css('.confirm-approve-content__medium-text'), - ) - const recipientDiv = permissionInfo[1] - assert.equal(await recipientDiv.getText(), '0x2f318C33...C970') - }) + ); + const recipientDiv = permissionInfo[1]; + assert.equal(await recipientDiv.getText(), '0x2f318C33...C970'); + }); it('submits the transaction', async function () { - await driver.delay(1000) + await driver.delay(1000); await driver.clickElement( By.xpath(`//button[contains(text(), 'Confirm')]`), - ) - await driver.delay(regularDelayMs) - }) + ); + await driver.delay(regularDelayMs); + }); it('finds the transaction in the transactions list', async function () { await driver.wait(async () => { @@ -1655,184 +1669,190 @@ describe('MetaMask', function () { By.css( '.transaction-list__completed-transactions .transaction-list-item', ), - ) - return confirmedTxes.length === 5 - }, 10000) + ); + return confirmedTxes.length === 5; + }, 10000); const txStatuses = await driver.findElements( By.css('.list-item__heading'), - ) + ); await driver.wait( until.elementTextMatches(txStatuses[0], /Approve TST spend limit/u), - ) - }) - }) + ); + }); + }); describe('Hide token', function () { it('hides the token when clicked', async function () { - await driver.clickElement(By.css('[data-testid="token-options__button"]')) + await driver.clickElement( + By.css('[data-testid="token-options__button"]'), + ); - await driver.clickElement(By.css('[data-testid="token-options__hide"]')) + await driver.clickElement(By.css('[data-testid="token-options__hide"]')); - const confirmHideModal = await driver.findElement(By.css('span .modal')) + const confirmHideModal = await driver.findElement(By.css('span .modal')); await driver.clickElement( By.css('[data-testid="hide-token-confirmation__hide"]'), - ) + ); - await driver.wait(until.stalenessOf(confirmHideModal)) - }) - }) + await driver.wait(until.stalenessOf(confirmHideModal)); + }); + }); describe('Add existing token using search', function () { it('clicks on the Add Token button', async function () { await driver.clickElement( By.xpath(`//button[contains(text(), 'Add Token')]`), - ) - await driver.delay(regularDelayMs) - }) + ); + await driver.delay(regularDelayMs); + }); it('can pick a token from the existing options', async function () { - const tokenSearch = await driver.findElement(By.css('#search-tokens')) - await tokenSearch.sendKeys('BAT') - await driver.delay(regularDelayMs) + const tokenSearch = await driver.findElement(By.css('#search-tokens')); + await tokenSearch.sendKeys('BAT'); + await driver.delay(regularDelayMs); - await driver.clickElement(By.xpath("//span[contains(text(), 'BAT')]")) - await driver.delay(regularDelayMs) + await driver.clickElement(By.xpath("//span[contains(text(), 'BAT')]")); + await driver.delay(regularDelayMs); - await driver.clickElement(By.xpath(`//button[contains(text(), 'Next')]`)) - await driver.delay(regularDelayMs) + await driver.clickElement(By.xpath(`//button[contains(text(), 'Next')]`)); + await driver.delay(regularDelayMs); await driver.clickElement( By.xpath(`//button[contains(text(), 'Add Tokens')]`), - ) - await driver.delay(largeDelayMs) - }) + ); + await driver.delay(largeDelayMs); + }); it('renders the balance for the chosen token', async function () { const balance = await driver.findElement( By.css('.token-overview__primary-balance'), - ) - await driver.wait(until.elementTextMatches(balance, /0\s*BAT/u)) - await driver.delay(regularDelayMs) - }) - }) + ); + await driver.wait(until.elementTextMatches(balance, /0\s*BAT/u)); + await driver.delay(regularDelayMs); + }); + }); describe('Stores custom RPC history', function () { it(`creates first custom RPC entry`, async function () { - const rpcUrl = 'http://127.0.0.1:8545/1' - const chainId = '0x539' // Ganache default, decimal 1337 + const rpcUrl = 'http://127.0.0.1:8545/1'; + const chainId = '0x539'; // Ganache default, decimal 1337 - await driver.clickElement(By.css('.network-display')) - await driver.delay(regularDelayMs) + await driver.clickElement(By.css('.network-display')); + await driver.delay(regularDelayMs); await driver.clickElement( By.xpath(`//span[contains(text(), 'Custom RPC')]`), - ) - await driver.delay(regularDelayMs) + ); + await driver.delay(regularDelayMs); - await driver.findElement(By.css('.settings-page__sub-header-text')) + await driver.findElement(By.css('.settings-page__sub-header-text')); const customRpcInputs = await driver.findElements( By.css('input[type="text"]'), - ) - const rpcUrlInput = customRpcInputs[1] - const chainIdInput = customRpcInputs[2] + ); + const rpcUrlInput = customRpcInputs[1]; + const chainIdInput = customRpcInputs[2]; - await rpcUrlInput.clear() - await rpcUrlInput.sendKeys(rpcUrl) + await rpcUrlInput.clear(); + await rpcUrlInput.sendKeys(rpcUrl); - await chainIdInput.clear() - await chainIdInput.sendKeys(chainId) + await chainIdInput.clear(); + await chainIdInput.sendKeys(chainId); - await driver.clickElement(By.css('.network-form__footer .btn-secondary')) - await driver.findElement(By.xpath(`//div[contains(text(), '${rpcUrl}')]`)) - }) + await driver.clickElement(By.css('.network-form__footer .btn-secondary')); + await driver.findElement( + By.xpath(`//div[contains(text(), '${rpcUrl}')]`), + ); + }); it(`creates second custom RPC entry`, async function () { - const rpcUrl = 'http://127.0.0.1:8545/2' - const chainId = '0x539' // Ganache default, decimal 1337 + const rpcUrl = 'http://127.0.0.1:8545/2'; + const chainId = '0x539'; // Ganache default, decimal 1337 - await driver.clickElement(By.css('.network-display')) - await driver.delay(regularDelayMs) + await driver.clickElement(By.css('.network-display')); + await driver.delay(regularDelayMs); await driver.clickElement( By.xpath(`//span[contains(text(), 'Custom RPC')]`), - ) - await driver.delay(regularDelayMs) + ); + await driver.delay(regularDelayMs); - await driver.findElement(By.css('.settings-page__sub-header-text')) + await driver.findElement(By.css('.settings-page__sub-header-text')); const customRpcInputs = await driver.findElements( By.css('input[type="text"]'), - ) - const rpcUrlInput = customRpcInputs[1] - const chainIdInput = customRpcInputs[2] + ); + const rpcUrlInput = customRpcInputs[1]; + const chainIdInput = customRpcInputs[2]; - await rpcUrlInput.clear() - await rpcUrlInput.sendKeys(rpcUrl) + await rpcUrlInput.clear(); + await rpcUrlInput.sendKeys(rpcUrl); - await chainIdInput.clear() - await chainIdInput.sendKeys(chainId) + await chainIdInput.clear(); + await chainIdInput.sendKeys(chainId); - await driver.clickElement(By.css('.network-form__footer .btn-secondary')) - await driver.findElement(By.xpath(`//div[contains(text(), '${rpcUrl}')]`)) - }) + await driver.clickElement(By.css('.network-form__footer .btn-secondary')); + await driver.findElement( + By.xpath(`//div[contains(text(), '${rpcUrl}')]`), + ); + }); it('selects another provider', async function () { - await driver.clickElement(By.css('.network-display')) - await driver.delay(regularDelayMs) + await driver.clickElement(By.css('.network-display')); + await driver.delay(regularDelayMs); await driver.clickElement( By.xpath(`//span[contains(text(), 'Ethereum Mainnet')]`), - ) - await driver.delay(largeDelayMs * 2) - }) + ); + await driver.delay(largeDelayMs * 2); + }); it('finds all recent RPCs in history', async function () { - await driver.clickElement(By.css('.network-display')) - await driver.delay(regularDelayMs) + await driver.clickElement(By.css('.network-display')); + await driver.delay(regularDelayMs); // only recent 3 are found and in correct order (most recent at the top) const customRpcs = await driver.findElements( By.xpath(`//span[contains(text(), 'http://127.0.0.1:8545/')]`), - ) + ); // click Mainnet to dismiss network dropdown await driver.clickElement( By.xpath(`//span[contains(text(), 'Ethereum Mainnet')]`), - ) + ); - assert.equal(customRpcs.length, 2) - }) + assert.equal(customRpcs.length, 2); + }); it('deletes a custom RPC', async function () { const networkListItems = await driver.findClickableElements( By.css('.networks-tab__networks-list-name'), - ) - const lastNetworkListItem = networkListItems[networkListItems.length - 1] - await lastNetworkListItem.click() - await driver.delay(100) + ); + const lastNetworkListItem = networkListItems[networkListItems.length - 1]; + await lastNetworkListItem.click(); + await driver.delay(100); - await driver.clickElement(By.css('.btn-danger')) - await driver.delay(regularDelayMs) + await driver.clickElement(By.css('.btn-danger')); + await driver.delay(regularDelayMs); const confirmDeleteNetworkModal = await driver.findElement( By.css('span .modal'), - ) + ); const byConfirmDeleteNetworkButton = By.css( '.button.btn-danger.modal-container__footer-button', - ) - await driver.clickElement(byConfirmDeleteNetworkButton) + ); + await driver.clickElement(byConfirmDeleteNetworkButton); - await driver.wait(until.stalenessOf(confirmDeleteNetworkModal)) + await driver.wait(until.stalenessOf(confirmDeleteNetworkModal)); const newNetworkListItems = await driver.findElements( By.css('.networks-tab__networks-list-name'), - ) + ); - assert.equal(networkListItems.length - 1, newNetworkListItems.length) - }) - }) -}) + assert.equal(networkListItems.length - 1, newNetworkListItems.length); + }); + }); +}); diff --git a/test/e2e/metrics.spec.js b/test/e2e/metrics.spec.js index 74c8f26d8..4346f59b1 100644 --- a/test/e2e/metrics.spec.js +++ b/test/e2e/metrics.spec.js @@ -1,14 +1,14 @@ -const { strict: assert } = require('assert') -const { By, Key } = require('selenium-webdriver') -const waitUntilCalled = require('../lib/wait-until-called') -const { withFixtures } = require('./helpers') +const { strict: assert } = require('assert'); +const { By, Key } = require('selenium-webdriver'); +const waitUntilCalled = require('../lib/wait-until-called'); +const { withFixtures } = require('./helpers'); /** * WARNING: These tests must be run using a build created with `yarn build:test:metrics`, so that it has * the correct Segment host and write keys set. Otherwise this test will fail. */ describe('Segment metrics', function () { - this.timeout(0) + this.timeout(0); it('should send first three Page metric events upon fullscreen page load', async function () { const ganacheOptions = { @@ -19,7 +19,7 @@ describe('Segment metrics', function () { balance: 25000000000000000000, }, ], - } + }; await withFixtures( { fixtures: 'metrics-enabled', @@ -30,29 +30,29 @@ describe('Segment metrics', function () { async ({ driver, segmentStub }) => { const threeSegmentEventsReceived = waitUntilCalled(segmentStub, null, { callCount: 3, - }) - await driver.navigate() + }); + await driver.navigate(); - const passwordField = await driver.findElement(By.css('#password')) - await passwordField.sendKeys('correct horse battery staple') - await passwordField.sendKeys(Key.ENTER) + const passwordField = await driver.findElement(By.css('#password')); + await passwordField.sendKeys('correct horse battery staple'); + await passwordField.sendKeys(Key.ENTER); - await threeSegmentEventsReceived() + await threeSegmentEventsReceived(); - assert.ok(segmentStub.called, 'Segment should receive metrics') + assert.ok(segmentStub.called, 'Segment should receive metrics'); - const firstSegmentEvent = segmentStub.getCall(0).args[0] - assert.equal(firstSegmentEvent.name, 'Home') - assert.equal(firstSegmentEvent.context.page.path, '/') + const firstSegmentEvent = segmentStub.getCall(0).args[0]; + assert.equal(firstSegmentEvent.name, 'Home'); + assert.equal(firstSegmentEvent.context.page.path, '/'); - const secondSegmentEvent = segmentStub.getCall(1).args[0] - assert.equal(secondSegmentEvent.name, 'Unlock Page') - assert.equal(secondSegmentEvent.context.page.path, '/unlock') + const secondSegmentEvent = segmentStub.getCall(1).args[0]; + assert.equal(secondSegmentEvent.name, 'Unlock Page'); + assert.equal(secondSegmentEvent.context.page.path, '/unlock'); - const thirdSegmentEvent = segmentStub.getCall(2).args[0] - assert.equal(thirdSegmentEvent.name, 'Home') - assert.equal(thirdSegmentEvent.context.page.path, '/') + const thirdSegmentEvent = segmentStub.getCall(2).args[0]; + assert.equal(thirdSegmentEvent.name, 'Home'); + assert.equal(thirdSegmentEvent.context.page.path, '/'); }, - ) - }) -}) + ); + }); +}); diff --git a/test/e2e/mock-3box/server.js b/test/e2e/mock-3box/server.js index 7094fddd4..cffb15f4d 100644 --- a/test/e2e/mock-3box/server.js +++ b/test/e2e/mock-3box/server.js @@ -1,38 +1,38 @@ -const http = require('http') +const http = require('http'); -const port = 8889 +const port = 8889; -const database = {} +const database = {}; const requestHandler = (request, response) => { - response.setHeader('Content-Type', 'application/json') + response.setHeader('Content-Type', 'application/json'); if (request.method === 'POST') { - let body = '' + let body = ''; request.on('data', (chunk) => { - body += chunk.toString() // convert Buffer to string - }) + body += chunk.toString(); // convert Buffer to string + }); request.on('end', () => { - const { key, data } = JSON.parse(body) + const { key, data } = JSON.parse(body); - database[key] = data - response.setHeader('Access-Control-Allow-Headers', '*') - response.end('ok') - }) + database[key] = data; + response.setHeader('Access-Control-Allow-Headers', '*'); + response.end('ok'); + }); } else if (request.method === 'GET') { const key = new URL(request.url, 'https://example.org/').searchParams.get( 'key', - ) - response.setHeader('Access-Control-Allow-Headers', '*') - response.end(JSON.stringify(database[key] || '')) + ); + response.setHeader('Access-Control-Allow-Headers', '*'); + response.end(JSON.stringify(database[key] || '')); } else { - response.end('unknown request') + response.end('unknown request'); } -} +}; -const server = http.createServer(requestHandler) +const server = http.createServer(requestHandler); server.listen(port, (err) => { if (err) { - console.log('mock 3box server error: ', err) + console.log('mock 3box server error: ', err); } -}) +}); diff --git a/test/e2e/permissions.spec.js b/test/e2e/permissions.spec.js index 4f15b625f..522f625dd 100644 --- a/test/e2e/permissions.spec.js +++ b/test/e2e/permissions.spec.js @@ -1,20 +1,20 @@ -const assert = require('assert') -const webdriver = require('selenium-webdriver') +const assert = require('assert'); +const webdriver = require('selenium-webdriver'); -const { By, until } = webdriver -const enLocaleMessages = require('../../app/_locales/en/messages.json') -const { regularDelayMs, largeDelayMs } = require('./helpers') -const { buildWebDriver } = require('./webdriver') -const Ganache = require('./ganache') +const { By, until } = webdriver; +const enLocaleMessages = require('../../app/_locales/en/messages.json'); +const { regularDelayMs, largeDelayMs } = require('./helpers'); +const { buildWebDriver } = require('./webdriver'); +const Ganache = require('./ganache'); -const ganacheServer = new Ganache() +const ganacheServer = new Ganache(); describe('MetaMask', function () { - let driver - let publicAddress + let driver; + let publicAddress; - this.timeout(0) - this.bail(true) + this.timeout(0); + this.bail(true); before(async function () { await ganacheServer.start({ @@ -25,175 +25,175 @@ describe('MetaMask', function () { balance: 25000000000000000000, }, ], - }) - const result = await buildWebDriver() - driver = result.driver - await driver.navigate() - }) + }); + const result = await buildWebDriver(); + driver = result.driver; + await driver.navigate(); + }); afterEach(async function () { if (process.env.SELENIUM_BROWSER === 'chrome') { - const errors = await driver.checkBrowserForConsoleErrors(driver) + const errors = await driver.checkBrowserForConsoleErrors(driver); if (errors.length) { - const errorReports = errors.map((err) => err.message) + const errorReports = errors.map((err) => err.message); const errorMessage = `Errors found in browser console:\n${errorReports.join( '\n', - )}` - console.error(new Error(errorMessage)) + )}`; + console.error(new Error(errorMessage)); } } if (this.currentTest.state === 'failed') { - await driver.verboseReportOnFailure(this.currentTest.title) + await driver.verboseReportOnFailure(this.currentTest.title); } - }) + }); after(async function () { - await ganacheServer.quit() - await driver.quit() - }) + await ganacheServer.quit(); + await driver.quit(); + }); describe('Going through the first time flow, but skipping the seed phrase challenge', function () { it('clicks the continue button on the welcome screen', async function () { - await driver.findElement(By.css('.welcome-page__header')) + await driver.findElement(By.css('.welcome-page__header')); await driver.clickElement( By.xpath( `//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`, ), - ) - await driver.delay(largeDelayMs) - }) + ); + await driver.delay(largeDelayMs); + }); it('clicks the "Create New Wallet" option', async function () { await driver.clickElement( By.xpath(`//button[contains(text(), 'Create a Wallet')]`), - ) - await driver.delay(largeDelayMs) - }) + ); + await driver.delay(largeDelayMs); + }); it('clicks the "No thanks" option on the metametrics opt-in screen', async function () { - await driver.clickElement(By.css('.btn-default')) - await driver.delay(largeDelayMs) - }) + await driver.clickElement(By.css('.btn-default')); + await driver.delay(largeDelayMs); + }); it('accepts a secure password', async function () { const passwordBox = await driver.findElement( By.css('.first-time-flow__form #create-password'), - ) + ); const passwordBoxConfirm = await driver.findElement( By.css('.first-time-flow__form #confirm-password'), - ) + ); - await passwordBox.sendKeys('correct horse battery staple') - await passwordBoxConfirm.sendKeys('correct horse battery staple') + await passwordBox.sendKeys('correct horse battery staple'); + await passwordBoxConfirm.sendKeys('correct horse battery staple'); - await driver.clickElement(By.css('.first-time-flow__checkbox')) + await driver.clickElement(By.css('.first-time-flow__checkbox')); - await driver.clickElement(By.css('.first-time-flow__form button')) - await driver.delay(largeDelayMs) - }) + await driver.clickElement(By.css('.first-time-flow__form button')); + await driver.delay(largeDelayMs); + }); it('skips the seed phrase challenge', async function () { await driver.clickElement( By.xpath( `//button[contains(text(), '${enLocaleMessages.remindMeLater.message}')]`, ), - ) - await driver.delay(regularDelayMs) + ); + await driver.delay(regularDelayMs); await driver.clickElement( By.css('[data-testid="account-options-menu-button"]'), - ) + ); await driver.clickElement( By.css('[data-testid="account-options-menu__account-details"]'), - ) - }) + ); + }); it('gets the current accounts address', async function () { const addressInput = await driver.findElement( By.css('.readonly-input__input'), - ) - publicAddress = await addressInput.getAttribute('value') - const accountModal = await driver.findElement(By.css('span .modal')) + ); + publicAddress = await addressInput.getAttribute('value'); + const accountModal = await driver.findElement(By.css('span .modal')); - await driver.clickElement(By.css('.account-modal__close')) + await driver.clickElement(By.css('.account-modal__close')); - await driver.wait(until.stalenessOf(accountModal)) - await driver.delay(regularDelayMs) - }) - }) + await driver.wait(until.stalenessOf(accountModal)); + await driver.delay(regularDelayMs); + }); + }); describe('sets permissions', function () { - let extension - let popup - let dapp + let extension; + let popup; + let dapp; it('connects to the dapp', async function () { - await driver.openNewPage('http://127.0.0.1:8080/') - await driver.delay(regularDelayMs) + await driver.openNewPage('http://127.0.0.1:8080/'); + await driver.delay(regularDelayMs); await driver.clickElement( By.xpath(`//button[contains(text(), 'Connect')]`), - ) + ); - await driver.waitUntilXWindowHandles(3) - const windowHandles = await driver.getAllWindowHandles() + await driver.waitUntilXWindowHandles(3); + const windowHandles = await driver.getAllWindowHandles(); - extension = windowHandles[0] + extension = windowHandles[0]; dapp = await driver.switchToWindowWithTitle( 'E2E Test Dapp', windowHandles, - ) + ); popup = windowHandles.find( (handle) => handle !== extension && handle !== dapp, - ) + ); - await driver.switchToWindow(popup) + await driver.switchToWindow(popup); - await driver.delay(regularDelayMs) + await driver.delay(regularDelayMs); - await driver.clickElement(By.xpath(`//button[contains(text(), 'Next')]`)) + await driver.clickElement(By.xpath(`//button[contains(text(), 'Next')]`)); await driver.clickElement( By.xpath(`//button[contains(text(), 'Connect')]`), - ) + ); - await driver.waitUntilXWindowHandles(2) - await driver.switchToWindow(extension) - await driver.delay(regularDelayMs) - }) + await driver.waitUntilXWindowHandles(2); + await driver.switchToWindow(extension); + await driver.delay(regularDelayMs); + }); it('shows connected sites', async function () { await driver.clickElement( By.css('[data-testid="account-options-menu-button"]'), - ) + ); await driver.clickElement( By.css('[data-testid="account-options-menu__connected-sites"]'), - ) + ); await driver.findElement( By.xpath(`//h2[contains(text(), 'Connected sites')]`), - ) + ); const domains = await driver.findClickableElements( By.css('.connected-sites-list__domain-name'), - ) - assert.equal(domains.length, 1) - }) + ); + assert.equal(domains.length, 1); + }); it('can get accounts within the dapp', async function () { - await driver.switchToWindow(dapp) - await driver.delay(regularDelayMs) + await driver.switchToWindow(dapp); + await driver.delay(regularDelayMs); await driver.clickElement( By.xpath(`//button[contains(text(), 'eth_accounts')]`), - ) + ); const getAccountsResult = await driver.findElement( By.css('#getAccountsResult'), - ) + ); assert.equal( (await getAccountsResult.getText()).toLowerCase(), publicAddress.toLowerCase(), - ) - }) - }) -}) + ); + }); + }); +}); diff --git a/test/e2e/send-edit.spec.js b/test/e2e/send-edit.spec.js index 3c70d67e0..9ae21e89b 100644 --- a/test/e2e/send-edit.spec.js +++ b/test/e2e/send-edit.spec.js @@ -1,22 +1,22 @@ -const assert = require('assert') -const webdriver = require('selenium-webdriver') +const assert = require('assert'); +const webdriver = require('selenium-webdriver'); -const { By, until } = webdriver -const enLocaleMessages = require('../../app/_locales/en/messages.json') -const { tinyDelayMs, regularDelayMs, largeDelayMs } = require('./helpers') -const { buildWebDriver } = require('./webdriver') -const Ganache = require('./ganache') +const { By, until } = webdriver; +const enLocaleMessages = require('../../app/_locales/en/messages.json'); +const { tinyDelayMs, regularDelayMs, largeDelayMs } = require('./helpers'); +const { buildWebDriver } = require('./webdriver'); +const Ganache = require('./ganache'); -const ganacheServer = new Ganache() +const ganacheServer = new Ganache(); describe('Using MetaMask with an existing account', function () { - let driver + let driver; const testSeedPhrase = - 'forum vessel pink push lonely enact gentle tail admit parrot grunt dress' + 'forum vessel pink push lonely enact gentle tail admit parrot grunt dress'; - this.timeout(0) - this.bail(true) + this.timeout(0); + this.bail(true); before(async function () { await ganacheServer.start({ @@ -27,224 +27,228 @@ describe('Using MetaMask with an existing account', function () { balance: 25000000000000000000, }, ], - }) - const result = await buildWebDriver() - driver = result.driver - await driver.navigate() - }) + }); + const result = await buildWebDriver(); + driver = result.driver; + await driver.navigate(); + }); afterEach(async function () { if (process.env.SELENIUM_BROWSER === 'chrome') { - const errors = await driver.checkBrowserForConsoleErrors(driver) + const errors = await driver.checkBrowserForConsoleErrors(driver); if (errors.length) { - const errorReports = errors.map((err) => err.message) + const errorReports = errors.map((err) => err.message); const errorMessage = `Errors found in browser console:\n${errorReports.join( '\n', - )}` - console.error(new Error(errorMessage)) + )}`; + console.error(new Error(errorMessage)); } } if (this.currentTest.state === 'failed') { - await driver.verboseReportOnFailure(this.currentTest.title) + await driver.verboseReportOnFailure(this.currentTest.title); } - }) + }); after(async function () { - await ganacheServer.quit() - await driver.quit() - }) + await ganacheServer.quit(); + await driver.quit(); + }); describe('First time flow starting from an existing seed phrase', function () { it('clicks the continue button on the welcome screen', async function () { - await driver.findElement(By.css('.welcome-page__header')) + await driver.findElement(By.css('.welcome-page__header')); await driver.clickElement( By.xpath( `//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`, ), - ) - await driver.delay(largeDelayMs) - }) + ); + await driver.delay(largeDelayMs); + }); it('clicks the "Import Wallet" option', async function () { await driver.clickElement( By.xpath(`//button[contains(text(), 'Import wallet')]`), - ) - await driver.delay(largeDelayMs) - }) + ); + await driver.delay(largeDelayMs); + }); it('clicks the "No thanks" option on the metametrics opt-in screen', async function () { - await driver.clickElement(By.css('.btn-default')) - await driver.delay(largeDelayMs) - }) + await driver.clickElement(By.css('.btn-default')); + await driver.delay(largeDelayMs); + }); it('imports a seed phrase', async function () { const [seedTextArea] = await driver.findElements( By.css('input[placeholder="Paste seed phrase from clipboard"]'), - ) - await seedTextArea.sendKeys(testSeedPhrase) - await driver.delay(regularDelayMs) + ); + await seedTextArea.sendKeys(testSeedPhrase); + await driver.delay(regularDelayMs); - const [password] = await driver.findElements(By.id('password')) - await password.sendKeys('correct horse battery staple') + const [password] = await driver.findElements(By.id('password')); + await password.sendKeys('correct horse battery staple'); const [confirmPassword] = await driver.findElements( By.id('confirm-password'), - ) - confirmPassword.sendKeys('correct horse battery staple') + ); + confirmPassword.sendKeys('correct horse battery staple'); - await driver.clickElement(By.css('.first-time-flow__terms')) + await driver.clickElement(By.css('.first-time-flow__terms')); await driver.clickElement( By.xpath(`//button[contains(text(), 'Import')]`), - ) - await driver.delay(regularDelayMs) - }) + ); + await driver.delay(regularDelayMs); + }); it('clicks through the success screen', async function () { await driver.findElement( By.xpath(`//div[contains(text(), 'Congratulations')]`), - ) + ); await driver.clickElement( By.xpath( `//button[contains(text(), '${enLocaleMessages.endOfFlowMessage10.message}')]`, ), - ) - await driver.delay(regularDelayMs) - }) - }) + ); + await driver.delay(regularDelayMs); + }); + }); describe('Send ETH from inside MetaMask', function () { it('starts a send transaction', async function () { - await driver.clickElement(By.css('[data-testid="eth-overview-send"]')) - await driver.delay(regularDelayMs) + await driver.clickElement(By.css('[data-testid="eth-overview-send"]')); + await driver.delay(regularDelayMs); const inputAddress = await driver.findElement( By.css('input[placeholder="Search, public address (0x), or ENS"]'), - ) - await inputAddress.sendKeys('0x2f318C334780961FB129D2a6c30D0763d9a5C970') + ); + await inputAddress.sendKeys('0x2f318C334780961FB129D2a6c30D0763d9a5C970'); - const inputAmount = await driver.findElement(By.css('.unit-input__input')) - await inputAmount.sendKeys('1') + const inputAmount = await driver.findElement( + By.css('.unit-input__input'), + ); + await inputAmount.sendKeys('1'); // Set the gas limit - await driver.clickElement(By.css('.advanced-gas-options-btn')) - await driver.delay(regularDelayMs) + await driver.clickElement(By.css('.advanced-gas-options-btn')); + await driver.delay(regularDelayMs); - const gasModal = await driver.findElement(By.css('span .modal')) + const gasModal = await driver.findElement(By.css('span .modal')); const [gasPriceInput, gasLimitInput] = await driver.findElements( By.css('.advanced-gas-inputs__gas-edit-row__input'), - ) + ); - await gasPriceInput.clear() - await driver.delay(50) - await gasPriceInput.sendKeys('10') - await driver.delay(50) - await driver.delay(tinyDelayMs) - await driver.delay(50) + await gasPriceInput.clear(); + await driver.delay(50); + await gasPriceInput.sendKeys('10'); + await driver.delay(50); + await driver.delay(tinyDelayMs); + await driver.delay(50); - await gasLimitInput.clear() - await driver.delay(50) - await gasLimitInput.sendKeys('25000') + await gasLimitInput.clear(); + await driver.delay(50); + await gasLimitInput.sendKeys('25000'); - await driver.delay(1000) + await driver.delay(1000); - await driver.clickElement(By.xpath(`//button[contains(text(), 'Save')]`)) - await driver.wait(until.stalenessOf(gasModal)) - await driver.delay(regularDelayMs) + await driver.clickElement(By.xpath(`//button[contains(text(), 'Save')]`)); + await driver.wait(until.stalenessOf(gasModal)); + await driver.delay(regularDelayMs); // Continue to next screen - await driver.clickElement(By.xpath(`//button[contains(text(), 'Next')]`)) - await driver.delay(regularDelayMs) - }) + await driver.clickElement(By.xpath(`//button[contains(text(), 'Next')]`)); + await driver.delay(regularDelayMs); + }); it('has correct value and fee on the confirm screen the transaction', async function () { const transactionAmounts = await driver.findElements( By.css('.currency-display-component__text'), - ) - const transactionAmount = transactionAmounts[0] - assert.equal(await transactionAmount.getText(), '1') + ); + const transactionAmount = transactionAmounts[0]; + assert.equal(await transactionAmount.getText(), '1'); - const transactionFee = transactionAmounts[1] - assert.equal(await transactionFee.getText(), '0.00025') - }) + const transactionFee = transactionAmounts[1]; + assert.equal(await transactionFee.getText(), '0.00025'); + }); it('edits the transaction', async function () { await driver.clickElement( By.css('.confirm-page-container-header__back-button'), - ) + ); - await driver.delay(regularDelayMs) + await driver.delay(regularDelayMs); - const inputAmount = await driver.findElement(By.css('.unit-input__input')) + const inputAmount = await driver.findElement( + By.css('.unit-input__input'), + ); - await inputAmount.clear() - await driver.delay(50) - await inputAmount.sendKeys('2.2') + await inputAmount.clear(); + await driver.delay(50); + await inputAmount.sendKeys('2.2'); - await driver.clickElement(By.css('.advanced-gas-options-btn')) - await driver.delay(regularDelayMs) + await driver.clickElement(By.css('.advanced-gas-options-btn')); + await driver.delay(regularDelayMs); - const gasModal = await driver.findElement(By.css('span .modal')) + const gasModal = await driver.findElement(By.css('span .modal')); const [gasPriceInput, gasLimitInput] = await driver.findElements( By.css('.advanced-gas-inputs__gas-edit-row__input'), - ) + ); - await gasPriceInput.clear() - await driver.delay(50) - await gasPriceInput.sendKeys('8') - await driver.delay(50) - await driver.delay(tinyDelayMs) - await driver.delay(50) + await gasPriceInput.clear(); + await driver.delay(50); + await gasPriceInput.sendKeys('8'); + await driver.delay(50); + await driver.delay(tinyDelayMs); + await driver.delay(50); - await gasLimitInput.clear() - await driver.delay(50) - await gasLimitInput.sendKeys('100000') + await gasLimitInput.clear(); + await driver.delay(50); + await gasLimitInput.sendKeys('100000'); - await driver.delay(1000) + await driver.delay(1000); - await driver.clickElement(By.xpath(`//button[contains(text(), 'Save')]`)) - await driver.wait(until.stalenessOf(gasModal)) - await driver.delay(regularDelayMs) + await driver.clickElement(By.xpath(`//button[contains(text(), 'Save')]`)); + await driver.wait(until.stalenessOf(gasModal)); + await driver.delay(regularDelayMs); - await driver.clickElement(By.xpath(`//button[contains(text(), 'Next')]`)) - await driver.delay(regularDelayMs) - }) + await driver.clickElement(By.xpath(`//button[contains(text(), 'Next')]`)); + await driver.delay(regularDelayMs); + }); it('has correct updated value on the confirm screen the transaction', async function () { const transactionAmounts = await driver.findElements( By.css('.currency-display-component__text'), - ) - const transactionAmount = transactionAmounts[0] - assert.equal(await transactionAmount.getText(), '2.2') + ); + const transactionAmount = transactionAmounts[0]; + assert.equal(await transactionAmount.getText(), '2.2'); - const transactionFee = transactionAmounts[1] - assert.equal(await transactionFee.getText(), '0.0008') - }) + const transactionFee = transactionAmounts[1]; + assert.equal(await transactionFee.getText(), '0.0008'); + }); it('confirms the transaction', async function () { await driver.clickElement( By.xpath(`//button[contains(text(), 'Confirm')]`), - ) - await driver.delay(regularDelayMs) - }) + ); + await driver.delay(regularDelayMs); + }); it('finds the transaction in the transactions list', async function () { - await driver.clickElement(By.css('[data-testid="home__activity-tab"]')) + await driver.clickElement(By.css('[data-testid="home__activity-tab"]')); await driver.wait(async () => { const confirmedTxes = await driver.findElements( By.css( '.transaction-list__completed-transactions .transaction-list-item', ), - ) - return confirmedTxes.length === 1 - }, 10000) + ); + return confirmedTxes.length === 1; + }, 10000); const txValues = await driver.findElements( By.css('.transaction-list-item__primary-currency'), - ) - assert.equal(txValues.length, 1) - assert.ok(/-2.2\s*ETH/u.test(await txValues[0].getText())) - }) - }) -}) + ); + assert.equal(txValues.length, 1); + assert.ok(/-2.2\s*ETH/u.test(await txValues[0].getText())); + }); + }); +}); diff --git a/test/e2e/signature-request.spec.js b/test/e2e/signature-request.spec.js index 3e4307ffa..da05aa00d 100644 --- a/test/e2e/signature-request.spec.js +++ b/test/e2e/signature-request.spec.js @@ -1,172 +1,172 @@ -const assert = require('assert') -const path = require('path') -const webdriver = require('selenium-webdriver') +const assert = require('assert'); +const path = require('path'); +const webdriver = require('selenium-webdriver'); -const { By, Key, until } = webdriver -const { regularDelayMs, largeDelayMs } = require('./helpers') -const { buildWebDriver } = require('./webdriver') -const Ganache = require('./ganache') -const FixtureServer = require('./fixture-server') +const { By, Key, until } = webdriver; +const { regularDelayMs, largeDelayMs } = require('./helpers'); +const { buildWebDriver } = require('./webdriver'); +const Ganache = require('./ganache'); +const FixtureServer = require('./fixture-server'); -const fixtureServer = new FixtureServer() +const fixtureServer = new FixtureServer(); -const ganacheServer = new Ganache() +const ganacheServer = new Ganache(); describe('MetaMask', function () { - let driver - let publicAddress + let driver; + let publicAddress; - this.timeout(0) - this.bail(true) + this.timeout(0); + this.bail(true); before(async function () { - await ganacheServer.start() - await fixtureServer.start() + await ganacheServer.start(); + await fixtureServer.start(); await fixtureServer.loadState( path.join(__dirname, 'fixtures', 'imported-account'), - ) - publicAddress = '0x5cfe73b6021e818b776b421b1c4db2474086a7e1' - const result = await buildWebDriver() - driver = result.driver - await driver.navigate() - }) + ); + publicAddress = '0x5cfe73b6021e818b776b421b1c4db2474086a7e1'; + const result = await buildWebDriver(); + driver = result.driver; + await driver.navigate(); + }); afterEach(async function () { if (process.env.SELENIUM_BROWSER === 'chrome') { - const errors = await driver.checkBrowserForConsoleErrors(driver) + const errors = await driver.checkBrowserForConsoleErrors(driver); if (errors.length) { - const errorReports = errors.map((err) => err.message) + const errorReports = errors.map((err) => err.message); const errorMessage = `Errors found in browser console:\n${errorReports.join( '\n', - )}` - console.error(new Error(errorMessage)) + )}`; + console.error(new Error(errorMessage)); } } if (this.currentTest.state === 'failed') { - await driver.verboseReportOnFailure(this.currentTest.title) + await driver.verboseReportOnFailure(this.currentTest.title); } - }) + }); after(async function () { - await ganacheServer.quit() - await fixtureServer.stop() - await driver.quit() - }) + await ganacheServer.quit(); + await fixtureServer.stop(); + await driver.quit(); + }); describe('successfully signs typed data', function () { - let extension - let popup - let dapp - let windowHandles + let extension; + let popup; + let dapp; + let windowHandles; it('accepts the account password after lock', async function () { - await driver.delay(1000) - const passwordField = await driver.findElement(By.id('password')) - await passwordField.sendKeys('correct horse battery staple') - await passwordField.sendKeys(Key.ENTER) - await driver.delay(largeDelayMs * 4) - }) + await driver.delay(1000); + const passwordField = await driver.findElement(By.id('password')); + await passwordField.sendKeys('correct horse battery staple'); + await passwordField.sendKeys(Key.ENTER); + await driver.delay(largeDelayMs * 4); + }); it('connects to the dapp', async function () { - await driver.openNewPage('http://127.0.0.1:8080/') - await driver.delay(regularDelayMs) + await driver.openNewPage('http://127.0.0.1:8080/'); + await driver.delay(regularDelayMs); await driver.clickElement( By.xpath(`//button[contains(text(), 'Connect')]`), - ) + ); - await driver.delay(regularDelayMs) + await driver.delay(regularDelayMs); - await driver.waitUntilXWindowHandles(3) - windowHandles = await driver.getAllWindowHandles() + await driver.waitUntilXWindowHandles(3); + windowHandles = await driver.getAllWindowHandles(); - extension = windowHandles[0] + extension = windowHandles[0]; dapp = await driver.switchToWindowWithTitle( 'E2E Test Dapp', windowHandles, - ) + ); popup = windowHandles.find( (handle) => handle !== extension && handle !== dapp, - ) + ); - await driver.switchToWindow(popup) + await driver.switchToWindow(popup); - await driver.delay(regularDelayMs) + await driver.delay(regularDelayMs); - await driver.clickElement(By.xpath(`//button[contains(text(), 'Next')]`)) + await driver.clickElement(By.xpath(`//button[contains(text(), 'Next')]`)); await driver.clickElement( By.xpath(`//button[contains(text(), 'Connect')]`), - ) + ); - await driver.waitUntilXWindowHandles(2) - await driver.switchToWindow(dapp) - }) + await driver.waitUntilXWindowHandles(2); + await driver.switchToWindow(dapp); + }); it('creates a sign typed data signature request', async function () { - await driver.clickElement(By.id('signTypedDataV4'), 10000) - await driver.delay(largeDelayMs) + await driver.clickElement(By.id('signTypedDataV4'), 10000); + await driver.delay(largeDelayMs); - await driver.delay(regularDelayMs) - windowHandles = await driver.getAllWindowHandles() + await driver.delay(regularDelayMs); + windowHandles = await driver.getAllWindowHandles(); await driver.switchToWindowWithTitle( 'MetaMask Notification', windowHandles, - ) - await driver.delay(regularDelayMs) + ); + await driver.delay(regularDelayMs); const title = await driver.findElement( By.css('.signature-request-content__title'), - ) + ); const name = await driver.findElement( By.css('.signature-request-content__info--bolded'), - ) + ); const content = await driver.findElements( By.css('.signature-request-content__info'), - ) - const origin = content[0] - const address = content[1] - assert.equal(await title.getText(), 'Signature Request') - assert.equal(await name.getText(), 'Ether Mail') - assert.equal(await origin.getText(), 'http://127.0.0.1:8080') + ); + const origin = content[0]; + const address = content[1]; + assert.equal(await title.getText(), 'Signature Request'); + assert.equal(await name.getText(), 'Ether Mail'); + assert.equal(await origin.getText(), 'http://127.0.0.1:8080'); assert.equal( await address.getText(), `${publicAddress.slice(0, 8)}...${publicAddress.slice( publicAddress.length - 8, )}`, - ) - }) + ); + }); it('signs the transaction', async function () { await driver.clickElement( By.xpath(`//button[contains(text(), 'Sign')]`), 10000, - ) - await driver.delay(regularDelayMs) + ); + await driver.delay(regularDelayMs); - extension = windowHandles[0] - await driver.switchToWindow(extension) - }) + extension = windowHandles[0]; + await driver.switchToWindow(extension); + }); it('gets the current accounts address', async function () { await driver.clickElement( By.css('[data-testid="account-options-menu-button"]'), - ) + ); await driver.clickElement( By.css('[data-testid="account-options-menu__account-details"]'), - ) - await driver.delay(regularDelayMs) + ); + await driver.delay(regularDelayMs); const addressInput = await driver.findElement( By.css('.readonly-input__input'), - ) - const newPublicAddress = await addressInput.getAttribute('value') - const accountModal = await driver.findElement(By.css('span .modal')) + ); + const newPublicAddress = await addressInput.getAttribute('value'); + const accountModal = await driver.findElement(By.css('span .modal')); - await driver.clickElement(By.css('.account-modal__close')) + await driver.clickElement(By.css('.account-modal__close')); - await driver.wait(until.stalenessOf(accountModal)) - await driver.delay(regularDelayMs) - assert.equal(newPublicAddress.toLowerCase(), publicAddress) - }) - }) -}) + await driver.wait(until.stalenessOf(accountModal)); + await driver.delay(regularDelayMs); + assert.equal(newPublicAddress.toLowerCase(), publicAddress); + }); + }); +}); diff --git a/test/e2e/tests/localization.spec.js b/test/e2e/tests/localization.spec.js index 5ba5558f7..27b93a269 100644 --- a/test/e2e/tests/localization.spec.js +++ b/test/e2e/tests/localization.spec.js @@ -1,6 +1,6 @@ -const { strict: assert } = require('assert') -const { By, Key } = require('selenium-webdriver') -const { withFixtures } = require('../helpers') +const { strict: assert } = require('assert'); +const { By, Key } = require('selenium-webdriver'); +const { withFixtures } = require('../helpers'); describe('Localization', function () { it('can correctly display Philippine peso symbol and code', async function () { @@ -12,22 +12,24 @@ describe('Localization', function () { balance: 25000000000000000000, }, ], - } + }; await withFixtures( { fixtures: 'localization', ganacheOptions, title: this.test.title }, async ({ driver }) => { - await driver.navigate() - const passwordField = await driver.findElement(By.css('#password')) - await passwordField.sendKeys('correct horse battery staple') - await passwordField.sendKeys(Key.ENTER) + await driver.navigate(); + const passwordField = await driver.findElement(By.css('#password')); + await passwordField.sendKeys('correct horse battery staple'); + await passwordField.sendKeys(Key.ENTER); const secondaryBalance = await driver.findElement( By.css('[data-testid="eth-overview__secondary-currency"]'), - ) - const secondaryBalanceText = await secondaryBalance.getText() - const [fiatAmount, fiatUnit] = secondaryBalanceText.trim().split(/\s+/u) - assert.ok(fiatAmount.startsWith('₱')) - assert.equal(fiatUnit, 'PHP') + ); + const secondaryBalanceText = await secondaryBalance.getText(); + const [fiatAmount, fiatUnit] = secondaryBalanceText + .trim() + .split(/\s+/u); + assert.ok(fiatAmount.startsWith('₱')); + assert.equal(fiatUnit, 'PHP'); }, - ) - }) -}) + ); + }); +}); diff --git a/test/e2e/tests/personal-sign.spec.js b/test/e2e/tests/personal-sign.spec.js index 462eab11b..e9efc5ea4 100644 --- a/test/e2e/tests/personal-sign.spec.js +++ b/test/e2e/tests/personal-sign.spec.js @@ -1,6 +1,6 @@ -const { strict: assert } = require('assert') -const { By, Key } = require('selenium-webdriver') -const { withFixtures } = require('../helpers') +const { strict: assert } = require('assert'); +const { By, Key } = require('selenium-webdriver'); +const { withFixtures } = require('../helpers'); describe('Personal sign', function () { it('can initiate and confirm a personal sign', async function () { @@ -12,7 +12,7 @@ describe('Personal sign', function () { balance: 25000000000000000000, }, ], - } + }; await withFixtures( { dapp: true, @@ -21,34 +21,34 @@ describe('Personal sign', function () { title: this.test.title, }, async ({ driver }) => { - await driver.navigate() - const passwordField = await driver.findElement(By.css('#password')) - await passwordField.sendKeys('correct horse battery staple') - await passwordField.sendKeys(Key.ENTER) + await driver.navigate(); + const passwordField = await driver.findElement(By.css('#password')); + await passwordField.sendKeys('correct horse battery staple'); + await passwordField.sendKeys(Key.ENTER); - await driver.openNewPage('http://127.0.0.1:8080/') - await driver.clickElement(By.id('personalSign')) + await driver.openNewPage('http://127.0.0.1:8080/'); + await driver.clickElement(By.id('personalSign')); - await driver.waitUntilXWindowHandles(3) + await driver.waitUntilXWindowHandles(3); - const windowHandles = await driver.getAllWindowHandles() + const windowHandles = await driver.getAllWindowHandles(); await driver.switchToWindowWithTitle( 'MetaMask Notification', windowHandles, - ) + ); const personalMessageRow = await driver.findElement( By.css('.request-signature__row-value'), - ) - const personalMessage = await personalMessageRow.getText() - assert.equal(personalMessage, 'Example `personal_sign` message') + ); + const personalMessage = await personalMessageRow.getText(); + assert.equal(personalMessage, 'Example `personal_sign` message'); await driver.clickElement( By.css('[data-testid="request-signature__sign"]'), - ) + ); - await driver.waitUntilXWindowHandles(2) + await driver.waitUntilXWindowHandles(2); }, - ) - }) -}) + ); + }); +}); diff --git a/test/e2e/tests/simple-send.spec.js b/test/e2e/tests/simple-send.spec.js index 332117951..e7564a071 100644 --- a/test/e2e/tests/simple-send.spec.js +++ b/test/e2e/tests/simple-send.spec.js @@ -1,5 +1,5 @@ -const { By, Key } = require('selenium-webdriver') -const { withFixtures } = require('../helpers') +const { By, Key } = require('selenium-webdriver'); +const { withFixtures } = require('../helpers'); describe('Simple send', function () { it('can send a simple transaction from one account to another', async function () { @@ -11,34 +11,34 @@ describe('Simple send', function () { balance: 25000000000000000000, }, ], - } + }; await withFixtures( { fixtures: 'imported-account', ganacheOptions, title: this.test.title }, async ({ driver }) => { - await driver.navigate() - const passwordField = await driver.findElement(By.css('#password')) - await passwordField.sendKeys('correct horse battery staple') - await passwordField.sendKeys(Key.ENTER) - await driver.clickElement(By.css('[data-testid="eth-overview-send"]')) + await driver.navigate(); + const passwordField = await driver.findElement(By.css('#password')); + await passwordField.sendKeys('correct horse battery staple'); + await passwordField.sendKeys(Key.ENTER); + await driver.clickElement(By.css('[data-testid="eth-overview-send"]')); const recipientAddressField = await driver.findElement( By.css('[data-testid="ens-input"]'), - ) + ); await recipientAddressField.sendKeys( '0x985c30949c92df7a0bd42e0f3e3d539ece98db24', - ) + ); const amountField = await driver.findElement( By.css('.unit-input__input'), - ) - await amountField.sendKeys('1') + ); + await amountField.sendKeys('1'); await driver.clickElement( By.css('[data-testid="page-container-footer-next"]'), - ) + ); await driver.clickElement( By.css('[data-testid="page-container-footer-next"]'), - ) - await driver.clickElement(By.css('[data-testid="home__activity-tab"]')) - await driver.findElement(By.css('.transaction-list-item')) + ); + await driver.clickElement(By.css('[data-testid="home__activity-tab"]')); + await driver.findElement(By.css('.transaction-list-item')); }, - ) - }) -}) + ); + }); +}); diff --git a/test/e2e/threebox.spec.js b/test/e2e/threebox.spec.js index 55f771a44..207f15afd 100644 --- a/test/e2e/threebox.spec.js +++ b/test/e2e/threebox.spec.js @@ -1,23 +1,23 @@ -const assert = require('assert') -const webdriver = require('selenium-webdriver') -const getPort = require('get-port') +const assert = require('assert'); +const webdriver = require('selenium-webdriver'); +const getPort = require('get-port'); -const { By, until } = webdriver -const enLocaleMessages = require('../../app/_locales/en/messages.json') -const { tinyDelayMs, regularDelayMs, largeDelayMs } = require('./helpers') -const { buildWebDriver } = require('./webdriver') -const Ganache = require('./ganache') +const { By, until } = webdriver; +const enLocaleMessages = require('../../app/_locales/en/messages.json'); +const { tinyDelayMs, regularDelayMs, largeDelayMs } = require('./helpers'); +const { buildWebDriver } = require('./webdriver'); +const Ganache = require('./ganache'); -const ganacheServer = new Ganache() +const ganacheServer = new Ganache(); describe('MetaMask', function () { - let driver + let driver; const testSeedPhrase = - 'forum vessel pink push lonely enact gentle tail admit parrot grunt dress' + 'forum vessel pink push lonely enact gentle tail admit parrot grunt dress'; - this.timeout(0) - this.bail(true) + this.timeout(0); + this.bail(true); before(async function () { await ganacheServer.start({ @@ -28,275 +28,275 @@ describe('MetaMask', function () { balance: 25000000000000000000, }, ], - }) - const result = await buildWebDriver({ port: await getPort() }) - driver = result.driver - await driver.navigate() - }) + }); + const result = await buildWebDriver({ port: await getPort() }); + driver = result.driver; + await driver.navigate(); + }); afterEach(async function () { if (process.env.SELENIUM_BROWSER === 'chrome') { - const errors = await driver.checkBrowserForConsoleErrors(driver) + const errors = await driver.checkBrowserForConsoleErrors(driver); if (errors.length) { - const errorReports = errors.map((err) => err.message) + const errorReports = errors.map((err) => err.message); const errorMessage = `Errors found in browser console:\n${errorReports.join( '\n', - )}` - console.error(new Error(errorMessage)) + )}`; + console.error(new Error(errorMessage)); } } if (this.currentTest.state === 'failed') { - await driver.verboseReportOnFailure(this.currentTest.title) + await driver.verboseReportOnFailure(this.currentTest.title); } - }) + }); after(async function () { - await ganacheServer.quit() - await driver.quit() - }) + await ganacheServer.quit(); + await driver.quit(); + }); describe('set up data to be restored by 3box', function () { describe('First time flow starting from an existing seed phrase', function () { it('clicks the continue button on the welcome screen', async function () { - await driver.findElement(By.css('.welcome-page__header')) + await driver.findElement(By.css('.welcome-page__header')); await driver.clickElement( By.xpath( `//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`, ), - ) - await driver.delay(largeDelayMs) - }) + ); + await driver.delay(largeDelayMs); + }); it('clicks the "Import Wallet" option', async function () { await driver.clickElement( By.xpath(`//button[contains(text(), 'Import wallet')]`), - ) - await driver.delay(largeDelayMs) - }) + ); + await driver.delay(largeDelayMs); + }); it('clicks the "No thanks" option on the metametrics opt-in screen', async function () { - await driver.clickElement(By.css('.btn-default')) - await driver.delay(largeDelayMs) - }) + await driver.clickElement(By.css('.btn-default')); + await driver.delay(largeDelayMs); + }); it('imports a seed phrase', async function () { const [seedTextArea] = await driver.findElements( By.css('input[placeholder="Paste seed phrase from clipboard"]'), - ) - await seedTextArea.sendKeys(testSeedPhrase) - await driver.delay(regularDelayMs) + ); + await seedTextArea.sendKeys(testSeedPhrase); + await driver.delay(regularDelayMs); - const [password] = await driver.findElements(By.id('password')) - await password.sendKeys('correct horse battery staple') + const [password] = await driver.findElements(By.id('password')); + await password.sendKeys('correct horse battery staple'); const [confirmPassword] = await driver.findElements( By.id('confirm-password'), - ) - confirmPassword.sendKeys('correct horse battery staple') + ); + confirmPassword.sendKeys('correct horse battery staple'); - await driver.clickElement(By.css('.first-time-flow__terms')) + await driver.clickElement(By.css('.first-time-flow__terms')); await driver.clickElement( By.xpath(`//button[contains(text(), 'Import')]`), - ) - await driver.delay(regularDelayMs) - }) + ); + await driver.delay(regularDelayMs); + }); it('clicks through the success screen', async function () { await driver.findElement( By.xpath(`//div[contains(text(), 'Congratulations')]`), - ) + ); await driver.clickElement( By.xpath( `//button[contains(text(), '${enLocaleMessages.endOfFlowMessage10.message}')]`, ), - ) - await driver.delay(regularDelayMs) - }) + ); + await driver.delay(regularDelayMs); + }); it('balance renders', async function () { const balance = await driver.findElement( By.css('[data-testid="wallet-balance"] .list-item__heading'), - ) - await driver.wait(until.elementTextMatches(balance, /25\s*ETH/u)) - await driver.delay(regularDelayMs) - }) - }) + ); + await driver.wait(until.elementTextMatches(balance, /25\s*ETH/u)); + await driver.delay(regularDelayMs); + }); + }); describe('turns on threebox syncing', function () { it('goes to the settings screen', async function () { - await driver.clickElement(By.css('.account-menu__icon')) - await driver.delay(regularDelayMs) + await driver.clickElement(By.css('.account-menu__icon')); + await driver.delay(regularDelayMs); await driver.clickElement( By.xpath(`//div[contains(text(), 'Settings')]`), - ) - }) + ); + }); it('turns on threebox syncing', async function () { await driver.clickElement( By.xpath(`//div[contains(text(), 'Advanced')]`), - ) + ); await driver.clickElement( By.css('[data-testid="advanced-setting-3box"] .toggle-button div'), - ) - }) - }) + ); + }); + }); describe('updates settings and address book', function () { it('navigates to General settings', async function () { await driver.clickElement( By.xpath(`//div[contains(text(), 'General')]`), - ) - }) + ); + }); it('turns on use of blockies', async function () { - await driver.clickElement(By.css('.toggle-button > div')) - }) + await driver.clickElement(By.css('.toggle-button > div')); + }); it('adds an address to the contact list', async function () { await driver.clickElement( By.xpath(`//div[contains(text(), 'Contacts')]`), - ) + ); - await driver.clickElement(By.css('.address-book-add-button__button')) - await driver.delay(tinyDelayMs) + await driver.clickElement(By.css('.address-book-add-button__button')); + await driver.delay(tinyDelayMs); - const addAddressInputs = await driver.findElements(By.css('input')) - await addAddressInputs[0].sendKeys('Test User Name 11') + const addAddressInputs = await driver.findElements(By.css('input')); + await addAddressInputs[0].sendKeys('Test User Name 11'); - await driver.delay(tinyDelayMs) + await driver.delay(tinyDelayMs); await addAddressInputs[1].sendKeys( '0x2f318C334780961FB129D2a6c30D0763d9a5C970', - ) + ); - await driver.delay(largeDelayMs * 2) + await driver.delay(largeDelayMs * 2); await driver.clickElement( By.xpath(`//button[contains(text(), 'Save')]`), - ) + ); await driver.findElement( By.xpath(`//div[contains(text(), 'Test User Name 11')]`), - ) - await driver.delay(regularDelayMs) - }) - }) - }) + ); + await driver.delay(regularDelayMs); + }); + }); + }); describe('restoration from 3box', function () { - let driver2 + let driver2; before(async function () { - const result = await buildWebDriver({ port: await getPort() }) - driver2 = result.driver - await driver2.navigate() - }) + const result = await buildWebDriver({ port: await getPort() }); + driver2 = result.driver; + await driver2.navigate(); + }); after(async function () { - await driver2.quit() - }) + await driver2.quit(); + }); describe('First time flow starting from an existing seed phrase', function () { it('clicks the continue button on the welcome screen', async function () { - await driver2.findElement(By.css('.welcome-page__header')) + await driver2.findElement(By.css('.welcome-page__header')); await driver2.clickElement( By.xpath( `//button[contains(text(), '${enLocaleMessages.getStarted.message}')]`, ), - ) - await driver2.delay(largeDelayMs) - }) + ); + await driver2.delay(largeDelayMs); + }); it('clicks the "Import Wallet" option', async function () { await driver2.clickElement( By.xpath(`//button[contains(text(), 'Import wallet')]`), - ) - await driver2.delay(largeDelayMs) - }) + ); + await driver2.delay(largeDelayMs); + }); it('clicks the "No thanks" option on the metametrics opt-in screen', async function () { - await driver2.clickElement(By.css('.btn-default')) - await driver2.delay(largeDelayMs) - }) + await driver2.clickElement(By.css('.btn-default')); + await driver2.delay(largeDelayMs); + }); it('imports a seed phrase', async function () { const [seedTextArea] = await driver2.findElements( By.css('input[placeholder="Paste seed phrase from clipboard"]'), - ) - await seedTextArea.sendKeys(testSeedPhrase) - await driver2.delay(regularDelayMs) + ); + await seedTextArea.sendKeys(testSeedPhrase); + await driver2.delay(regularDelayMs); - const [password] = await driver2.findElements(By.id('password')) - await password.sendKeys('correct horse battery staple') + const [password] = await driver2.findElements(By.id('password')); + await password.sendKeys('correct horse battery staple'); const [confirmPassword] = await driver2.findElements( By.id('confirm-password'), - ) - confirmPassword.sendKeys('correct horse battery staple') + ); + confirmPassword.sendKeys('correct horse battery staple'); - await driver2.clickElement(By.css('.first-time-flow__terms')) + await driver2.clickElement(By.css('.first-time-flow__terms')); await driver2.clickElement( By.xpath(`//button[contains(text(), 'Import')]`), - ) - await driver2.delay(regularDelayMs) - }) + ); + await driver2.delay(regularDelayMs); + }); it('clicks through the success screen', async function () { await driver2.findElement( By.xpath(`//div[contains(text(), 'Congratulations')]`), - ) + ); await driver2.clickElement( By.xpath( `//button[contains(text(), '${enLocaleMessages.endOfFlowMessage10.message}')]`, ), - ) - await driver2.delay(regularDelayMs) - }) + ); + await driver2.delay(regularDelayMs); + }); it('balance renders', async function () { const balance = await driver2.findElement( By.css('[data-testid="wallet-balance"] .list-item__heading'), - ) - await driver2.wait(until.elementTextMatches(balance, /25\s*ETH/u)) - await driver2.delay(regularDelayMs) - }) - }) + ); + await driver2.wait(until.elementTextMatches(balance, /25\s*ETH/u)); + await driver2.delay(regularDelayMs); + }); + }); describe('restores 3box data', function () { it('confirms the 3box restore notification', async function () { - await driver2.clickElement(By.css('.home-notification__accept-button')) - }) + await driver2.clickElement(By.css('.home-notification__accept-button')); + }); it('goes to the settings screen', async function () { - await driver2.clickElement(By.css('.account-menu__icon')) - await driver2.delay(regularDelayMs) + await driver2.clickElement(By.css('.account-menu__icon')); + await driver2.delay(regularDelayMs); await driver2.clickElement( By.xpath(`//div[contains(text(), 'Settings')]`), - ) - }) + ); + }); it('finds the blockies toggle turned on', async function () { - await driver2.delay(regularDelayMs) + await driver2.delay(regularDelayMs); const toggleLabel = await driver2.findElement( By.css('.toggle-button__status'), - ) - const toggleLabelText = await toggleLabel.getText() - assert.equal(toggleLabelText, 'ON') - }) + ); + const toggleLabelText = await toggleLabel.getText(); + assert.equal(toggleLabelText, 'ON'); + }); it('finds the restored address in the contact list', async function () { await driver2.clickElement( By.xpath(`//div[contains(text(), 'Contacts')]`), - ) - await driver2.delay(regularDelayMs) + ); + await driver2.delay(regularDelayMs); await driver2.findElement( By.xpath(`//div[contains(text(), 'Test User Name 11')]`), - ) - await driver2.delay(regularDelayMs) - }) - }) - }) -}) + ); + await driver2.delay(regularDelayMs); + }); + }); + }); +}); diff --git a/test/e2e/webdriver/chrome.js b/test/e2e/webdriver/chrome.js index 75e031475..e0bb65626 100644 --- a/test/e2e/webdriver/chrome.js +++ b/test/e2e/webdriver/chrome.js @@ -1,29 +1,31 @@ -const { Builder } = require('selenium-webdriver') -const chrome = require('selenium-webdriver/chrome') +const { Builder } = require('selenium-webdriver'); +const chrome = require('selenium-webdriver/chrome'); /** * A wrapper around a {@code WebDriver} instance exposing Chrome-specific functionality */ class ChromeDriver { static async build({ responsive, port }) { - const args = [`load-extension=dist/chrome`] + const args = [`load-extension=dist/chrome`]; if (responsive) { - args.push('--auto-open-devtools-for-tabs') + args.push('--auto-open-devtools-for-tabs'); } - const options = new chrome.Options().addArguments(args) - const builder = new Builder().forBrowser('chrome').setChromeOptions(options) + const options = new chrome.Options().addArguments(args); + const builder = new Builder() + .forBrowser('chrome') + .setChromeOptions(options); if (port) { - const service = new chrome.ServiceBuilder().setPort(port) - builder.setChromeService(service) + const service = new chrome.ServiceBuilder().setPort(port); + builder.setChromeService(service); } - const driver = builder.build() - const chromeDriver = new ChromeDriver(driver) - const extensionId = await chromeDriver.getExtensionIdByName('MetaMask') + const driver = builder.build(); + const chromeDriver = new ChromeDriver(driver); + const extensionId = await chromeDriver.getExtensionIdByName('MetaMask'); return { driver, extensionUrl: `chrome-extension://${extensionId}`, - } + }; } /** @@ -31,7 +33,7 @@ class ChromeDriver { * @param {!ThenableWebDriver} driver - a {@code WebDriver} instance */ constructor(driver) { - this._driver = driver + this._driver = driver; } /** @@ -40,7 +42,7 @@ class ChromeDriver { * @returns {Promise} the extension ID */ async getExtensionIdByName(extensionName) { - await this._driver.get('chrome://extensions') + await this._driver.get('chrome://extensions'); return await this._driver.executeScript(` const extensions = document.querySelector("extensions-manager").shadowRoot .querySelector("extensions-item-list").shadowRoot @@ -55,8 +57,8 @@ class ChromeDriver { } return undefined - `) + `); } } -module.exports = ChromeDriver +module.exports = ChromeDriver; diff --git a/test/e2e/webdriver/driver.js b/test/e2e/webdriver/driver.js index 9f094e1a6..f1da84a21 100644 --- a/test/e2e/webdriver/driver.js +++ b/test/e2e/webdriver/driver.js @@ -1,6 +1,6 @@ -const { promises: fs } = require('fs') -const { strict: assert } = require('assert') -const { until, error: webdriverError } = require('selenium-webdriver') +const { promises: fs } = require('fs'); +const { strict: assert } = require('assert'); +const { until, error: webdriverError } = require('selenium-webdriver'); class Driver { /** @@ -9,152 +9,152 @@ class Driver { * @param {number} timeout */ constructor(driver, browser, extensionUrl, timeout = 10000) { - this.driver = driver - this.browser = browser - this.extensionUrl = extensionUrl - this.timeout = timeout + this.driver = driver; + this.browser = browser; + this.extensionUrl = extensionUrl; + this.timeout = timeout; } async delay(time) { - await new Promise((resolve) => setTimeout(resolve, time)) + await new Promise((resolve) => setTimeout(resolve, time)); } async wait(condition, timeout = this.timeout) { - await this.driver.wait(condition, timeout) + await this.driver.wait(condition, timeout); } async quit() { - await this.driver.quit() + await this.driver.quit(); } // Element interactions async findElement(locator) { - return await this.driver.wait(until.elementLocated(locator), this.timeout) + return await this.driver.wait(until.elementLocated(locator), this.timeout); } async findVisibleElement(locator) { - const element = await this.findElement(locator) - await this.driver.wait(until.elementIsVisible(element), this.timeout) - return element + const element = await this.findElement(locator); + await this.driver.wait(until.elementIsVisible(element), this.timeout); + return element; } async findClickableElement(locator) { - const element = await this.findElement(locator) + const element = await this.findElement(locator); await Promise.all([ this.driver.wait(until.elementIsVisible(element), this.timeout), this.driver.wait(until.elementIsEnabled(element), this.timeout), - ]) - return element + ]); + return element; } async findElements(locator) { - return await this.driver.wait(until.elementsLocated(locator), this.timeout) + return await this.driver.wait(until.elementsLocated(locator), this.timeout); } async findClickableElements(locator) { - const elements = await this.findElements(locator) + const elements = await this.findElements(locator); await Promise.all( elements.reduce((acc, element) => { acc.push( this.driver.wait(until.elementIsVisible(element), this.timeout), this.driver.wait(until.elementIsEnabled(element), this.timeout), - ) - return acc + ); + return acc; }, []), - ) - return elements + ); + return elements; } async clickElement(locator) { - const element = await this.findClickableElement(locator) - await element.click() + const element = await this.findClickableElement(locator); + await element.click(); } async clickPoint(locator, x, y) { - const element = await this.findElement(locator) + const element = await this.findElement(locator); await this.driver .actions() .move({ origin: element, x, y }) .click() - .perform() + .perform(); } async scrollToElement(element) { await this.driver.executeScript( 'arguments[0].scrollIntoView(true)', element, - ) + ); } async assertElementNotPresent(locator) { - let dataTab + let dataTab; try { - dataTab = await this.findElement(locator) + dataTab = await this.findElement(locator); } catch (err) { assert( err instanceof webdriverError.NoSuchElementError || err instanceof webdriverError.TimeoutError, - ) + ); } - assert.ok(!dataTab, 'Found element that should not be present') + assert.ok(!dataTab, 'Found element that should not be present'); } // Navigation async navigate(page = Driver.PAGES.HOME) { - return await this.driver.get(`${this.extensionUrl}/${page}.html`) + return await this.driver.get(`${this.extensionUrl}/${page}.html`); } // Metrics async collectMetrics() { - return await this.driver.executeScript(collectMetrics) + return await this.driver.executeScript(collectMetrics); } // Window management async openNewPage(url) { - const newHandle = await this.driver.switchTo().newWindow() - await this.driver.get(url) - return newHandle + const newHandle = await this.driver.switchTo().newWindow(); + await this.driver.get(url); + return newHandle; } async switchToWindow(handle) { - await this.driver.switchTo().window(handle) + await this.driver.switchTo().window(handle); } async getAllWindowHandles() { - return await this.driver.getAllWindowHandles() + return await this.driver.getAllWindowHandles(); } async waitUntilXWindowHandles(x, delayStep = 1000, timeout = 5000) { - let timeElapsed = 0 - let windowHandles = [] + let timeElapsed = 0; + let windowHandles = []; while (timeElapsed <= timeout) { - windowHandles = await this.driver.getAllWindowHandles() + windowHandles = await this.driver.getAllWindowHandles(); if (windowHandles.length === x) { - return windowHandles + return windowHandles; } - await this.delay(delayStep) - timeElapsed += delayStep + await this.delay(delayStep); + timeElapsed += delayStep; } - throw new Error('waitUntilXWindowHandles timed out polling window handles') + throw new Error('waitUntilXWindowHandles timed out polling window handles'); } async switchToWindowWithTitle(title, windowHandles) { // eslint-disable-next-line no-param-reassign - windowHandles = windowHandles || (await this.driver.getAllWindowHandles()) + windowHandles = windowHandles || (await this.driver.getAllWindowHandles()); for (const handle of windowHandles) { - await this.driver.switchTo().window(handle) - const handleTitle = await this.driver.getTitle() + await this.driver.switchTo().window(handle); + const handleTitle = await this.driver.getTitle(); if (handleTitle === title) { - return handle + return handle; } } - throw new Error(`No window with title: ${title}`) + throw new Error(`No window with title: ${title}`); } /** @@ -165,14 +165,14 @@ class Driver { */ async closeAllWindowHandlesExcept(exceptions, windowHandles) { // eslint-disable-next-line no-param-reassign - windowHandles = windowHandles || (await this.driver.getAllWindowHandles()) + windowHandles = windowHandles || (await this.driver.getAllWindowHandles()); for (const handle of windowHandles) { if (!exceptions.includes(handle)) { - await this.driver.switchTo().window(handle) - await this.delay(1000) - await this.driver.close() - await this.delay(1000) + await this.driver.switchTo().window(handle); + await this.delay(1000); + await this.driver.close(); + await this.delay(1000); } } } @@ -180,41 +180,41 @@ class Driver { // Error handling async verboseReportOnFailure(title) { - const artifactDir = `./test-artifacts/${this.browser}/${title}` - const filepathBase = `${artifactDir}/test-failure` - await fs.mkdir(artifactDir, { recursive: true }) - const screenshot = await this.driver.takeScreenshot() + const artifactDir = `./test-artifacts/${this.browser}/${title}`; + const filepathBase = `${artifactDir}/test-failure`; + await fs.mkdir(artifactDir, { recursive: true }); + const screenshot = await this.driver.takeScreenshot(); await fs.writeFile(`${filepathBase}-screenshot.png`, screenshot, { encoding: 'base64', - }) - const htmlSource = await this.driver.getPageSource() - await fs.writeFile(`${filepathBase}-dom.html`, htmlSource) + }); + const htmlSource = await this.driver.getPageSource(); + await fs.writeFile(`${filepathBase}-dom.html`, htmlSource); const uiState = await this.driver.executeScript( () => window.getCleanAppState && window.getCleanAppState(), - ) + ); await fs.writeFile( `${filepathBase}-state.json`, JSON.stringify(uiState, null, 2), - ) + ); } async checkBrowserForConsoleErrors() { - const ignoredLogTypes = ['WARNING'] + const ignoredLogTypes = ['WARNING']; const ignoredErrorMessages = [ // Third-party Favicon 404s show up as errors 'favicon.ico - Failed to load resource: the server responded with a status of 404 (Not Found)', - ] - const browserLogs = await this.driver.manage().logs().get('browser') + ]; + const browserLogs = await this.driver.manage().logs().get('browser'); const errorEntries = browserLogs.filter( (entry) => !ignoredLogTypes.includes(entry.level.toString()), - ) - const errorObjects = errorEntries.map((entry) => entry.toJSON()) + ); + const errorObjects = errorEntries.map((entry) => entry.toJSON()); return errorObjects.filter( (entry) => !ignoredErrorMessages.some((message) => entry.message.includes(message), ), - ) + ); } } @@ -222,11 +222,11 @@ function collectMetrics() { const results = { paint: {}, navigation: [], - } + }; window.performance.getEntriesByType('paint').forEach((paintEntry) => { - results.paint[paintEntry.name] = paintEntry.startTime - }) + results.paint[paintEntry.name] = paintEntry.startTime; + }); window.performance .getEntriesByType('navigation') @@ -237,16 +237,16 @@ function collectMetrics() { domInteractive: navigationEntry.domInteractive, redirectCount: navigationEntry.redirectCount, type: navigationEntry.type, - }) - }) + }); + }); - return results + return results; } Driver.PAGES = { HOME: 'home', NOTIFICATION: 'notification', POPUP: 'popup', -} +}; -module.exports = Driver +module.exports = Driver; diff --git a/test/e2e/webdriver/firefox.js b/test/e2e/webdriver/firefox.js index 63c037b02..ed90dc256 100644 --- a/test/e2e/webdriver/firefox.js +++ b/test/e2e/webdriver/firefox.js @@ -1,16 +1,16 @@ -const fs = require('fs') -const os = require('os') -const path = require('path') -const { Builder, By, until } = require('selenium-webdriver') -const firefox = require('selenium-webdriver/firefox') -const { version } = require('../../../app/manifest/_base.json') +const fs = require('fs'); +const os = require('os'); +const path = require('path'); +const { Builder, By, until } = require('selenium-webdriver'); +const firefox = require('selenium-webdriver/firefox'); +const { version } = require('../../../app/manifest/_base.json'); /** * The prefix for temporary Firefox profiles. All Firefox profiles used for e2e tests * will be created as random directories inside this. * @type {string} */ -const TEMP_PROFILE_PATH_PREFIX = path.join(os.tmpdir(), 'MetaMask-Fx-Profile') +const TEMP_PROFILE_PATH_PREFIX = path.join(os.tmpdir(), 'MetaMask-Fx-Profile'); /** * A wrapper around a {@code WebDriver} instance exposing Firefox-specific functionality @@ -22,32 +22,32 @@ class FirefoxDriver { * @returns {Promise<{driver: !ThenableWebDriver, extensionUrl: string, extensionId: string}>} */ static async build({ responsive, port }) { - const templateProfile = fs.mkdtempSync(TEMP_PROFILE_PATH_PREFIX) - const options = new firefox.Options().setProfile(templateProfile) + const templateProfile = fs.mkdtempSync(TEMP_PROFILE_PATH_PREFIX); + const options = new firefox.Options().setProfile(templateProfile); const builder = new Builder() .forBrowser('firefox') - .setFirefoxOptions(options) + .setFirefoxOptions(options); if (port) { - const service = new firefox.ServiceBuilder().setPort(port) - builder.setFirefoxService(service) + const service = new firefox.ServiceBuilder().setPort(port); + builder.setFirefoxService(service); } - const driver = builder.build() - const fxDriver = new FirefoxDriver(driver) + const driver = builder.build(); + const fxDriver = new FirefoxDriver(driver); const extensionId = await fxDriver.installExtension( `builds/metamask-firefox-${version}.zip`, - ) - const internalExtensionId = await fxDriver.getInternalId() + ); + const internalExtensionId = await fxDriver.getInternalId(); if (responsive) { - await driver.manage().window().setRect({ width: 320, height: 600 }) + await driver.manage().window().setRect({ width: 320, height: 600 }); } return { driver, extensionId, extensionUrl: `moz-extension://${internalExtensionId}`, - } + }; } /** @@ -55,7 +55,7 @@ class FirefoxDriver { * @param {!ThenableWebDriver} driver - a {@code WebDriver} instance */ constructor(driver) { - this._driver = driver + this._driver = driver; } /** @@ -64,7 +64,7 @@ class FirefoxDriver { * @returns {Promise} the extension ID */ async installExtension(addonPath) { - return await this._driver.installAddon(addonPath, true) + return await this._driver.installAddon(addonPath, true); } /** @@ -72,7 +72,7 @@ class FirefoxDriver { * @returns {Promise} the Internal UUID for the given extension */ async getInternalId() { - await this._driver.get('about:debugging#addons') + await this._driver.get('about:debugging#addons'); return await this._driver .wait( until.elementLocated( @@ -80,8 +80,8 @@ class FirefoxDriver { ), 1000, ) - .getText() + .getText(); } } -module.exports = FirefoxDriver +module.exports = FirefoxDriver; diff --git a/test/e2e/webdriver/index.js b/test/e2e/webdriver/index.js index 8a41aac8a..b7647f96a 100644 --- a/test/e2e/webdriver/index.js +++ b/test/e2e/webdriver/index.js @@ -1,36 +1,36 @@ -const { Browser } = require('selenium-webdriver') -const fetchMockResponses = require('../../data/fetch-mocks.json') -const Driver = require('./driver') -const ChromeDriver = require('./chrome') -const FirefoxDriver = require('./firefox') +const { Browser } = require('selenium-webdriver'); +const fetchMockResponses = require('../../data/fetch-mocks.json'); +const Driver = require('./driver'); +const ChromeDriver = require('./chrome'); +const FirefoxDriver = require('./firefox'); async function buildWebDriver({ responsive, port } = {}) { - const browser = process.env.SELENIUM_BROWSER + const browser = process.env.SELENIUM_BROWSER; const { driver: seleniumDriver, extensionId, extensionUrl, - } = await buildBrowserWebDriver(browser, { responsive, port }) - await setupFetchMocking(seleniumDriver) - const driver = new Driver(seleniumDriver, browser, extensionUrl) + } = await buildBrowserWebDriver(browser, { responsive, port }); + await setupFetchMocking(seleniumDriver); + const driver = new Driver(seleniumDriver, browser, extensionUrl); return { driver, extensionId, - } + }; } async function buildBrowserWebDriver(browser, webDriverOptions) { switch (browser) { case Browser.CHROME: { - return await ChromeDriver.build(webDriverOptions) + return await ChromeDriver.build(webDriverOptions); } case Browser.FIREFOX: { - return await FirefoxDriver.build(webDriverOptions) + return await FirefoxDriver.build(webDriverOptions); } default: { - throw new Error(`Unrecognized browser: ${browser}`) + throw new Error(`Unrecognized browser: ${browser}`); } } } @@ -38,44 +38,44 @@ async function buildBrowserWebDriver(browser, webDriverOptions) { async function setupFetchMocking(driver) { // define fetchMocking script, to be evaluated in the browser function fetchMocking(mockResponses) { - window.origFetch = window.fetch.bind(window) + window.origFetch = window.fetch.bind(window); window.fetch = async (...args) => { - const url = args[0] + const url = args[0]; // api.metaswap.codefi.network/gasPrices if ( url.match(/^http(s)?:\/\/api\.metaswap\.codefi\.network\/gasPrices/u) ) { - return { json: async () => clone(mockResponses.gasPricesBasic) } + return { json: async () => clone(mockResponses.gasPricesBasic) }; } else if (url.match(/chromeextensionmm/u)) { - return { json: async () => clone(mockResponses.metametrics) } + return { json: async () => clone(mockResponses.metametrics) }; } else if (url.match(/^https:\/\/(api\.metaswap|.*airswap-dev)/u)) { if (url.match(/featureFlag$/u)) { - return { json: async () => clone(mockResponses.swaps.featureFlag) } + return { json: async () => clone(mockResponses.swaps.featureFlag) }; } } - return window.origFetch(...args) - } + return window.origFetch(...args); + }; if (window.chrome && window.chrome.webRequest) { window.chrome.webRequest.onBeforeRequest.addListener( cancelInfuraRequest, { urls: ['https://*.infura.io/*'] }, ['blocking'], - ) + ); } function cancelInfuraRequest(requestDetails) { - console.log(`fetchMocking - Canceling request: "${requestDetails.url}"`) - return { cancel: true } + console.log(`fetchMocking - Canceling request: "${requestDetails.url}"`); + return { cancel: true }; } function clone(obj) { - return JSON.parse(JSON.stringify(obj)) + return JSON.parse(JSON.stringify(obj)); } } // fetchMockResponses are parsed last minute to ensure that objects are uniquely instantiated - const fetchMockResponsesJson = JSON.stringify(fetchMockResponses) + const fetchMockResponsesJson = JSON.stringify(fetchMockResponses); // eval the fetchMocking script in the browser - await driver.executeScript(`(${fetchMocking})(${fetchMockResponsesJson})`) + await driver.executeScript(`(${fetchMocking})(${fetchMockResponsesJson})`); } module.exports = { buildWebDriver, -} +}; diff --git a/test/env.js b/test/env.js index 1fbdad3df..38e4a6fed 100644 --- a/test/env.js +++ b/test/env.js @@ -1 +1 @@ -process.env.METAMASK_ENV = 'test' +process.env.METAMASK_ENV = 'test'; diff --git a/test/helper.js b/test/helper.js index 38462c6ca..5731a905e 100644 --- a/test/helper.js +++ b/test/helper.js @@ -1,92 +1,92 @@ -import Ganache from 'ganache-core' -import nock from 'nock' -import Enzyme from 'enzyme' -import Adapter from 'enzyme-adapter-react-16' -import log from 'loglevel' -import { JSDOM } from 'jsdom' +import Ganache from 'ganache-core'; +import nock from 'nock'; +import Enzyme from 'enzyme'; +import Adapter from 'enzyme-adapter-react-16'; +import log from 'loglevel'; +import { JSDOM } from 'jsdom'; -nock.disableNetConnect() -nock.enableNetConnect('localhost') +nock.disableNetConnect(); +nock.enableNetConnect('localhost'); // catch rejections that are still unhandled when tests exit -const unhandledRejections = new Map() +const unhandledRejections = new Map(); process.on('unhandledRejection', (reason, promise) => { - console.log('Unhandled rejection:', reason) - unhandledRejections.set(promise, reason) -}) + console.log('Unhandled rejection:', reason); + unhandledRejections.set(promise, reason); +}); process.on('rejectionHandled', (promise) => { - console.log(`handled: ${unhandledRejections.get(promise)}`) - unhandledRejections.delete(promise) -}) + console.log(`handled: ${unhandledRejections.get(promise)}`); + unhandledRejections.delete(promise); +}); process.on('exit', () => { if (unhandledRejections.size > 0) { - console.error(`Found ${unhandledRejections.size} unhandled rejections:`) + console.error(`Found ${unhandledRejections.size} unhandled rejections:`); for (const reason of unhandledRejections.values()) { - console.error('Unhandled rejection: ', reason) + console.error('Unhandled rejection: ', reason); } - process.exit(1) + process.exit(1); } -}) +}); -Enzyme.configure({ adapter: new Adapter() }) +Enzyme.configure({ adapter: new Adapter() }); // ganache server -const server = Ganache.server() -server.listen(8545) +const server = Ganache.server(); +server.listen(8545); -server.on('error', console.error) -server.on('clientError', console.error) +server.on('error', console.error); +server.on('clientError', console.error); -log.setDefaultLevel(5) -global.log = log +log.setDefaultLevel(5); +global.log = log; // // polyfills // // dom -const jsdom = new JSDOM() -global.window = jsdom.window +const jsdom = new JSDOM(); +global.window = jsdom.window; // required by `trezor-connect/node_modules/whatwg-fetch` -global.self = window +global.self = window; // required by `dom-helpers` and various other libraries -global.document = window.document +global.document = window.document; // required by `react-tippy` -global.navigator = window.navigator -global.Element = window.Element +global.navigator = window.navigator; +global.Element = window.Element; // required by `react-popper` -global.HTMLElement = window.HTMLElement +global.HTMLElement = window.HTMLElement; // required by any components anchored on `popover-content` -const popoverContent = window.document.createElement('div') -popoverContent.setAttribute('id', 'popover-content') -window.document.body.appendChild(popoverContent) +const popoverContent = window.document.createElement('div'); +popoverContent.setAttribute('id', 'popover-content'); +window.document.body.appendChild(popoverContent); // delete AbortController added by jsdom so it can be polyfilled correctly below -delete window.AbortController +delete window.AbortController; // fetch -const fetch = require('node-fetch') +const fetch = require('node-fetch'); -const { Headers, Request, Response } = fetch -Object.assign(window, { fetch, Headers, Request, Response }) +const { Headers, Request, Response } = fetch; +Object.assign(window, { fetch, Headers, Request, Response }); -require('abortcontroller-polyfill/dist/polyfill-patch-fetch') +require('abortcontroller-polyfill/dist/polyfill-patch-fetch'); // localStorage window.localStorage = { removeItem: () => null, -} +}; // override @metamask/logo -window.requestAnimationFrame = () => undefined +window.requestAnimationFrame = () => undefined; // crypto.getRandomValues if (!window.crypto) { - window.crypto = {} + window.crypto = {}; } if (!window.crypto.getRandomValues) { // eslint-disable-next-line node/global-require - window.crypto.getRandomValues = require('polyfill-crypto.getrandomvalues') + window.crypto.getRandomValues = require('polyfill-crypto.getrandomvalues'); } diff --git a/test/lib/createTxMeta.js b/test/lib/createTxMeta.js index c4b680d8e..035f336a6 100644 --- a/test/lib/createTxMeta.js +++ b/test/lib/createTxMeta.js @@ -1,16 +1,16 @@ -import { snapshotFromTxMeta } from '../../app/scripts/controllers/transactions/lib/tx-state-history-helpers' -import { TRANSACTION_STATUSES } from '../../shared/constants/transaction' +import { snapshotFromTxMeta } from '../../app/scripts/controllers/transactions/lib/tx-state-history-helpers'; +import { TRANSACTION_STATUSES } from '../../shared/constants/transaction'; export default function createTxMeta(partialMeta) { const txMeta = { status: TRANSACTION_STATUSES.UNAPPROVED, txParams: {}, ...partialMeta, - } + }; // initialize history - txMeta.history = [] + txMeta.history = []; // capture initial snapshot of txMeta for history - const snapshot = snapshotFromTxMeta(txMeta) - txMeta.history.push(snapshot) - return txMeta + const snapshot = snapshotFromTxMeta(txMeta); + txMeta.history.push(snapshot); + return txMeta; } diff --git a/test/lib/mock-encryptor.js b/test/lib/mock-encryptor.js index 4b9f7faee..75a8488a8 100644 --- a/test/lib/mock-encryptor.js +++ b/test/lib/mock-encryptor.js @@ -1,36 +1,36 @@ -const mockHex = '0xabcdef0123456789' -const mockKey = Buffer.alloc(32) -let cacheVal +const mockHex = '0xabcdef0123456789'; +const mockKey = Buffer.alloc(32); +let cacheVal; const mockEncryptor = { encrypt(_, dataObj) { - cacheVal = dataObj - return Promise.resolve(mockHex) + cacheVal = dataObj; + return Promise.resolve(mockHex); }, decrypt() { - return Promise.resolve(cacheVal || {}) + return Promise.resolve(cacheVal || {}); }, encryptWithKey(key, dataObj) { - return this.encrypt(key, dataObj) + return this.encrypt(key, dataObj); }, decryptWithKey(key, text) { - return this.decrypt(key, text) + return this.decrypt(key, text); }, keyFromPassword() { - return Promise.resolve(mockKey) + return Promise.resolve(mockKey); }, generateSalt() { - return 'WHADDASALT!' + return 'WHADDASALT!'; }, getRandomValues() { - return 'SOO RANDO!!!1' + return 'SOO RANDO!!!1'; }, -} +}; -export default mockEncryptor +export default mockEncryptor; diff --git a/test/lib/render-helpers.js b/test/lib/render-helpers.js index b8d6be450..9d6bbe881 100644 --- a/test/lib/render-helpers.js +++ b/test/lib/render-helpers.js @@ -1,10 +1,10 @@ -import React from 'react' -import { Provider } from 'react-redux' -import { render } from '@testing-library/react' -import { mount } from 'enzyme' -import { MemoryRouter } from 'react-router-dom' -import PropTypes from 'prop-types' -import { LegacyI18nProvider } from '../../ui/app/contexts/i18n' +import React from 'react'; +import { Provider } from 'react-redux'; +import { render } from '@testing-library/react'; +import { mount } from 'enzyme'; +import { MemoryRouter } from 'react-router-dom'; +import PropTypes from 'prop-types'; +import { LegacyI18nProvider } from '../../ui/app/contexts/i18n'; export function mountWithRouter(component, store = {}, pathname = '/') { // Instantiate router context @@ -16,7 +16,7 @@ export function mountWithRouter(component, store = {}, pathname = '/') { }, match: {}, }, - } + }; const createContext = () => ({ context: { @@ -31,15 +31,15 @@ export function mountWithRouter(component, store = {}, pathname = '/') { metricsEvent: PropTypes.func, store: PropTypes.object, }, - }) + }); const Wrapper = () => ( {component} - ) + ); - return mount(, createContext()) + return mount(, createContext()); } export function renderWithProvider(component, store) { @@ -47,7 +47,7 @@ export function renderWithProvider(component, store) { {component} - ) + ); - return render() + return render(); } diff --git a/test/lib/wait-until-called.js b/test/lib/wait-until-called.js index 8252f6049..94a87f0f4 100644 --- a/test/lib/wait-until-called.js +++ b/test/lib/wait-until-called.js @@ -1,4 +1,4 @@ -const DEFAULT_TIMEOUT = 10000 +const DEFAULT_TIMEOUT = 10000; /** * A function that wraps a sinon stub and returns an asynchronous function @@ -25,42 +25,42 @@ function waitUntilCalled( wrappedThis = null, { callCount = 1, timeout = DEFAULT_TIMEOUT } = {}, ) { - let numCalls = 0 - let resolve - let timeoutHandle + let numCalls = 0; + let resolve; + let timeoutHandle; const stubHasBeenCalled = new Promise((_resolve) => { - resolve = _resolve + resolve = _resolve; if (timeout !== null) { timeoutHandle = setTimeout( () => resolve(new Error('Timeout exceeded')), timeout, - ) + ); } - }) + }); stub.callsFake((...args) => { try { if (stub.wrappedMethod) { - stub.wrappedMethod.call(wrappedThis, ...args) + stub.wrappedMethod.call(wrappedThis, ...args); } } finally { if (numCalls < callCount) { - numCalls += 1 + numCalls += 1; if (numCalls === callCount) { if (timeoutHandle) { - clearTimeout(timeoutHandle) + clearTimeout(timeoutHandle); } - resolve() + resolve(); } } } - }) + }); return async () => { - const error = await stubHasBeenCalled + const error = await stubHasBeenCalled; if (error) { - throw error + throw error; } - } + }; } -module.exports = waitUntilCalled +module.exports = waitUntilCalled; diff --git a/test/setup.js b/test/setup.js index abc8d6c30..a4795b61b 100644 --- a/test/setup.js +++ b/test/setup.js @@ -1,6 +1,6 @@ -require('@babel/register') +require('@babel/register'); -require('./helper') +require('./helper'); -window.SVGPathElement = window.SVGPathElement || { prototype: {} } -global.indexedDB = {} +window.SVGPathElement = window.SVGPathElement || { prototype: {} }; +global.indexedDB = {}; diff --git a/test/stub/provider.js b/test/stub/provider.js index f9bc72977..7f84e795f 100644 --- a/test/stub/provider.js +++ b/test/stub/provider.js @@ -1,10 +1,10 @@ -import { JsonRpcEngine } from 'json-rpc-engine' -import scaffoldMiddleware from 'eth-json-rpc-middleware/scaffold' -import providerAsMiddleware from 'eth-json-rpc-middleware/providerAsMiddleware' -import GanacheCore from 'ganache-core' +import { JsonRpcEngine } from 'json-rpc-engine'; +import scaffoldMiddleware from 'eth-json-rpc-middleware/scaffold'; +import providerAsMiddleware from 'eth-json-rpc-middleware/providerAsMiddleware'; +import GanacheCore from 'ganache-core'; export function getTestSeed() { - return 'people carpet cluster attract ankle motor ozone mass dove original primary mask' + return 'people carpet cluster attract ankle motor ozone mass dove original primary mask'; } export function getTestAccounts() { @@ -30,22 +30,22 @@ export function getTestAccounts() { 'hex', ), }, - ] + ]; } export function createEngineForTestData() { - return new JsonRpcEngine() + return new JsonRpcEngine(); } export function providerFromEngine(engine) { - const provider = { sendAsync: engine.handle.bind(engine) } - return provider + const provider = { sendAsync: engine.handle.bind(engine) }; + return provider; } export function createTestProviderTools(opts = {}) { - const engine = createEngineForTestData() + const engine = createEngineForTestData(); // handle provided hooks - engine.push(scaffoldMiddleware(opts.scaffold || {})) + engine.push(scaffoldMiddleware(opts.scaffold || {})); // handle block tracker methods engine.push( providerAsMiddleware( @@ -56,8 +56,8 @@ export function createTestProviderTools(opts = {}) { _chainIdRpc: opts.chainId, }), ), - ) + ); // wrap in standard provider interface - const provider = providerFromEngine(engine) - return { provider, engine } + const provider = providerFromEngine(engine); + return { provider, engine }; } diff --git a/test/unit-global/frozenPromise.js b/test/unit-global/frozenPromise.js index 427d7ffb9..de2409792 100644 --- a/test/unit-global/frozenPromise.js +++ b/test/unit-global/frozenPromise.js @@ -1,53 +1,53 @@ // Should occur before anything else -import './globalPatch' -import 'ses/lockdown' -import '../../app/scripts/runLockdown' -import assert from 'assert' /* eslint-disable-line import/first,import/order */ +import './globalPatch'; +import 'ses/lockdown'; +import '../../app/scripts/runLockdown'; +import assert from 'assert'; /* eslint-disable-line import/first,import/order */ describe('Promise global is immutable', function () { it('throws when reassinging promise (syntax 1)', function () { try { // eslint-disable-next-line no-global-assign,no-native-reassign - Promise = {} - assert.fail('did not throw error') + Promise = {}; + assert.fail('did not throw error'); } catch (err) { - assert.ok(err, 'did throw error') + assert.ok(err, 'did throw error'); } - }) + }); it('throws when reassinging promise (syntax 2)', function () { try { - global.Promise = {} - assert.fail('did not throw error') + global.Promise = {}; + assert.fail('did not throw error'); } catch (err) { - assert.ok(err, 'did throw error') + assert.ok(err, 'did throw error'); } - }) + }); it('throws when mutating existing Promise property', function () { try { - Promise.all = () => undefined - assert.fail('did not throw error') + Promise.all = () => undefined; + assert.fail('did not throw error'); } catch (err) { - assert.ok(err, 'did throw error') + assert.ok(err, 'did throw error'); } - }) + }); it('throws when adding new Promise property', function () { try { - Promise.foo = 'bar' - assert.fail('did not throw error') + Promise.foo = 'bar'; + assert.fail('did not throw error'); } catch (err) { - assert.ok(err, 'did throw error') + assert.ok(err, 'did throw error'); } - }) + }); it('throws when deleting Promise from global', function () { try { - delete global.Promise - assert.fail('did not throw error') + delete global.Promise; + assert.fail('did not throw error'); } catch (err) { - assert.ok(err, 'did throw error') + assert.ok(err, 'did throw error'); } - }) -}) + }); +}); diff --git a/test/unit-global/globalPatch.js b/test/unit-global/globalPatch.js index 89d392454..da239953c 100644 --- a/test/unit-global/globalPatch.js +++ b/test/unit-global/globalPatch.js @@ -1,2 +1,2 @@ // eslint-disable-next-line import/unambiguous,node/no-unsupported-features/es-builtins -global.globalThis = global +global.globalThis = global; diff --git a/test/unit/actions/config_test.js b/test/unit/actions/config_test.js index 35064ad9c..7b31cd84f 100644 --- a/test/unit/actions/config_test.js +++ b/test/unit/actions/config_test.js @@ -1,8 +1,8 @@ -import assert from 'assert' -import freeze from 'deep-freeze-strict' -import reducers from '../../../ui/app/ducks' -import * as actionConstants from '../../../ui/app/store/actionConstants' -import { NETWORK_TYPE_RPC } from '../../../shared/constants/network' +import assert from 'assert'; +import freeze from 'deep-freeze-strict'; +import reducers from '../../../ui/app/ducks'; +import * as actionConstants from '../../../ui/app/store/actionConstants'; +import { NETWORK_TYPE_RPC } from '../../../shared/constants/network'; describe('config view actions', function () { const initialState = { @@ -15,19 +15,19 @@ describe('config view actions', function () { name: 'accounts', }, }, - } - freeze(initialState) + }; + freeze(initialState); describe('SET_RPC_TARGET', function () { it('sets the state.metamask.rpcUrl property of the state to the action.value', function () { const action = { type: actionConstants.SET_RPC_TARGET, value: 'foo', - } + }; - const result = reducers(initialState, action) - assert.equal(result.metamask.provider.type, NETWORK_TYPE_RPC) - assert.equal(result.metamask.provider.rpcUrl, 'foo') - }) - }) -}) + const result = reducers(initialState, action); + assert.equal(result.metamask.provider.type, NETWORK_TYPE_RPC); + assert.equal(result.metamask.provider.rpcUrl, 'foo'); + }); + }); +}); diff --git a/test/unit/actions/set_account_label_test.js b/test/unit/actions/set_account_label_test.js index 7a79bd0b4..7bdb0d22c 100644 --- a/test/unit/actions/set_account_label_test.js +++ b/test/unit/actions/set_account_label_test.js @@ -1,7 +1,7 @@ -import assert from 'assert' -import freeze from 'deep-freeze-strict' -import reducers from '../../../ui/app/ducks' -import * as actionConstants from '../../../ui/app/store/actionConstants' +import assert from 'assert'; +import freeze from 'deep-freeze-strict'; +import reducers from '../../../ui/app/ducks'; +import * as actionConstants from '../../../ui/app/store/actionConstants'; describe('SET_ACCOUNT_LABEL', function () { it('updates the state.metamask.identities[:i].name property of the state to the action.value.label', function () { @@ -13,8 +13,8 @@ describe('SET_ACCOUNT_LABEL', function () { }, }, }, - } - freeze(initialState) + }; + freeze(initialState); const action = { type: actionConstants.SET_ACCOUNT_LABEL, @@ -22,13 +22,13 @@ describe('SET_ACCOUNT_LABEL', function () { account: 'foo', label: 'baz', }, - } - freeze(action) + }; + freeze(action); - const resultingState = reducers(initialState, action) + const resultingState = reducers(initialState, action); assert.equal( resultingState.metamask.identities.foo.name, action.value.label, - ) - }) -}) + ); + }); +}); diff --git a/test/unit/actions/set_selected_account_test.js b/test/unit/actions/set_selected_account_test.js index 03292c439..9f9a79036 100644 --- a/test/unit/actions/set_selected_account_test.js +++ b/test/unit/actions/set_selected_account_test.js @@ -1,7 +1,7 @@ -import assert from 'assert' -import freeze from 'deep-freeze-strict' -import reducers from '../../../ui/app/ducks' -import * as actionConstants from '../../../ui/app/store/actionConstants' +import assert from 'assert'; +import freeze from 'deep-freeze-strict'; +import reducers from '../../../ui/app/ducks'; +import * as actionConstants from '../../../ui/app/store/actionConstants'; describe('SHOW_ACCOUNT_DETAIL', function () { it('updates metamask state', function () { @@ -9,16 +9,16 @@ describe('SHOW_ACCOUNT_DETAIL', function () { metamask: { selectedAddress: 'foo', }, - } - freeze(initialState) + }; + freeze(initialState); const action = { type: actionConstants.SHOW_ACCOUNT_DETAIL, value: 'bar', - } - freeze(action) + }; + freeze(action); - const resultingState = reducers(initialState, action) - assert.equal(resultingState.metamask.selectedAddress, action.value) - }) -}) + const resultingState = reducers(initialState, action); + assert.equal(resultingState.metamask.selectedAddress, action.value); + }); +}); diff --git a/test/unit/actions/tx_test.js b/test/unit/actions/tx_test.js index 99b27689f..c1a969b75 100644 --- a/test/unit/actions/tx_test.js +++ b/test/unit/actions/tx_test.js @@ -1,14 +1,14 @@ -import assert from 'assert' -import configureMockStore from 'redux-mock-store' -import thunk from 'redux-thunk' -import * as actions from '../../../ui/app/store/actions' -import * as actionConstants from '../../../ui/app/store/actionConstants' +import assert from 'assert'; +import configureMockStore from 'redux-mock-store'; +import thunk from 'redux-thunk'; +import * as actions from '../../../ui/app/store/actions'; +import * as actionConstants from '../../../ui/app/store/actionConstants'; -const middlewares = [thunk] -const mockStore = configureMockStore(middlewares) +const middlewares = [thunk]; +const mockStore = configureMockStore(middlewares); describe('tx confirmation screen', function () { - const txId = 1457634084250832 + const txId = 1457634084250832; const initialState = { appState: {}, metamask: { @@ -20,31 +20,31 @@ describe('tx confirmation screen', function () { }, }, }, - } + }; - const store = mockStore(initialState) + const store = mockStore(initialState); describe('cancelTx', function () { it('creates COMPLETED_TX with the cancelled transaction ID', async function () { actions._setBackgroundConnection({ approveTransaction(_, cb) { - cb(new Error('An error!')) + cb(new Error('An error!')); }, cancelTransaction(_, cb) { - cb() + cb(); }, getState(cb) { - cb(null, {}) + cb(null, {}); }, - }) + }); - await store.dispatch(actions.cancelTx({ id: txId })) - const storeActions = store.getActions() + await store.dispatch(actions.cancelTx({ id: txId })); + const storeActions = store.getActions(); const completedTxAction = storeActions.find( ({ type }) => type === actionConstants.COMPLETED_TX, - ) - const { id } = completedTxAction.value - assert.equal(id, txId) - }) - }) -}) + ); + const { id } = completedTxAction.value; + assert.equal(id, txId); + }); + }); +}); diff --git a/test/unit/actions/warning_test.js b/test/unit/actions/warning_test.js index a59b40f92..2ec35525b 100644 --- a/test/unit/actions/warning_test.js +++ b/test/unit/actions/warning_test.js @@ -1,24 +1,24 @@ -import assert from 'assert' -import freeze from 'deep-freeze-strict' -import * as actions from '../../../ui/app/store/actions' -import reducers from '../../../ui/app/ducks' +import assert from 'assert'; +import freeze from 'deep-freeze-strict'; +import * as actions from '../../../ui/app/store/actions'; +import reducers from '../../../ui/app/ducks'; describe('action DISPLAY_WARNING', function () { it('sets appState.warning to provided value', function () { const initialState = { appState: {}, - } - freeze(initialState) + }; + freeze(initialState); - const warningText = 'This is a sample warning message' + const warningText = 'This is a sample warning message'; - const action = actions.displayWarning(warningText) - const resultingState = reducers(initialState, action) + const action = actions.displayWarning(warningText); + const resultingState = reducers(initialState, action); assert.equal( resultingState.appState.warning, warningText, 'warning text set', - ) - }) -}) + ); + }); +}); diff --git a/test/unit/app/ComposableObservableStore.js b/test/unit/app/ComposableObservableStore.js index 205e0a59b..816e0de59 100644 --- a/test/unit/app/ComposableObservableStore.js +++ b/test/unit/app/ComposableObservableStore.js @@ -1,35 +1,35 @@ -import assert from 'assert' -import { ObservableStore } from '@metamask/obs-store' -import ComposableObservableStore from '../../../app/scripts/lib/ComposableObservableStore' +import assert from 'assert'; +import { ObservableStore } from '@metamask/obs-store'; +import ComposableObservableStore from '../../../app/scripts/lib/ComposableObservableStore'; describe('ComposableObservableStore', function () { it('should register initial state', function () { - const store = new ComposableObservableStore('state') - assert.strictEqual(store.getState(), 'state') - }) + const store = new ComposableObservableStore('state'); + assert.strictEqual(store.getState(), 'state'); + }); it('should register initial structure', function () { - const testStore = new ObservableStore() - const store = new ComposableObservableStore(null, { TestStore: testStore }) - testStore.putState('state') - assert.deepEqual(store.getState(), { TestStore: 'state' }) - }) + const testStore = new ObservableStore(); + const store = new ComposableObservableStore(null, { TestStore: testStore }); + testStore.putState('state'); + assert.deepEqual(store.getState(), { TestStore: 'state' }); + }); it('should update structure', function () { - const testStore = new ObservableStore() - const store = new ComposableObservableStore() - store.updateStructure({ TestStore: testStore }) - testStore.putState('state') - assert.deepEqual(store.getState(), { TestStore: 'state' }) - }) + const testStore = new ObservableStore(); + const store = new ComposableObservableStore(); + store.updateStructure({ TestStore: testStore }); + testStore.putState('state'); + assert.deepEqual(store.getState(), { TestStore: 'state' }); + }); it('should return flattened state', function () { - const fooStore = new ObservableStore({ foo: 'foo' }) - const barStore = new ObservableStore({ bar: 'bar' }) + const fooStore = new ObservableStore({ foo: 'foo' }); + const barStore = new ObservableStore({ bar: 'bar' }); const store = new ComposableObservableStore(null, { FooStore: fooStore, BarStore: barStore, - }) - assert.deepEqual(store.getFlatState(), { foo: 'foo', bar: 'bar' }) - }) -}) + }); + assert.deepEqual(store.getFlatState(), { foo: 'foo', bar: 'bar' }); + }); +}); diff --git a/test/unit/app/account-import-strategies.spec.js b/test/unit/app/account-import-strategies.spec.js index 8918bd064..5dc706b90 100644 --- a/test/unit/app/account-import-strategies.spec.js +++ b/test/unit/app/account-import-strategies.spec.js @@ -1,72 +1,72 @@ -import assert from 'assert' -import ethUtil from 'ethereumjs-util' -import accountImporter from '../../../app/scripts/account-import-strategies' +import assert from 'assert'; +import ethUtil from 'ethereumjs-util'; +import accountImporter from '../../../app/scripts/account-import-strategies'; describe('Account Import Strategies', function () { const privkey = - '0x4cfd3e90fc78b0f86bf7524722150bb8da9c60cd532564d7ff43f5716514f553' + '0x4cfd3e90fc78b0f86bf7524722150bb8da9c60cd532564d7ff43f5716514f553'; const json = - '{"version":3,"id":"dbb54385-0a99-437f-83c0-647de9f244c3","address":"a7f92ce3fba24196cf6f4bd2e1eb3db282ba998c","Crypto":{"ciphertext":"bde13d9ade5c82df80281ca363320ce254a8a3a06535bbf6ffdeaf0726b1312c","cipherparams":{"iv":"fbf93718a57f26051b292f072f2e5b41"},"cipher":"aes-128-ctr","kdf":"scrypt","kdfparams":{"dklen":32,"salt":"7ffe00488319dec48e4c49a120ca49c6afbde9272854c64d9541c83fc6acdffe","n":8192,"r":8,"p":1},"mac":"2adfd9c4bc1cdac4c85bddfb31d9e21a684e0e050247a70c5698facf6b7d4681"}}' + '{"version":3,"id":"dbb54385-0a99-437f-83c0-647de9f244c3","address":"a7f92ce3fba24196cf6f4bd2e1eb3db282ba998c","Crypto":{"ciphertext":"bde13d9ade5c82df80281ca363320ce254a8a3a06535bbf6ffdeaf0726b1312c","cipherparams":{"iv":"fbf93718a57f26051b292f072f2e5b41"},"cipher":"aes-128-ctr","kdf":"scrypt","kdfparams":{"dklen":32,"salt":"7ffe00488319dec48e4c49a120ca49c6afbde9272854c64d9541c83fc6acdffe","n":8192,"r":8,"p":1},"mac":"2adfd9c4bc1cdac4c85bddfb31d9e21a684e0e050247a70c5698facf6b7d4681"}}'; describe('private key import', function () { it('imports a private key and strips 0x prefix', async function () { const importPrivKey = await accountImporter.importAccount('Private Key', [ privkey, - ]) - assert.equal(importPrivKey, ethUtil.stripHexPrefix(privkey)) - }) + ]); + assert.equal(importPrivKey, ethUtil.stripHexPrefix(privkey)); + }); it('throws an error for empty string private key', async function () { await assert.rejects( async () => { - await accountImporter.importAccount('Private Key', ['']) + await accountImporter.importAccount('Private Key', ['']); }, Error, 'no empty strings', - ) - }) + ); + }); it('throws an error for undefined string private key', async function () { await assert.rejects(async () => { - await accountImporter.importAccount('Private Key', [undefined]) - }) + await accountImporter.importAccount('Private Key', [undefined]); + }); await assert.rejects(async () => { - await accountImporter.importAccount('Private Key', []) - }) - }) + await accountImporter.importAccount('Private Key', []); + }); + }); it('throws an error for invalid private key', async function () { await assert.rejects(async () => { - await accountImporter.importAccount('Private Key', ['popcorn']) - }) - }) - }) + await accountImporter.importAccount('Private Key', ['popcorn']); + }); + }); + }); describe('JSON keystore import', function () { it('fails when password is incorrect for keystore', async function () { - const wrongPassword = 'password2' + const wrongPassword = 'password2'; try { - await accountImporter.importAccount('JSON File', [json, wrongPassword]) + await accountImporter.importAccount('JSON File', [json, wrongPassword]); } catch (error) { assert.equal( error.message, 'Key derivation failed - possibly wrong passphrase', - ) + ); } - }) + }); it('imports json string and password to return a private key', async function () { - const fileContentsPassword = 'password1' + const fileContentsPassword = 'password1'; const importJson = await accountImporter.importAccount('JSON File', [ json, fileContentsPassword, - ]) + ]); assert.equal( importJson, '0x5733876abe94146069ce8bcbabbde2677f2e35fa33e875e92041ed2ac87e5bc7', - ) - }) - }) -}) + ); + }); + }); +}); diff --git a/test/unit/app/buy-eth-url.spec.js b/test/unit/app/buy-eth-url.spec.js index 749d0a40f..d9730b4fb 100644 --- a/test/unit/app/buy-eth-url.spec.js +++ b/test/unit/app/buy-eth-url.spec.js @@ -1,43 +1,43 @@ -import assert from 'assert' -import getBuyEthUrl from '../../../app/scripts/lib/buy-eth-url' +import assert from 'assert'; +import getBuyEthUrl from '../../../app/scripts/lib/buy-eth-url'; describe('buy-eth-url', function () { const mainnet = { network: '1', amount: 5, address: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc', - } + }; const ropsten = { network: '3', - } + }; const rinkeby = { network: '4', - } + }; const kovan = { network: '42', - } + }; it('returns wyre url with address for network 1', function () { - const wyreUrl = getBuyEthUrl(mainnet) + const wyreUrl = getBuyEthUrl(mainnet); assert.equal( wyreUrl, 'https://pay.sendwyre.com/purchase?dest=ethereum:0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc&destCurrency=ETH&accountId=AC-7AG3W4XH4N2&paymentMethod=debit-card', - ) - }) + ); + }); it('returns metamask ropsten faucet for network 3', function () { - const ropstenUrl = getBuyEthUrl(ropsten) - assert.equal(ropstenUrl, 'https://faucet.metamask.io/') - }) + const ropstenUrl = getBuyEthUrl(ropsten); + assert.equal(ropstenUrl, 'https://faucet.metamask.io/'); + }); it('returns rinkeby dapp for network 4', function () { - const rinkebyUrl = getBuyEthUrl(rinkeby) - assert.equal(rinkebyUrl, 'https://www.rinkeby.io/') - }) + const rinkebyUrl = getBuyEthUrl(rinkeby); + assert.equal(rinkebyUrl, 'https://www.rinkeby.io/'); + }); it('returns kovan github test faucet for network 42', function () { - const kovanUrl = getBuyEthUrl(kovan) - assert.equal(kovanUrl, 'https://github.com/kovan-testnet/faucet') - }) -}) + const kovanUrl = getBuyEthUrl(kovan); + assert.equal(kovanUrl, 'https://github.com/kovan-testnet/faucet'); + }); +}); diff --git a/test/unit/app/cleanErrorStack.spec.js b/test/unit/app/cleanErrorStack.spec.js index 5aa63cb4c..e6bf8951f 100644 --- a/test/unit/app/cleanErrorStack.spec.js +++ b/test/unit/app/cleanErrorStack.spec.js @@ -1,34 +1,34 @@ -import assert from 'assert' -import cleanErrorStack from '../../../app/scripts/lib/cleanErrorStack' +import assert from 'assert'; +import cleanErrorStack from '../../../app/scripts/lib/cleanErrorStack'; describe('Clean Error Stack', function () { - const testMessage = 'Test Message' - const testError = new Error(testMessage) - const undefinedErrorName = new Error(testMessage) - const blankErrorName = new Error(testMessage) - const blankMsgError = new Error() + const testMessage = 'Test Message'; + const testError = new Error(testMessage); + const undefinedErrorName = new Error(testMessage); + const blankErrorName = new Error(testMessage); + const blankMsgError = new Error(); beforeEach(function () { - undefinedErrorName.name = undefined - blankErrorName.name = '' - }) + undefinedErrorName.name = undefined; + blankErrorName.name = ''; + }); it('tests error with message', function () { - assert.equal(cleanErrorStack(testError), 'Error: Test Message') - }) + assert.equal(cleanErrorStack(testError), 'Error: Test Message'); + }); it('tests error with undefined name', function () { assert.equal( cleanErrorStack(undefinedErrorName).toString(), 'Error: Test Message', - ) - }) + ); + }); it('tests error with blank name', function () { - assert.equal(cleanErrorStack(blankErrorName).toString(), 'Test Message') - }) + assert.equal(cleanErrorStack(blankErrorName).toString(), 'Test Message'); + }); it('tests error with blank message', function () { - assert.equal(cleanErrorStack(blankMsgError), 'Error') - }) -}) + assert.equal(cleanErrorStack(blankMsgError), 'Error'); + }); +}); diff --git a/test/unit/app/controllers/cached-balances-test.js b/test/unit/app/controllers/cached-balances-test.js index 8a7fb61ae..1267e083b 100644 --- a/test/unit/app/controllers/cached-balances-test.js +++ b/test/unit/app/controllers/cached-balances-test.js @@ -1,6 +1,6 @@ -import assert from 'assert' -import sinon from 'sinon' -import CachedBalancesController from '../../../../app/scripts/controllers/cached-balances' +import assert from 'assert'; +import sinon from 'sinon'; +import CachedBalancesController from '../../../../app/scripts/controllers/cached-balances'; describe('CachedBalancesController', function () { describe('updateCachedBalances', function () { @@ -15,25 +15,25 @@ describe('CachedBalancesController', function () { initState: { cachedBalances: 'mockCachedBalances', }, - }) + }); controller._generateBalancesToCache = sinon .stub() - .callsFake(() => Promise.resolve('mockNewCachedBalances')) + .callsFake(() => Promise.resolve('mockNewCachedBalances')); - await controller.updateCachedBalances({ accounts: 'mockAccounts' }) + await controller.updateCachedBalances({ accounts: 'mockAccounts' }); - assert.equal(controller._generateBalancesToCache.callCount, 1) + assert.equal(controller._generateBalancesToCache.callCount, 1); assert.deepEqual(controller._generateBalancesToCache.args[0], [ 'mockAccounts', 17, - ]) + ]); assert.equal( controller.store.getState().cachedBalances, 'mockNewCachedBalances', - ) - }) - }) + ); + }); + }); describe('_generateBalancesToCache', function () { it('should generate updated account balances where the current network was updated', function () { @@ -57,7 +57,7 @@ describe('CachedBalancesController', function () { }, }, }, - }) + }); const result = controller._generateBalancesToCache( { @@ -66,7 +66,7 @@ describe('CachedBalancesController', function () { c: { balance: '0x5' }, }, 17, - ) + ); assert.deepEqual(result, { 17: { @@ -79,8 +79,8 @@ describe('CachedBalancesController', function () { b: '0xb', c: '0xc', }, - }) - }) + }); + }); it('should generate updated account balances where the a new network was selected', function () { const controller = new CachedBalancesController({ @@ -98,7 +98,7 @@ describe('CachedBalancesController', function () { }, }, }, - }) + }); const result = controller._generateBalancesToCache( { @@ -107,7 +107,7 @@ describe('CachedBalancesController', function () { c: { balance: '0x5' }, }, 16, - ) + ); assert.deepEqual(result, { 17: { @@ -119,13 +119,13 @@ describe('CachedBalancesController', function () { a: '0x4', c: '0x5', }, - }) - }) - }) + }); + }); + }); describe('_registerUpdates', function () { it('should subscribe to the account tracker with the updateCachedBalances method', async function () { - const subscribeSpy = sinon.spy() + const subscribeSpy = sinon.spy(); const controller = new CachedBalancesController({ getNetwork: () => Promise.resolve(17), accountTracker: { @@ -133,18 +133,18 @@ describe('CachedBalancesController', function () { subscribe: subscribeSpy, }, }, - }) - subscribeSpy.resetHistory() + }); + subscribeSpy.resetHistory(); - const updateCachedBalancesSpy = sinon.spy() - controller.updateCachedBalances = updateCachedBalancesSpy - controller._registerUpdates({ accounts: 'mockAccounts' }) + const updateCachedBalancesSpy = sinon.spy(); + controller.updateCachedBalances = updateCachedBalancesSpy; + controller._registerUpdates({ accounts: 'mockAccounts' }); - assert.equal(subscribeSpy.callCount, 1) + assert.equal(subscribeSpy.callCount, 1); - subscribeSpy.args[0][0]() + subscribeSpy.args[0][0](); - assert.equal(updateCachedBalancesSpy.callCount, 1) - }) - }) -}) + assert.equal(updateCachedBalancesSpy.callCount, 1); + }); + }); +}); diff --git a/test/unit/app/controllers/detect-tokens-test.js b/test/unit/app/controllers/detect-tokens-test.js index d76906d26..458183d8b 100644 --- a/test/unit/app/controllers/detect-tokens-test.js +++ b/test/unit/app/controllers/detect-tokens-test.js @@ -1,112 +1,112 @@ -import assert from 'assert' -import sinon from 'sinon' -import { ObservableStore } from '@metamask/obs-store' -import contracts from '@metamask/contract-metadata' -import BigNumber from 'bignumber.js' +import assert from 'assert'; +import sinon from 'sinon'; +import { ObservableStore } from '@metamask/obs-store'; +import contracts from '@metamask/contract-metadata'; +import BigNumber from 'bignumber.js'; -import DetectTokensController from '../../../../app/scripts/controllers/detect-tokens' -import NetworkController from '../../../../app/scripts/controllers/network/network' -import PreferencesController from '../../../../app/scripts/controllers/preferences' -import { MAINNET, ROPSTEN } from '../../../../shared/constants/network' +import DetectTokensController from '../../../../app/scripts/controllers/detect-tokens'; +import NetworkController from '../../../../app/scripts/controllers/network/network'; +import PreferencesController from '../../../../app/scripts/controllers/preferences'; +import { MAINNET, ROPSTEN } from '../../../../shared/constants/network'; describe('DetectTokensController', function () { - const sandbox = sinon.createSandbox() - let keyringMemStore, network, preferences + const sandbox = sinon.createSandbox(); + let keyringMemStore, network, preferences; - const noop = () => undefined + const noop = () => undefined; const networkControllerProviderConfig = { getAccounts: noop, - } + }; beforeEach(async function () { - keyringMemStore = new ObservableStore({ isUnlocked: false }) - network = new NetworkController() - network.setInfuraProjectId('foo') - preferences = new PreferencesController({ network }) + keyringMemStore = new ObservableStore({ isUnlocked: false }); + network = new NetworkController(); + network.setInfuraProjectId('foo'); + preferences = new PreferencesController({ network }); preferences.setAddresses([ '0x7e57e2', '0xbc86727e770de68b1060c91f6bb6945c73e10388', - ]) - network.initializeProvider(networkControllerProviderConfig) - }) + ]); + network.initializeProvider(networkControllerProviderConfig); + }); after(function () { - sandbox.restore() - }) + sandbox.restore(); + }); it('should poll on correct interval', async function () { - const stub = sinon.stub(global, 'setInterval') - new DetectTokensController({ interval: 1337 }) // eslint-disable-line no-new - assert.strictEqual(stub.getCall(0).args[1], 1337) - stub.restore() - }) + const stub = sinon.stub(global, 'setInterval'); + new DetectTokensController({ interval: 1337 }); // eslint-disable-line no-new + assert.strictEqual(stub.getCall(0).args[1], 1337); + stub.restore(); + }); it('should be called on every polling period', async function () { - const clock = sandbox.useFakeTimers() - network.setProviderType(MAINNET) + const clock = sandbox.useFakeTimers(); + network.setProviderType(MAINNET); const controller = new DetectTokensController({ preferences, network, keyringMemStore, - }) - controller.isOpen = true - controller.isUnlocked = true + }); + controller.isOpen = true; + controller.isUnlocked = true; - const stub = sandbox.stub(controller, 'detectNewTokens') + const stub = sandbox.stub(controller, 'detectNewTokens'); - clock.tick(1) - sandbox.assert.notCalled(stub) - clock.tick(180000) - sandbox.assert.called(stub) - clock.tick(180000) - sandbox.assert.calledTwice(stub) - clock.tick(180000) - sandbox.assert.calledThrice(stub) - }) + clock.tick(1); + sandbox.assert.notCalled(stub); + clock.tick(180000); + sandbox.assert.called(stub); + clock.tick(180000); + sandbox.assert.calledTwice(stub); + clock.tick(180000); + sandbox.assert.calledThrice(stub); + }); it('should not check tokens while on test network', async function () { - sandbox.useFakeTimers() - network.setProviderType(ROPSTEN) + sandbox.useFakeTimers(); + network.setProviderType(ROPSTEN); const controller = new DetectTokensController({ preferences, network, keyringMemStore, - }) - controller.isOpen = true - controller.isUnlocked = true + }); + controller.isOpen = true; + controller.isUnlocked = true; - const stub = sandbox.stub(controller, '_getTokenBalances') + const stub = sandbox.stub(controller, '_getTokenBalances'); - await controller.detectNewTokens() - sandbox.assert.notCalled(stub) - }) + await controller.detectNewTokens(); + sandbox.assert.notCalled(stub); + }); it('should skip adding tokens listed in hiddenTokens array', async function () { - sandbox.useFakeTimers() - network.setProviderType(MAINNET) + sandbox.useFakeTimers(); + network.setProviderType(MAINNET); const controller = new DetectTokensController({ preferences, network, keyringMemStore, - }) - controller.isOpen = true - controller.isUnlocked = true + }); + controller.isOpen = true; + controller.isUnlocked = true; - const contractAddresses = Object.keys(contracts) + const contractAddresses = Object.keys(contracts); const erc20ContractAddresses = contractAddresses.filter( (contractAddress) => contracts[contractAddress].erc20 === true, - ) + ); - const existingTokenAddress = erc20ContractAddresses[0] - const existingToken = contracts[existingTokenAddress] + const existingTokenAddress = erc20ContractAddresses[0]; + const existingToken = contracts[existingTokenAddress]; await preferences.addToken( existingTokenAddress, existingToken.symbol, existingToken.decimals, - ) + ); - const tokenAddressToSkip = erc20ContractAddresses[1] + const tokenAddressToSkip = erc20ContractAddresses[1]; sandbox .stub(controller, '_getTokenBalances') @@ -114,11 +114,11 @@ describe('DetectTokensController', function () { tokensToDetect.map((token) => token === tokenAddressToSkip ? new BigNumber(10) : 0, ), - ) + ); - await preferences.removeToken(tokenAddressToSkip) + await preferences.removeToken(tokenAddressToSkip); - await controller.detectNewTokens() + await controller.detectNewTokens(); assert.deepEqual(preferences.store.getState().tokens, [ { @@ -126,51 +126,51 @@ describe('DetectTokensController', function () { decimals: existingToken.decimals, symbol: existingToken.symbol, }, - ]) - }) + ]); + }); it('should check and add tokens while on main network', async function () { - sandbox.useFakeTimers() - network.setProviderType(MAINNET) + sandbox.useFakeTimers(); + network.setProviderType(MAINNET); const controller = new DetectTokensController({ preferences, network, keyringMemStore, - }) - controller.isOpen = true - controller.isUnlocked = true + }); + controller.isOpen = true; + controller.isUnlocked = true; - const contractAddresses = Object.keys(contracts) + const contractAddresses = Object.keys(contracts); const erc20ContractAddresses = contractAddresses.filter( (contractAddress) => contracts[contractAddress].erc20 === true, - ) + ); - const existingTokenAddress = erc20ContractAddresses[0] - const existingToken = contracts[existingTokenAddress] + const existingTokenAddress = erc20ContractAddresses[0]; + const existingToken = contracts[existingTokenAddress]; await preferences.addToken( existingTokenAddress, existingToken.symbol, existingToken.decimals, - ) + ); - const tokenAddressToAdd = erc20ContractAddresses[1] - const tokenToAdd = contracts[tokenAddressToAdd] + const tokenAddressToAdd = erc20ContractAddresses[1]; + const tokenToAdd = contracts[tokenAddressToAdd]; const contractAddresssesToDetect = contractAddresses.filter( (address) => address !== existingTokenAddress, - ) + ); const indexOfTokenToAdd = contractAddresssesToDetect.indexOf( tokenAddressToAdd, - ) + ); - const balances = new Array(contractAddresssesToDetect.length) - balances[indexOfTokenToAdd] = new BigNumber(10) + const balances = new Array(contractAddresssesToDetect.length); + balances[indexOfTokenToAdd] = new BigNumber(10); sandbox .stub(controller, '_getTokenBalances') - .returns(Promise.resolve(balances)) + .returns(Promise.resolve(balances)); - await controller.detectNewTokens() + await controller.detectNewTokens(); assert.deepEqual(preferences.store.getState().tokens, [ { @@ -183,51 +183,51 @@ describe('DetectTokensController', function () { decimals: tokenToAdd.decimals, symbol: tokenToAdd.symbol, }, - ]) - }) + ]); + }); it('should check and add tokens while on non-default Mainnet', async function () { - sandbox.useFakeTimers() - network.setRpcTarget('https://some-fake-RPC-endpoint.metamask.io', '0x1') + sandbox.useFakeTimers(); + network.setRpcTarget('https://some-fake-RPC-endpoint.metamask.io', '0x1'); const controller = new DetectTokensController({ preferences, network, keyringMemStore, - }) - controller.isOpen = true - controller.isUnlocked = true + }); + controller.isOpen = true; + controller.isUnlocked = true; - const contractAddresses = Object.keys(contracts) + const contractAddresses = Object.keys(contracts); const erc20ContractAddresses = contractAddresses.filter( (contractAddress) => contracts[contractAddress].erc20 === true, - ) + ); - const existingTokenAddress = erc20ContractAddresses[0] - const existingToken = contracts[existingTokenAddress] + const existingTokenAddress = erc20ContractAddresses[0]; + const existingToken = contracts[existingTokenAddress]; await preferences.addToken( existingTokenAddress, existingToken.symbol, existingToken.decimals, - ) + ); - const tokenAddressToAdd = erc20ContractAddresses[1] - const tokenToAdd = contracts[tokenAddressToAdd] + const tokenAddressToAdd = erc20ContractAddresses[1]; + const tokenToAdd = contracts[tokenAddressToAdd]; const contractAddresssesToDetect = contractAddresses.filter( (address) => address !== existingTokenAddress, - ) + ); const indexOfTokenToAdd = contractAddresssesToDetect.indexOf( tokenAddressToAdd, - ) + ); - const balances = new Array(contractAddresssesToDetect.length) - balances[indexOfTokenToAdd] = new BigNumber(10) + const balances = new Array(contractAddresssesToDetect.length); + balances[indexOfTokenToAdd] = new BigNumber(10); sandbox .stub(controller, '_getTokenBalances') - .returns(Promise.resolve(balances)) + .returns(Promise.resolve(balances)); - await controller.detectNewTokens() + await controller.detectNewTokens(); assert.deepEqual(preferences.store.getState().tokens, [ { @@ -240,70 +240,70 @@ describe('DetectTokensController', function () { decimals: tokenToAdd.decimals, symbol: tokenToAdd.symbol, }, - ]) - }) + ]); + }); it('should trigger detect new tokens when change address', async function () { - sandbox.useFakeTimers() + sandbox.useFakeTimers(); const controller = new DetectTokensController({ preferences, network, keyringMemStore, - }) - controller.isOpen = true - controller.isUnlocked = true - const stub = sandbox.stub(controller, 'detectNewTokens') + }); + controller.isOpen = true; + controller.isUnlocked = true; + const stub = sandbox.stub(controller, 'detectNewTokens'); await preferences.setSelectedAddress( '0xbc86727e770de68b1060c91f6bb6945c73e10388', - ) - sandbox.assert.called(stub) - }) + ); + sandbox.assert.called(stub); + }); it('should trigger detect new tokens when submit password', async function () { - sandbox.useFakeTimers() + sandbox.useFakeTimers(); const controller = new DetectTokensController({ preferences, network, keyringMemStore, - }) - controller.isOpen = true - controller.selectedAddress = '0x0' - const stub = sandbox.stub(controller, 'detectNewTokens') - await controller._keyringMemStore.updateState({ isUnlocked: true }) - sandbox.assert.called(stub) - }) + }); + controller.isOpen = true; + controller.selectedAddress = '0x0'; + const stub = sandbox.stub(controller, 'detectNewTokens'); + await controller._keyringMemStore.updateState({ isUnlocked: true }); + sandbox.assert.called(stub); + }); it('should not trigger detect new tokens when not unlocked', async function () { - const clock = sandbox.useFakeTimers() - network.setProviderType(MAINNET) + const clock = sandbox.useFakeTimers(); + network.setProviderType(MAINNET); const controller = new DetectTokensController({ preferences, network, keyringMemStore, - }) - controller.isOpen = true - controller.isUnlocked = false - const stub = sandbox.stub(controller, '_getTokenBalances') - clock.tick(180000) - sandbox.assert.notCalled(stub) - }) + }); + controller.isOpen = true; + controller.isUnlocked = false; + const stub = sandbox.stub(controller, '_getTokenBalances'); + clock.tick(180000); + sandbox.assert.notCalled(stub); + }); it('should not trigger detect new tokens when not open', async function () { - const clock = sandbox.useFakeTimers() - network.setProviderType(MAINNET) + const clock = sandbox.useFakeTimers(); + network.setProviderType(MAINNET); const controller = new DetectTokensController({ preferences, network, keyringMemStore, - }) + }); // trigger state update from preferences controller await preferences.setSelectedAddress( '0xbc86727e770de68b1060c91f6bb6945c73e10388', - ) - controller.isOpen = false - controller.isUnlocked = true - const stub = sandbox.stub(controller, '_getTokenBalances') - clock.tick(180000) - sandbox.assert.notCalled(stub) - }) -}) + ); + controller.isOpen = false; + controller.isUnlocked = true; + const stub = sandbox.stub(controller, '_getTokenBalances'); + clock.tick(180000); + sandbox.assert.notCalled(stub); + }); +}); diff --git a/test/unit/app/controllers/ens-controller-test.js b/test/unit/app/controllers/ens-controller-test.js index dd116e69f..c210fa3f8 100644 --- a/test/unit/app/controllers/ens-controller-test.js +++ b/test/unit/app/controllers/ens-controller-test.js @@ -1,119 +1,119 @@ -import assert from 'assert' -import sinon from 'sinon' -import { ObservableStore } from '@metamask/obs-store' -import EnsController from '../../../../app/scripts/controllers/ens' +import assert from 'assert'; +import sinon from 'sinon'; +import { ObservableStore } from '@metamask/obs-store'; +import EnsController from '../../../../app/scripts/controllers/ens'; -const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000' -const ZERO_X_ERROR_ADDRESS = '0x' +const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'; +const ZERO_X_ERROR_ADDRESS = '0x'; describe('EnsController', function () { describe('#constructor', function () { it('should construct the controller given a provider and a network', async function () { - const currentNetworkId = '3' - const networkStore = new ObservableStore(currentNetworkId) + const currentNetworkId = '3'; + const networkStore = new ObservableStore(currentNetworkId); const ens = new EnsController({ provider: {}, networkStore, - }) + }); - assert.ok(ens._ens) - }) + assert.ok(ens._ens); + }); it('should construct the controller given an existing ENS instance', async function () { const networkStore = { subscribe: sinon.spy(), - } + }; const ens = new EnsController({ ens: {}, networkStore, - }) + }); - assert.ok(ens._ens) - }) - }) + assert.ok(ens._ens); + }); + }); describe('#reverseResolveName', function () { it('should resolve to an ENS name', async function () { - const address = '0x8e5d75d60224ea0c33d0041e75de68b1c3cb6dd5' + const address = '0x8e5d75d60224ea0c33d0041e75de68b1c3cb6dd5'; const networkStore = { subscribe: sinon.spy(), - } + }; const ens = new EnsController({ ens: { reverse: sinon.stub().withArgs(address).returns('peaksignal.eth'), lookup: sinon.stub().withArgs('peaksignal.eth').returns(address), }, networkStore, - }) + }); - const name = await ens.reverseResolveAddress(address) - assert.equal(name, 'peaksignal.eth') - }) + const name = await ens.reverseResolveAddress(address); + assert.equal(name, 'peaksignal.eth'); + }); it('should only resolve an ENS name once', async function () { - const address = '0x8e5d75d60224ea0c33d0041e75de68b1c3cb6dd5' - const reverse = sinon.stub().withArgs(address).returns('peaksignal.eth') - const lookup = sinon.stub().withArgs('peaksignal.eth').returns(address) + const address = '0x8e5d75d60224ea0c33d0041e75de68b1c3cb6dd5'; + const reverse = sinon.stub().withArgs(address).returns('peaksignal.eth'); + const lookup = sinon.stub().withArgs('peaksignal.eth').returns(address); const networkStore = { subscribe: sinon.spy(), - } + }; const ens = new EnsController({ ens: { reverse, lookup, }, networkStore, - }) + }); - assert.equal(await ens.reverseResolveAddress(address), 'peaksignal.eth') - assert.equal(await ens.reverseResolveAddress(address), 'peaksignal.eth') - assert.ok(lookup.calledOnce) - assert.ok(reverse.calledOnce) - }) + assert.equal(await ens.reverseResolveAddress(address), 'peaksignal.eth'); + assert.equal(await ens.reverseResolveAddress(address), 'peaksignal.eth'); + assert.ok(lookup.calledOnce); + assert.ok(reverse.calledOnce); + }); it('should fail if the name is registered to a different address than the reverse-resolved', async function () { - const address = '0x8e5d75d60224ea0c33d0041e75de68b1c3cb6dd5' + const address = '0x8e5d75d60224ea0c33d0041e75de68b1c3cb6dd5'; const networkStore = { subscribe: sinon.spy(), - } + }; const ens = new EnsController({ ens: { reverse: sinon.stub().withArgs(address).returns('peaksignal.eth'), lookup: sinon.stub().withArgs('peaksignal.eth').returns('0xfoo'), }, networkStore, - }) + }); - const name = await ens.reverseResolveAddress(address) - assert.strictEqual(name, undefined) - }) + const name = await ens.reverseResolveAddress(address); + assert.strictEqual(name, undefined); + }); it('should throw an error when the lookup resolves to the zero address', async function () { - const address = '0x8e5d75d60224ea0c33d0041e75de68b1c3cb6dd5' + const address = '0x8e5d75d60224ea0c33d0041e75de68b1c3cb6dd5'; const networkStore = { subscribe: sinon.spy(), - } + }; const ens = new EnsController({ ens: { reverse: sinon.stub().withArgs(address).returns('peaksignal.eth'), lookup: sinon.stub().withArgs('peaksignal.eth').returns(ZERO_ADDRESS), }, networkStore, - }) + }); try { - await ens.reverseResolveAddress(address) - assert.fail('#reverseResolveAddress did not throw') + await ens.reverseResolveAddress(address); + assert.fail('#reverseResolveAddress did not throw'); } catch (e) { - assert.ok(e) + assert.ok(e); } - }) + }); it('should throw an error the lookup resolves to the zero x address', async function () { - const address = '0x8e5d75d60224ea0c33d0041e75de68b1c3cb6dd5' + const address = '0x8e5d75d60224ea0c33d0041e75de68b1c3cb6dd5'; const networkStore = { subscribe: sinon.spy(), - } + }; const ens = new EnsController({ ens: { reverse: sinon.stub().withArgs(address).returns('peaksignal.eth'), @@ -123,14 +123,14 @@ describe('EnsController', function () { .returns(ZERO_X_ERROR_ADDRESS), }, networkStore, - }) + }); try { - await ens.reverseResolveAddress(address) - assert.fail('#reverseResolveAddress did not throw') + await ens.reverseResolveAddress(address); + assert.fail('#reverseResolveAddress did not throw'); } catch (e) { - assert.ok(e) + assert.ok(e); } - }) - }) -}) + }); + }); +}); diff --git a/test/unit/app/controllers/incoming-transactions-test.js b/test/unit/app/controllers/incoming-transactions-test.js index af8ac1084..86e629609 100644 --- a/test/unit/app/controllers/incoming-transactions-test.js +++ b/test/unit/app/controllers/incoming-transactions-test.js @@ -1,10 +1,10 @@ -import assert from 'assert' -import sinon from 'sinon' -import proxyquire from 'proxyquire' -import nock from 'nock' -import { cloneDeep } from 'lodash' +import assert from 'assert'; +import sinon from 'sinon'; +import proxyquire from 'proxyquire'; +import nock from 'nock'; +import { cloneDeep } from 'lodash'; -import waitUntilCalled from '../../../lib/wait-until-called' +import waitUntilCalled from '../../../lib/wait-until-called'; import { GOERLI, KOVAN, @@ -14,22 +14,22 @@ import { ROPSTEN, ROPSTEN_CHAIN_ID, ROPSTEN_NETWORK_ID, -} from '../../../../shared/constants/network' +} from '../../../../shared/constants/network'; import { TRANSACTION_CATEGORIES, TRANSACTION_STATUSES, -} from '../../../../shared/constants/transaction' +} from '../../../../shared/constants/transaction'; const IncomingTransactionsController = proxyquire( '../../../../app/scripts/controllers/incoming-transactions', { '../lib/random-id': { default: () => 54321 }, }, -).default +).default; -const FAKE_CHAIN_ID = '0x1338' -const MOCK_SELECTED_ADDRESS = '0x0101' -const SET_STATE_TIMEOUT = 10 +const FAKE_CHAIN_ID = '0x1338'; +const MOCK_SELECTED_ADDRESS = '0x0101'; +const SET_STATE_TIMEOUT = 10; function getEmptyInitState() { return { @@ -41,7 +41,7 @@ function getEmptyInitState() { [RINKEBY]: null, [ROPSTEN]: null, }, - } + }; } function getNonEmptyInitState() { @@ -56,14 +56,14 @@ function getNonEmptyInitState() { [RINKEBY]: 5, [ROPSTEN]: 4, }, - } + }; } function getMockNetworkController(chainId = FAKE_CHAIN_ID) { return { getCurrentChainId: () => chainId, on: sinon.spy(), - } + }; } function getMockPreferencesController({ @@ -79,7 +79,7 @@ function getMockPreferencesController({ }), subscribe: sinon.spy(), }, - } + }; } function getMockBlockTracker() { @@ -88,7 +88,7 @@ function getMockBlockTracker() { removeListener: sinon.spy(), testProperty: 'fakeBlockTracker', getCurrentBlock: () => '0xa', - } + }; } /** @@ -132,14 +132,14 @@ const getFakeEtherscanTransaction = ( timeStamp: '16000000000000', to: toAddress, value: '0', - } -} + }; +}; describe('IncomingTransactionsController', function () { afterEach(function () { - sinon.restore() - nock.cleanAll() - }) + sinon.restore(); + nock.cleanAll(); + }); describe('constructor', function () { it('should set up correct store, listeners and properties in the constructor', function () { @@ -150,34 +150,34 @@ describe('IncomingTransactionsController', function () { preferencesController: getMockPreferencesController(), initState: {}, }, - ) - sinon.spy(incomingTransactionsController, '_update') + ); + sinon.spy(incomingTransactionsController, '_update'); assert.deepEqual( incomingTransactionsController.store.getState(), getEmptyInitState(), - ) + ); - assert(incomingTransactionsController.networkController.on.calledOnce) + assert(incomingTransactionsController.networkController.on.calledOnce); assert.equal( incomingTransactionsController.networkController.on.getCall(0).args[0], 'networkDidChange', - ) + ); const networkControllerListenerCallback = incomingTransactionsController.networkController.on.getCall( 0, - ).args[1] - assert.equal(incomingTransactionsController._update.callCount, 0) - networkControllerListenerCallback('testNetworkType') - assert.equal(incomingTransactionsController._update.callCount, 1) + ).args[1]; + assert.equal(incomingTransactionsController._update.callCount, 0); + networkControllerListenerCallback('testNetworkType'); + assert.equal(incomingTransactionsController._update.callCount, 1); assert.deepEqual( incomingTransactionsController._update.getCall(0).args[0], { address: '0x0101', }, - ) + ); - incomingTransactionsController._update.resetHistory() - }) + incomingTransactionsController._update.resetHistory(); + }); it('should set the store to a provided initial state', function () { const incomingTransactionsController = new IncomingTransactionsController( @@ -187,14 +187,14 @@ describe('IncomingTransactionsController', function () { preferencesController: getMockPreferencesController(), initState: getNonEmptyInitState(), }, - ) + ); assert.deepEqual( incomingTransactionsController.store.getState(), getNonEmptyInitState(), - ) - }) - }) + ); + }); + }); describe('update events', function () { it('should set up a listener for the latest block', async function () { @@ -205,17 +205,19 @@ describe('IncomingTransactionsController', function () { preferencesController: getMockPreferencesController(), initState: {}, }, - ) + ); - incomingTransactionsController.start() + incomingTransactionsController.start(); - assert(incomingTransactionsController.blockTracker.addListener.calledOnce) + assert( + incomingTransactionsController.blockTracker.addListener.calledOnce, + ); assert.equal( incomingTransactionsController.blockTracker.addListener.getCall(0) .args[0], 'latest', - ) - }) + ); + }); it('should update upon latest block when started and on supported network', async function () { const incomingTransactionsController = new IncomingTransactionsController( @@ -225,9 +227,9 @@ describe('IncomingTransactionsController', function () { preferencesController: getMockPreferencesController(), initState: getNonEmptyInitState(), }, - ) + ); const startBlock = getNonEmptyInitState() - .incomingTxLastFetchedBlocksByNetwork[ROPSTEN] + .incomingTxLastFetchedBlocksByNetwork[ROPSTEN]; nock('https://api-ropsten.etherscan.io') .get( `/api?module=account&action=txlist&address=${MOCK_SELECTED_ADDRESS}&tag=latest&page=1&startBlock=${startBlock}`, @@ -238,29 +240,29 @@ describe('IncomingTransactionsController', function () { status: '1', result: [getFakeEtherscanTransaction()], }), - ) + ); const updateStateStub = sinon.stub( incomingTransactionsController.store, 'updateState', - ) + ); const updateStateCalled = waitUntilCalled( updateStateStub, incomingTransactionsController.store, - ) + ); - incomingTransactionsController.start() - await updateStateCalled() + incomingTransactionsController.start(); + await updateStateCalled(); - const actualState = incomingTransactionsController.store.getState() - const generatedTxId = actualState?.incomingTransactions?.['0xfake']?.id + const actualState = incomingTransactionsController.store.getState(); + const generatedTxId = actualState?.incomingTransactions?.['0xfake']?.id; - const actualStateWithoutGenerated = cloneDeep(actualState) - delete actualStateWithoutGenerated?.incomingTransactions?.['0xfake']?.id + const actualStateWithoutGenerated = cloneDeep(actualState); + delete actualStateWithoutGenerated?.incomingTransactions?.['0xfake']?.id; assert.ok( typeof generatedTxId === 'number' && generatedTxId > 0, 'Generated transaction ID should be a positive number', - ) + ); assert.deepStrictEqual( actualStateWithoutGenerated, { @@ -289,8 +291,8 @@ describe('IncomingTransactionsController', function () { }, }, 'State should have been updated after first block was received', - ) - }) + ); + }); it('should not update upon latest block when started and not on supported network', async function () { const incomingTransactionsController = new IncomingTransactionsController( @@ -300,7 +302,7 @@ describe('IncomingTransactionsController', function () { preferencesController: getMockPreferencesController(), initState: getNonEmptyInitState(), }, - ) + ); // reply with a valid request for any supported network, so that this test has every opportunity to fail for (const network of [ GOERLI, @@ -322,40 +324,40 @@ describe('IncomingTransactionsController', function () { status: '1', result: [getFakeEtherscanTransaction()], }), - ) + ); } const updateStateStub = sinon.stub( incomingTransactionsController.store, 'updateState', - ) + ); const updateStateCalled = waitUntilCalled( updateStateStub, incomingTransactionsController.store, - ) + ); const putStateStub = sinon.stub( incomingTransactionsController.store, 'putState', - ) + ); const putStateCalled = waitUntilCalled( putStateStub, incomingTransactionsController.store, - ) + ); - incomingTransactionsController.start() + incomingTransactionsController.start(); try { await Promise.race([ updateStateCalled(), putStateCalled(), new Promise((_, reject) => { - setTimeout(() => reject(new Error('TIMEOUT')), SET_STATE_TIMEOUT) + setTimeout(() => reject(new Error('TIMEOUT')), SET_STATE_TIMEOUT); }), - ]) - assert.fail('Update state should not have been called') + ]); + assert.fail('Update state should not have been called'); } catch (error) { - assert(error.message === 'TIMEOUT', 'TIMEOUT error should be thrown') + assert(error.message === 'TIMEOUT', 'TIMEOUT error should be thrown'); } - }) + }); it('should not update upon latest block when started and incoming transactions disabled', async function () { const incomingTransactionsController = new IncomingTransactionsController( @@ -367,7 +369,7 @@ describe('IncomingTransactionsController', function () { }), initState: getNonEmptyInitState(), }, - ) + ); // reply with a valid request for any supported network, so that this test has every opportunity to fail for (const network of [ GOERLI, @@ -389,40 +391,40 @@ describe('IncomingTransactionsController', function () { status: '1', result: [getFakeEtherscanTransaction()], }), - ) + ); } const updateStateStub = sinon.stub( incomingTransactionsController.store, 'updateState', - ) + ); const updateStateCalled = waitUntilCalled( updateStateStub, incomingTransactionsController.store, - ) + ); const putStateStub = sinon.stub( incomingTransactionsController.store, 'putState', - ) + ); const putStateCalled = waitUntilCalled( putStateStub, incomingTransactionsController.store, - ) + ); - incomingTransactionsController.start() + incomingTransactionsController.start(); try { await Promise.race([ updateStateCalled(), putStateCalled(), new Promise((_, reject) => { - setTimeout(() => reject(new Error('TIMEOUT')), SET_STATE_TIMEOUT) + setTimeout(() => reject(new Error('TIMEOUT')), SET_STATE_TIMEOUT); }), - ]) - assert.fail('Update state should not have been called') + ]); + assert.fail('Update state should not have been called'); } catch (error) { - assert(error.message === 'TIMEOUT', 'TIMEOUT error should be thrown') + assert(error.message === 'TIMEOUT', 'TIMEOUT error should be thrown'); } - }) + }); it('should not update upon latest block when not started', async function () { const incomingTransactionsController = new IncomingTransactionsController( @@ -432,7 +434,7 @@ describe('IncomingTransactionsController', function () { preferencesController: getMockPreferencesController(), initState: getNonEmptyInitState(), }, - ) + ); // reply with a valid request for any supported network, so that this test has every opportunity to fail for (const network of [ GOERLI, @@ -454,38 +456,38 @@ describe('IncomingTransactionsController', function () { status: '1', result: [getFakeEtherscanTransaction()], }), - ) + ); } const updateStateStub = sinon.stub( incomingTransactionsController.store, 'updateState', - ) + ); const updateStateCalled = waitUntilCalled( updateStateStub, incomingTransactionsController.store, - ) + ); const putStateStub = sinon.stub( incomingTransactionsController.store, 'putState', - ) + ); const putStateCalled = waitUntilCalled( putStateStub, incomingTransactionsController.store, - ) + ); try { await Promise.race([ updateStateCalled(), putStateCalled(), new Promise((_, reject) => { - setTimeout(() => reject(new Error('TIMEOUT')), SET_STATE_TIMEOUT) + setTimeout(() => reject(new Error('TIMEOUT')), SET_STATE_TIMEOUT); }), - ]) - assert.fail('Update state should not have been called') + ]); + assert.fail('Update state should not have been called'); } catch (error) { - assert(error.message === 'TIMEOUT', 'TIMEOUT error should be thrown') + assert(error.message === 'TIMEOUT', 'TIMEOUT error should be thrown'); } - }) + }); it('should not update upon latest block when stopped', async function () { const incomingTransactionsController = new IncomingTransactionsController( @@ -495,7 +497,7 @@ describe('IncomingTransactionsController', function () { preferencesController: getMockPreferencesController(), initState: getNonEmptyInitState(), }, - ) + ); // reply with a valid request for any supported network, so that this test has every opportunity to fail for (const network of [ GOERLI, @@ -517,40 +519,40 @@ describe('IncomingTransactionsController', function () { status: '1', result: [getFakeEtherscanTransaction()], }), - ) + ); } const updateStateStub = sinon.stub( incomingTransactionsController.store, 'updateState', - ) + ); const updateStateCalled = waitUntilCalled( updateStateStub, incomingTransactionsController.store, - ) + ); const putStateStub = sinon.stub( incomingTransactionsController.store, 'putState', - ) + ); const putStateCalled = waitUntilCalled( putStateStub, incomingTransactionsController.store, - ) + ); - incomingTransactionsController.stop() + incomingTransactionsController.stop(); try { await Promise.race([ updateStateCalled(), putStateCalled(), new Promise((_, reject) => { - setTimeout(() => reject(new Error('TIMEOUT')), SET_STATE_TIMEOUT) + setTimeout(() => reject(new Error('TIMEOUT')), SET_STATE_TIMEOUT); }), - ]) - assert.fail('Update state should not have been called') + ]); + assert.fail('Update state should not have been called'); } catch (error) { - assert(error.message === 'TIMEOUT', 'TIMEOUT error should be thrown') + assert(error.message === 'TIMEOUT', 'TIMEOUT error should be thrown'); } - }) + }); it('should update when the selected address changes and on supported network', async function () { const incomingTransactionsController = new IncomingTransactionsController( @@ -560,10 +562,10 @@ describe('IncomingTransactionsController', function () { preferencesController: getMockPreferencesController(), initState: getNonEmptyInitState(), }, - ) - const NEW_MOCK_SELECTED_ADDRESS = `${MOCK_SELECTED_ADDRESS}9` + ); + const NEW_MOCK_SELECTED_ADDRESS = `${MOCK_SELECTED_ADDRESS}9`; const startBlock = getNonEmptyInitState() - .incomingTxLastFetchedBlocksByNetwork[ROPSTEN] + .incomingTxLastFetchedBlocksByNetwork[ROPSTEN]; nock('https://api-ropsten.etherscan.io') .get( `/api?module=account&action=txlist&address=${NEW_MOCK_SELECTED_ADDRESS}&tag=latest&page=1&startBlock=${startBlock}`, @@ -574,36 +576,36 @@ describe('IncomingTransactionsController', function () { status: '1', result: [getFakeEtherscanTransaction(NEW_MOCK_SELECTED_ADDRESS)], }), - ) + ); const updateStateStub = sinon.stub( incomingTransactionsController.store, 'updateState', - ) + ); const updateStateCalled = waitUntilCalled( updateStateStub, incomingTransactionsController.store, - ) + ); const subscription = incomingTransactionsController.preferencesController.store.subscribe.getCall( 1, - ).args[0] + ).args[0]; // The incoming transactions controller will always skip the first event // We need to call subscription twice to test the event handling // TODO: stop skipping the first event - await subscription({ selectedAddress: MOCK_SELECTED_ADDRESS }) - await subscription({ selectedAddress: NEW_MOCK_SELECTED_ADDRESS }) - await updateStateCalled() + await subscription({ selectedAddress: MOCK_SELECTED_ADDRESS }); + await subscription({ selectedAddress: NEW_MOCK_SELECTED_ADDRESS }); + await updateStateCalled(); - const actualState = incomingTransactionsController.store.getState() - const generatedTxId = actualState?.incomingTransactions?.['0xfake']?.id + const actualState = incomingTransactionsController.store.getState(); + const generatedTxId = actualState?.incomingTransactions?.['0xfake']?.id; - const actualStateWithoutGenerated = cloneDeep(actualState) - delete actualStateWithoutGenerated?.incomingTransactions?.['0xfake']?.id + const actualStateWithoutGenerated = cloneDeep(actualState); + delete actualStateWithoutGenerated?.incomingTransactions?.['0xfake']?.id; assert.ok( typeof generatedTxId === 'number' && generatedTxId > 0, 'Generated transaction ID should be a positive number', - ) + ); assert.deepStrictEqual( actualStateWithoutGenerated, { @@ -632,8 +634,8 @@ describe('IncomingTransactionsController', function () { }, }, 'State should have been updated after first block was received', - ) - }) + ); + }); it('should not update when the selected address changes and not on supported network', async function () { const incomingTransactionsController = new IncomingTransactionsController( @@ -643,8 +645,8 @@ describe('IncomingTransactionsController', function () { preferencesController: getMockPreferencesController(), initState: getNonEmptyInitState(), }, - ) - const NEW_MOCK_SELECTED_ADDRESS = `${MOCK_SELECTED_ADDRESS}9` + ); + const NEW_MOCK_SELECTED_ADDRESS = `${MOCK_SELECTED_ADDRESS}9`; // reply with a valid request for any supported network, so that this test has every opportunity to fail for (const network of [ GOERLI, @@ -666,47 +668,47 @@ describe('IncomingTransactionsController', function () { status: '1', result: [getFakeEtherscanTransaction(NEW_MOCK_SELECTED_ADDRESS)], }), - ) + ); } const updateStateStub = sinon.stub( incomingTransactionsController.store, 'updateState', - ) + ); const updateStateCalled = waitUntilCalled( updateStateStub, incomingTransactionsController.store, - ) + ); const putStateStub = sinon.stub( incomingTransactionsController.store, 'putState', - ) + ); const putStateCalled = waitUntilCalled( putStateStub, incomingTransactionsController.store, - ) + ); const subscription = incomingTransactionsController.preferencesController.store.subscribe.getCall( 1, - ).args[0] + ).args[0]; // The incoming transactions controller will always skip the first event // We need to call subscription twice to test the event handling // TODO: stop skipping the first event - await subscription({ selectedAddress: MOCK_SELECTED_ADDRESS }) - await subscription({ selectedAddress: NEW_MOCK_SELECTED_ADDRESS }) + await subscription({ selectedAddress: MOCK_SELECTED_ADDRESS }); + await subscription({ selectedAddress: NEW_MOCK_SELECTED_ADDRESS }); try { await Promise.race([ updateStateCalled(), putStateCalled(), new Promise((_, reject) => { - setTimeout(() => reject(new Error('TIMEOUT')), SET_STATE_TIMEOUT) + setTimeout(() => reject(new Error('TIMEOUT')), SET_STATE_TIMEOUT); }), - ]) - assert.fail('Update state should not have been called') + ]); + assert.fail('Update state should not have been called'); } catch (error) { - assert(error.message === 'TIMEOUT', 'TIMEOUT error should be thrown') + assert(error.message === 'TIMEOUT', 'TIMEOUT error should be thrown'); } - }) + }); it('should update when switching to a supported network', async function () { const incomingTransactionsController = new IncomingTransactionsController( @@ -716,9 +718,9 @@ describe('IncomingTransactionsController', function () { preferencesController: getMockPreferencesController(), initState: getNonEmptyInitState(), }, - ) + ); const startBlock = getNonEmptyInitState() - .incomingTxLastFetchedBlocksByNetwork[ROPSTEN] + .incomingTxLastFetchedBlocksByNetwork[ROPSTEN]; nock('https://api-ropsten.etherscan.io') .get( `/api?module=account&action=txlist&address=${MOCK_SELECTED_ADDRESS}&tag=latest&page=1&startBlock=${startBlock}`, @@ -729,35 +731,35 @@ describe('IncomingTransactionsController', function () { status: '1', result: [getFakeEtherscanTransaction()], }), - ) + ); const updateStateStub = sinon.stub( incomingTransactionsController.store, 'updateState', - ) + ); const updateStateCalled = waitUntilCalled( updateStateStub, incomingTransactionsController.store, - ) + ); const subscription = incomingTransactionsController.networkController.on.getCall( 0, - ).args[1] + ).args[1]; incomingTransactionsController.networkController = getMockNetworkController( ROPSTEN_CHAIN_ID, - ) - await subscription(ROPSTEN) - await updateStateCalled() + ); + await subscription(ROPSTEN); + await updateStateCalled(); - const actualState = incomingTransactionsController.store.getState() - const generatedTxId = actualState?.incomingTransactions?.['0xfake']?.id + const actualState = incomingTransactionsController.store.getState(); + const generatedTxId = actualState?.incomingTransactions?.['0xfake']?.id; - const actualStateWithoutGenerated = cloneDeep(actualState) - delete actualStateWithoutGenerated?.incomingTransactions?.['0xfake']?.id + const actualStateWithoutGenerated = cloneDeep(actualState); + delete actualStateWithoutGenerated?.incomingTransactions?.['0xfake']?.id; assert.ok( typeof generatedTxId === 'number' && generatedTxId > 0, 'Generated transaction ID should be a positive number', - ) + ); assert.deepStrictEqual( actualStateWithoutGenerated, { @@ -786,11 +788,11 @@ describe('IncomingTransactionsController', function () { }, }, 'State should have been updated after first block was received', - ) - }) + ); + }); it('should not update when switching to an unsupported network', async function () { - const networkController = getMockNetworkController(ROPSTEN_CHAIN_ID) + const networkController = getMockNetworkController(ROPSTEN_CHAIN_ID); const incomingTransactionsController = new IncomingTransactionsController( { blockTracker: getMockBlockTracker(), @@ -798,7 +800,7 @@ describe('IncomingTransactionsController', function () { preferencesController: getMockPreferencesController(), initState: getNonEmptyInitState(), }, - ) + ); // reply with a valid request for any supported network, so that this test has every opportunity to fail for (const network of [ GOERLI, @@ -820,46 +822,46 @@ describe('IncomingTransactionsController', function () { status: '1', result: [getFakeEtherscanTransaction()], }), - ) + ); } const updateStateStub = sinon.stub( incomingTransactionsController.store, 'updateState', - ) + ); const updateStateCalled = waitUntilCalled( updateStateStub, incomingTransactionsController.store, - ) + ); const putStateStub = sinon.stub( incomingTransactionsController.store, 'putState', - ) + ); const putStateCalled = waitUntilCalled( putStateStub, incomingTransactionsController.store, - ) + ); const subscription = incomingTransactionsController.networkController.on.getCall( 0, - ).args[1] + ).args[1]; - networkController.getCurrentChainId = () => FAKE_CHAIN_ID - await subscription() + networkController.getCurrentChainId = () => FAKE_CHAIN_ID; + await subscription(); try { await Promise.race([ updateStateCalled(), putStateCalled(), new Promise((_, reject) => { - setTimeout(() => reject(new Error('TIMEOUT')), SET_STATE_TIMEOUT) + setTimeout(() => reject(new Error('TIMEOUT')), SET_STATE_TIMEOUT); }), - ]) - assert.fail('Update state should not have been called') + ]); + assert.fail('Update state should not have been called'); } catch (error) { - assert(error.message === 'TIMEOUT', 'TIMEOUT error should be thrown') + assert(error.message === 'TIMEOUT', 'TIMEOUT error should be thrown'); } - }) - }) + }); + }); describe('_getDataForUpdate', function () { it('should call fetchAll with the correct params when passed a new block number and the current network has no stored block', async function () { @@ -870,22 +872,22 @@ describe('IncomingTransactionsController', function () { preferencesController: getMockPreferencesController(), initState: getEmptyInitState(), }, - ) - incomingTransactionsController._fetchAll = sinon.stub().returns({}) + ); + incomingTransactionsController._fetchAll = sinon.stub().returns({}); await incomingTransactionsController._getDataForUpdate({ address: 'fakeAddress', chainId: ROPSTEN_CHAIN_ID, newBlockNumberDec: 999, - }) + }); - assert(incomingTransactionsController._fetchAll.calledOnce) + assert(incomingTransactionsController._fetchAll.calledOnce); assert.deepEqual( incomingTransactionsController._fetchAll.getCall(0).args, ['fakeAddress', 999, ROPSTEN_CHAIN_ID], - ) - }) + ); + }); it('should call fetchAll with the correct params when passed a new block number but the current network has a stored block', async function () { const incomingTransactionsController = new IncomingTransactionsController( @@ -895,22 +897,22 @@ describe('IncomingTransactionsController', function () { preferencesController: getMockPreferencesController(), initState: getNonEmptyInitState(), }, - ) - incomingTransactionsController._fetchAll = sinon.stub().returns({}) + ); + incomingTransactionsController._fetchAll = sinon.stub().returns({}); await incomingTransactionsController._getDataForUpdate({ address: 'fakeAddress', chainId: ROPSTEN_CHAIN_ID, newBlockNumberDec: 999, - }) + }); - assert(incomingTransactionsController._fetchAll.calledOnce) + assert(incomingTransactionsController._fetchAll.calledOnce); assert.deepEqual( incomingTransactionsController._fetchAll.getCall(0).args, ['fakeAddress', 4, ROPSTEN_CHAIN_ID], - ) - }) + ); + }); it('should return the expected data', async function () { const incomingTransactionsController = new IncomingTransactionsController( @@ -920,16 +922,16 @@ describe('IncomingTransactionsController', function () { preferencesController: getMockPreferencesController(), initState: getNonEmptyInitState(), }, - ) + ); incomingTransactionsController._fetchAll = sinon.stub().returns({ latestIncomingTxBlockNumber: 444, txs: [{ id: 555 }], - }) + }); const result = await incomingTransactionsController._getDataForUpdate({ address: 'fakeAddress', chainId: ROPSTEN_CHAIN_ID, - }) + }); assert.deepEqual(result, { latestIncomingTxBlockNumber: 444, @@ -946,9 +948,9 @@ describe('IncomingTransactionsController', function () { }, fetchedBlockNumber: 4, chainId: ROPSTEN_CHAIN_ID, - }) - }) - }) + }); + }); + }); describe('_updateStateWithNewTxData', function () { const MOCK_INPUT_WITHOUT_LASTEST = { @@ -965,12 +967,12 @@ describe('IncomingTransactionsController', function () { }, fetchedBlockNumber: 1111, chainId: ROPSTEN_CHAIN_ID, - } + }; const MOCK_INPUT_WITH_LASTEST = { ...MOCK_INPUT_WITHOUT_LASTEST, latestIncomingTxBlockNumber: 444, - } + }; it('should update state with correct blockhash and transactions when passed a truthy latestIncomingTxBlockNumber', async function () { const incomingTransactionsController = new IncomingTransactionsController( @@ -980,14 +982,14 @@ describe('IncomingTransactionsController', function () { preferencesController: getMockPreferencesController(), initState: getNonEmptyInitState(), }, - ) - sinon.spy(incomingTransactionsController.store, 'updateState') + ); + sinon.spy(incomingTransactionsController.store, 'updateState'); await incomingTransactionsController._updateStateWithNewTxData( MOCK_INPUT_WITH_LASTEST, - ) + ); - assert(incomingTransactionsController.store.updateState.calledOnce) + assert(incomingTransactionsController.store.updateState.calledOnce); assert.deepEqual( incomingTransactionsController.store.updateState.getCall(0).args[0], @@ -1001,8 +1003,8 @@ describe('IncomingTransactionsController', function () { '0xfff': { id: 555, hash: '0xfff' }, }, }, - ) - }) + ); + }); it('should update state with correct blockhash and transactions when passed a falsy latestIncomingTxBlockNumber', async function () { const incomingTransactionsController = new IncomingTransactionsController( @@ -1012,14 +1014,14 @@ describe('IncomingTransactionsController', function () { preferencesController: getMockPreferencesController(), initState: getNonEmptyInitState(), }, - ) - sinon.spy(incomingTransactionsController.store, 'updateState') + ); + sinon.spy(incomingTransactionsController.store, 'updateState'); await incomingTransactionsController._updateStateWithNewTxData( MOCK_INPUT_WITHOUT_LASTEST, - ) + ); - assert(incomingTransactionsController.store.updateState.calledOnce) + assert(incomingTransactionsController.store.updateState.calledOnce); assert.deepEqual( incomingTransactionsController.store.updateState.getCall(0).args[0], @@ -1033,26 +1035,26 @@ describe('IncomingTransactionsController', function () { '0xfff': { id: 555, hash: '0xfff' }, }, }, - ) - }) - }) + ); + }); + }); describe('_fetchTxs', function () { const mockFetch = sinon.stub().returns( Promise.resolve({ json: () => Promise.resolve({ someKey: 'someValue' }), }), - ) - let tempFetch + ); + let tempFetch; beforeEach(function () { - tempFetch = window.fetch - window.fetch = mockFetch - }) + tempFetch = window.fetch; + window.fetch = mockFetch; + }); afterEach(function () { - window.fetch = tempFetch - mockFetch.resetHistory() - }) + window.fetch = tempFetch; + mockFetch.resetHistory(); + }); it('should call fetch with the expected url when passed an address, block number and supported network', async function () { const incomingTransactionsController = new IncomingTransactionsController( @@ -1062,20 +1064,20 @@ describe('IncomingTransactionsController', function () { preferencesController: getMockPreferencesController(), initState: getNonEmptyInitState(), }, - ) + ); await incomingTransactionsController._fetchTxs( '0xfakeaddress', '789', ROPSTEN_CHAIN_ID, - ) + ); - assert(mockFetch.calledOnce) + assert(mockFetch.calledOnce); assert.equal( mockFetch.getCall(0).args[0], `https://api-${ROPSTEN}.etherscan.io/api?module=account&action=txlist&address=0xfakeaddress&tag=latest&page=1&startBlock=789`, - ) - }) + ); + }); it('should call fetch with the expected url when passed an address, block number and MAINNET', async function () { const incomingTransactionsController = new IncomingTransactionsController( @@ -1085,20 +1087,20 @@ describe('IncomingTransactionsController', function () { preferencesController: getMockPreferencesController(), initState: getNonEmptyInitState(), }, - ) + ); await incomingTransactionsController._fetchTxs( '0xfakeaddress', '789', MAINNET_CHAIN_ID, - ) + ); - assert(mockFetch.calledOnce) + assert(mockFetch.calledOnce); assert.equal( mockFetch.getCall(0).args[0], `https://api.etherscan.io/api?module=account&action=txlist&address=0xfakeaddress&tag=latest&page=1&startBlock=789`, - ) - }) + ); + }); it('should call fetch with the expected url when passed an address and supported network, but a falsy block number', async function () { const incomingTransactionsController = new IncomingTransactionsController( @@ -1108,20 +1110,20 @@ describe('IncomingTransactionsController', function () { preferencesController: getMockPreferencesController(), initState: getNonEmptyInitState(), }, - ) + ); await incomingTransactionsController._fetchTxs( '0xfakeaddress', null, ROPSTEN_CHAIN_ID, - ) + ); - assert(mockFetch.calledOnce) + assert(mockFetch.calledOnce); assert.equal( mockFetch.getCall(0).args[0], `https://api-${ROPSTEN}.etherscan.io/api?module=account&action=txlist&address=0xfakeaddress&tag=latest&page=1`, - ) - }) + ); + }); it('should return the results from the fetch call, plus the address and currentNetworkID, when passed an address, block number and supported network', async function () { const incomingTransactionsController = new IncomingTransactionsController( @@ -1131,22 +1133,22 @@ describe('IncomingTransactionsController', function () { preferencesController: getMockPreferencesController(), initState: getNonEmptyInitState(), }, - ) + ); const result = await incomingTransactionsController._fetchTxs( '0xfakeaddress', '789', ROPSTEN_CHAIN_ID, - ) + ); - assert(mockFetch.calledOnce) + assert(mockFetch.calledOnce); assert.deepEqual(result, { someKey: 'someValue', address: '0xfakeaddress', chainId: ROPSTEN_CHAIN_ID, - }) - }) - }) + }); + }); + }); describe('_processTxFetchResponse', function () { it('should return a null block number and empty tx array if status is 0', function () { @@ -1157,19 +1159,19 @@ describe('IncomingTransactionsController', function () { preferencesController: getMockPreferencesController(), initState: getNonEmptyInitState(), }, - ) + ); const result = incomingTransactionsController._processTxFetchResponse({ status: '0', result: [{ id: 1 }], address: '0xfakeaddress', - }) + }); assert.deepEqual(result, { latestIncomingTxBlockNumber: null, txs: [], - }) - }) + }); + }); it('should return a null block number and empty tx array if the passed result array is empty', function () { const incomingTransactionsController = new IncomingTransactionsController( @@ -1179,19 +1181,19 @@ describe('IncomingTransactionsController', function () { preferencesController: getMockPreferencesController(), initState: getNonEmptyInitState(), }, - ) + ); const result = incomingTransactionsController._processTxFetchResponse({ status: '1', result: [], address: '0xfakeaddress', - }) + }); assert.deepEqual(result, { latestIncomingTxBlockNumber: null, txs: [], - }) - }) + }); + }); it('should return the expected block number and tx list when passed data from a successful fetch', function () { const incomingTransactionsController = new IncomingTransactionsController( @@ -1201,13 +1203,13 @@ describe('IncomingTransactionsController', function () { preferencesController: getMockPreferencesController(), initState: getNonEmptyInitState(), }, - ) + ); incomingTransactionsController._normalizeTxFromEtherscan = (tx) => ({ ...tx, currentNetworkID: ROPSTEN_NETWORK_ID, normalized: true, - }) + }); const result = incomingTransactionsController._processTxFetchResponse({ status: '1', @@ -1263,7 +1265,7 @@ describe('IncomingTransactionsController', function () { time: 13, }, ], - }) + }); assert.deepEqual(result, { latestIncomingTxBlockNumber: 5001, @@ -1309,9 +1311,9 @@ describe('IncomingTransactionsController', function () { currentNetworkID: ROPSTEN_NETWORK_ID, }, ], - }) - }) - }) + }); + }); + }); describe('_normalizeTxFromEtherscan', function () { it('should return the expected data when the tx is in error', function () { @@ -1322,7 +1324,7 @@ describe('IncomingTransactionsController', function () { preferencesController: getMockPreferencesController(), initState: getNonEmptyInitState(), }, - ) + ); const result = incomingTransactionsController._normalizeTxFromEtherscan( { @@ -1338,7 +1340,7 @@ describe('IncomingTransactionsController', function () { hash: '0xg', }, ROPSTEN_CHAIN_ID, - ) + ); assert.deepEqual(result, { blockNumber: 333, @@ -1356,8 +1358,8 @@ describe('IncomingTransactionsController', function () { }, hash: '0xg', transactionCategory: TRANSACTION_CATEGORIES.INCOMING, - }) - }) + }); + }); it('should return the expected data when the tx is not in error', function () { const incomingTransactionsController = new IncomingTransactionsController( @@ -1367,7 +1369,7 @@ describe('IncomingTransactionsController', function () { preferencesController: getMockPreferencesController(), initState: getNonEmptyInitState(), }, - ) + ); const result = incomingTransactionsController._normalizeTxFromEtherscan( { @@ -1383,7 +1385,7 @@ describe('IncomingTransactionsController', function () { hash: '0xg', }, ROPSTEN_CHAIN_ID, - ) + ); assert.deepEqual(result, { blockNumber: 333, @@ -1401,7 +1403,7 @@ describe('IncomingTransactionsController', function () { }, hash: '0xg', transactionCategory: TRANSACTION_CATEGORIES.INCOMING, - }) - }) - }) -}) + }); + }); + }); +}); diff --git a/test/unit/app/controllers/metamask-controller-test.js b/test/unit/app/controllers/metamask-controller-test.js index 2e1c4021d..ab7d9d85f 100644 --- a/test/unit/app/controllers/metamask-controller-test.js +++ b/test/unit/app/controllers/metamask-controller-test.js @@ -1,33 +1,33 @@ -import assert from 'assert' -import sinon from 'sinon' -import { cloneDeep } from 'lodash' -import nock from 'nock' -import ethUtil from 'ethereumjs-util' -import { obj as createThoughStream } from 'through2' -import EthQuery from 'eth-query' -import proxyquire from 'proxyquire' -import firstTimeState from '../../localhostState' -import createTxMeta from '../../../lib/createTxMeta' -import { addHexPrefix } from '../../../../app/scripts/lib/util' -import { TRANSACTION_STATUSES } from '../../../../shared/constants/transaction' +import assert from 'assert'; +import sinon from 'sinon'; +import { cloneDeep } from 'lodash'; +import nock from 'nock'; +import ethUtil from 'ethereumjs-util'; +import { obj as createThoughStream } from 'through2'; +import EthQuery from 'eth-query'; +import proxyquire from 'proxyquire'; +import firstTimeState from '../../localhostState'; +import createTxMeta from '../../../lib/createTxMeta'; +import { addHexPrefix } from '../../../../app/scripts/lib/util'; +import { TRANSACTION_STATUSES } from '../../../../shared/constants/transaction'; const threeBoxSpies = { init: sinon.stub(), getThreeBoxSyncingState: sinon.stub().returns(true), turnThreeBoxSyncingOn: sinon.stub(), _registerUpdates: sinon.spy(), -} +}; class ThreeBoxControllerMock { constructor() { this.store = { subscribe: () => undefined, getState: () => ({}), - } - this.init = threeBoxSpies.init - this.getThreeBoxSyncingState = threeBoxSpies.getThreeBoxSyncingState - this.turnThreeBoxSyncingOn = threeBoxSpies.turnThreeBoxSyncingOn - this._registerUpdates = threeBoxSpies._registerUpdates + }; + this.init = threeBoxSpies.init; + this.getThreeBoxSyncingState = threeBoxSpies.getThreeBoxSyncingState; + this.turnThreeBoxSyncingOn = threeBoxSpies.turnThreeBoxSyncingOn; + this._registerUpdates = threeBoxSpies._registerUpdates; } } @@ -38,30 +38,30 @@ const ExtensionizerMock = { addListener: () => undefined, }, }, -} +}; -let loggerMiddlewareMock +let loggerMiddlewareMock; const initializeMockMiddlewareLog = () => { loggerMiddlewareMock = { requests: [], responses: [], - } -} + }; +}; const tearDownMockMiddlewareLog = () => { - loggerMiddlewareMock = undefined -} + loggerMiddlewareMock = undefined; +}; const createLoggerMiddlewareMock = () => (req, res, next) => { if (loggerMiddlewareMock) { - loggerMiddlewareMock.requests.push(req) + loggerMiddlewareMock.requests.push(req); next((cb) => { - loggerMiddlewareMock.responses.push(res) - cb() - }) - return + loggerMiddlewareMock.responses.push(res); + cb(); + }); + return; } - next() -} + next(); +}; const MetaMaskController = proxyquire( '../../../../app/scripts/metamask-controller', @@ -69,42 +69,42 @@ const MetaMaskController = proxyquire( './controllers/threebox': { default: ThreeBoxControllerMock }, './lib/createLoggerMiddleware': { default: createLoggerMiddlewareMock }, }, -).default +).default; -const currentNetworkId = '42' -const DEFAULT_LABEL = 'Account 1' -const DEFAULT_LABEL_2 = 'Account 2' +const currentNetworkId = '42'; +const DEFAULT_LABEL = 'Account 1'; +const DEFAULT_LABEL_2 = 'Account 2'; const TEST_SEED = - 'debris dizzy just program just float decrease vacant alarm reduce speak stadium' -const TEST_ADDRESS = '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc' -const TEST_ADDRESS_2 = '0xec1adf982415d2ef5ec55899b9bfb8bc0f29251b' -const TEST_ADDRESS_3 = '0xeb9e64b93097bc15f01f13eae97015c57ab64823' + 'debris dizzy just program just float decrease vacant alarm reduce speak stadium'; +const TEST_ADDRESS = '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc'; +const TEST_ADDRESS_2 = '0xec1adf982415d2ef5ec55899b9bfb8bc0f29251b'; +const TEST_ADDRESS_3 = '0xeb9e64b93097bc15f01f13eae97015c57ab64823'; const TEST_SEED_ALT = - 'setup olympic issue mobile velvet surge alcohol burger horse view reopen gentle' -const TEST_ADDRESS_ALT = '0xc42edfcc21ed14dda456aa0756c153f7985d8813' -const CUSTOM_RPC_URL = 'http://localhost:8545' -const CUSTOM_RPC_CHAIN_ID = '0x539' + 'setup olympic issue mobile velvet surge alcohol burger horse view reopen gentle'; +const TEST_ADDRESS_ALT = '0xc42edfcc21ed14dda456aa0756c153f7985d8813'; +const CUSTOM_RPC_URL = 'http://localhost:8545'; +const CUSTOM_RPC_CHAIN_ID = '0x539'; describe('MetaMaskController', function () { - let metamaskController - const sandbox = sinon.createSandbox() - const noop = () => undefined + let metamaskController; + const sandbox = sinon.createSandbox(); + const noop = () => undefined; beforeEach(function () { nock('https://min-api.cryptocompare.com') .persist() .get(/.*/u) - .reply(200, '{"JPY":12415.9}') + .reply(200, '{"JPY":12415.9}'); metamaskController = new MetaMaskController({ showUserConfirmation: noop, encryptor: { encrypt(_, object) { - this.object = object - return Promise.resolve('mock-encrypted') + this.object = object; + return Promise.resolve('mock-encrypted'); }, decrypt() { - return Promise.resolve(this.object) + return Promise.resolve(this.object); }, }, initState: cloneDeep(firstTimeState), @@ -115,314 +115,326 @@ describe('MetaMaskController', function () { }, extension: ExtensionizerMock, infuraProjectId: 'foo', - }) + }); // add sinon method spies sandbox.spy( metamaskController.keyringController, 'createNewVaultAndKeychain', - ) + ); sandbox.spy( metamaskController.keyringController, 'createNewVaultAndRestore', - ) - }) + ); + }); afterEach(function () { - nock.cleanAll() - sandbox.restore() - }) + nock.cleanAll(); + sandbox.restore(); + }); describe('#getAccounts', function () { it('returns first address when dapp calls web3.eth.getAccounts', async function () { - const password = 'a-fake-password' - await metamaskController.createNewVaultAndRestore(password, TEST_SEED) + const password = 'a-fake-password'; + await metamaskController.createNewVaultAndRestore(password, TEST_SEED); metamaskController.networkController._baseProviderParams.getAccounts( (err, res) => { - assert.ifError(err) - assert.equal(res.length, 1) - assert.equal(res[0], '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc') + assert.ifError(err); + assert.equal(res.length, 1); + assert.equal(res[0], '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc'); }, - ) - }) - }) + ); + }); + }); describe('#importAccountWithStrategy', function () { const importPrivkey = - '4cfd3e90fc78b0f86bf7524722150bb8da9c60cd532564d7ff43f5716514f553' + '4cfd3e90fc78b0f86bf7524722150bb8da9c60cd532564d7ff43f5716514f553'; beforeEach(async function () { - const password = 'a-fake-password' - await metamaskController.createNewVaultAndRestore(password, TEST_SEED) + const password = 'a-fake-password'; + await metamaskController.createNewVaultAndRestore(password, TEST_SEED); await metamaskController.importAccountWithStrategy('Private Key', [ importPrivkey, - ]) - }) + ]); + }); it('adds private key to keyrings in KeyringController', async function () { const simpleKeyrings = metamaskController.keyringController.getKeyringsByType( 'Simple Key Pair', - ) - const privKeyBuffer = simpleKeyrings[0].wallets[0]._privKey - const pubKeyBuffer = simpleKeyrings[0].wallets[0]._pubKey - const addressBuffer = ethUtil.pubToAddress(pubKeyBuffer) - const privKey = ethUtil.bufferToHex(privKeyBuffer) - const pubKey = ethUtil.bufferToHex(addressBuffer) - assert.equal(privKey, addHexPrefix(importPrivkey)) - assert.equal(pubKey, '0xe18035bf8712672935fdb4e5e431b1a0183d2dfc') - }) + ); + const privKeyBuffer = simpleKeyrings[0].wallets[0]._privKey; + const pubKeyBuffer = simpleKeyrings[0].wallets[0]._pubKey; + const addressBuffer = ethUtil.pubToAddress(pubKeyBuffer); + const privKey = ethUtil.bufferToHex(privKeyBuffer); + const pubKey = ethUtil.bufferToHex(addressBuffer); + assert.equal(privKey, addHexPrefix(importPrivkey)); + assert.equal(pubKey, '0xe18035bf8712672935fdb4e5e431b1a0183d2dfc'); + }); it('adds 1 account', async function () { - const keyringAccounts = await metamaskController.keyringController.getAccounts() + const keyringAccounts = await metamaskController.keyringController.getAccounts(); assert.equal( keyringAccounts[keyringAccounts.length - 1], '0xe18035bf8712672935fdb4e5e431b1a0183d2dfc', - ) - }) - }) + ); + }); + }); describe('submitPassword', function () { - const password = 'password' + const password = 'password'; beforeEach(async function () { - await metamaskController.createNewVaultAndKeychain(password) - threeBoxSpies.init.reset() - threeBoxSpies.turnThreeBoxSyncingOn.reset() - }) + await metamaskController.createNewVaultAndKeychain(password); + threeBoxSpies.init.reset(); + threeBoxSpies.turnThreeBoxSyncingOn.reset(); + }); it('removes any identities that do not correspond to known accounts.', async function () { - const fakeAddress = '0xbad0' - metamaskController.preferencesController.addAddresses([fakeAddress]) - await metamaskController.submitPassword(password) + const fakeAddress = '0xbad0'; + metamaskController.preferencesController.addAddresses([fakeAddress]); + await metamaskController.submitPassword(password); const identities = Object.keys( metamaskController.preferencesController.store.getState().identities, - ) - const addresses = await metamaskController.keyringController.getAccounts() + ); + const addresses = await metamaskController.keyringController.getAccounts(); identities.forEach((identity) => { assert.ok( addresses.includes(identity), `addresses should include all IDs: ${identity}`, - ) - }) + ); + }); addresses.forEach((address) => { assert.ok( identities.includes(address), `identities should include all Addresses: ${address}`, - ) - }) - }) + ); + }); + }); it('gets the address from threebox and creates a new 3box instance', async function () { - await metamaskController.submitPassword(password) - assert(threeBoxSpies.init.calledOnce) - assert(threeBoxSpies.turnThreeBoxSyncingOn.calledOnce) - }) + await metamaskController.submitPassword(password); + assert(threeBoxSpies.init.calledOnce); + assert(threeBoxSpies.turnThreeBoxSyncingOn.calledOnce); + }); it('succeeds even if blockTracker or threeBoxController throw', async function () { - const throwErr = sinon.fake.throws('foo') - metamaskController.blockTracker.checkForLatestBlock = throwErr - metamaskController.threeBoxController.getThreeBoxSyncingState = throwErr - await metamaskController.submitPassword(password) + const throwErr = sinon.fake.throws('foo'); + metamaskController.blockTracker.checkForLatestBlock = throwErr; + metamaskController.threeBoxController.getThreeBoxSyncingState = throwErr; + await metamaskController.submitPassword(password); assert.ok( throwErr.calledTwice, 'should have called checkForLatestBlock and getThreeBoxSyncingState', - ) - }) - }) + ); + }); + }); describe('#createNewVaultAndKeychain', function () { it('can only create new vault on keyringController once', async function () { - const selectStub = sandbox.stub(metamaskController, 'selectFirstIdentity') + const selectStub = sandbox.stub( + metamaskController, + 'selectFirstIdentity', + ); - const password = 'a-fake-password' + const password = 'a-fake-password'; - await metamaskController.createNewVaultAndKeychain(password) - await metamaskController.createNewVaultAndKeychain(password) + await metamaskController.createNewVaultAndKeychain(password); + await metamaskController.createNewVaultAndKeychain(password); assert( metamaskController.keyringController.createNewVaultAndKeychain .calledOnce, - ) + ); - selectStub.reset() - }) - }) + selectStub.reset(); + }); + }); describe('#createNewVaultAndRestore', function () { it('should be able to call newVaultAndRestore despite a mistake.', async function () { - const password = 'what-what-what' - sandbox.stub(metamaskController, 'getBalance') + const password = 'what-what-what'; + sandbox.stub(metamaskController, 'getBalance'); metamaskController.getBalance.callsFake(() => { - return Promise.resolve('0x0') - }) + return Promise.resolve('0x0'); + }); await metamaskController .createNewVaultAndRestore(password, TEST_SEED.slice(0, -1)) - .catch(() => null) - await metamaskController.createNewVaultAndRestore(password, TEST_SEED) + .catch(() => null); + await metamaskController.createNewVaultAndRestore(password, TEST_SEED); assert( metamaskController.keyringController.createNewVaultAndRestore .calledTwice, - ) - }) + ); + }); it('should clear previous identities after vault restoration', async function () { - sandbox.stub(metamaskController, 'getBalance') + sandbox.stub(metamaskController, 'getBalance'); metamaskController.getBalance.callsFake(() => { - return Promise.resolve('0x0') - }) + return Promise.resolve('0x0'); + }); - let startTime = Date.now() - await metamaskController.createNewVaultAndRestore('foobar1337', TEST_SEED) - let endTime = Date.now() + let startTime = Date.now(); + await metamaskController.createNewVaultAndRestore( + 'foobar1337', + TEST_SEED, + ); + let endTime = Date.now(); const firstVaultIdentities = cloneDeep( metamaskController.getState().identities, - ) + ); assert.ok( firstVaultIdentities[TEST_ADDRESS].lastSelected >= startTime && firstVaultIdentities[TEST_ADDRESS].lastSelected <= endTime, `'${firstVaultIdentities[TEST_ADDRESS].lastSelected}' expected to be between '${startTime}' and '${endTime}'`, - ) - delete firstVaultIdentities[TEST_ADDRESS].lastSelected + ); + delete firstVaultIdentities[TEST_ADDRESS].lastSelected; assert.deepEqual(firstVaultIdentities, { [TEST_ADDRESS]: { address: TEST_ADDRESS, name: DEFAULT_LABEL }, - }) + }); await metamaskController.preferencesController.setAccountLabel( TEST_ADDRESS, 'Account Foo', - ) + ); const labelledFirstVaultIdentities = cloneDeep( metamaskController.getState().identities, - ) - delete labelledFirstVaultIdentities[TEST_ADDRESS].lastSelected + ); + delete labelledFirstVaultIdentities[TEST_ADDRESS].lastSelected; assert.deepEqual(labelledFirstVaultIdentities, { [TEST_ADDRESS]: { address: TEST_ADDRESS, name: 'Account Foo' }, - }) + }); - startTime = Date.now() + startTime = Date.now(); await metamaskController.createNewVaultAndRestore( 'foobar1337', TEST_SEED_ALT, - ) - endTime = Date.now() + ); + endTime = Date.now(); const secondVaultIdentities = cloneDeep( metamaskController.getState().identities, - ) + ); assert.ok( secondVaultIdentities[TEST_ADDRESS_ALT].lastSelected >= startTime && secondVaultIdentities[TEST_ADDRESS_ALT].lastSelected <= endTime, `'${secondVaultIdentities[TEST_ADDRESS_ALT].lastSelected}' expected to be between '${startTime}' and '${endTime}'`, - ) - delete secondVaultIdentities[TEST_ADDRESS_ALT].lastSelected + ); + delete secondVaultIdentities[TEST_ADDRESS_ALT].lastSelected; assert.deepEqual(secondVaultIdentities, { [TEST_ADDRESS_ALT]: { address: TEST_ADDRESS_ALT, name: DEFAULT_LABEL }, - }) - }) + }); + }); it('should restore any consecutive accounts with balances', async function () { - sandbox.stub(metamaskController, 'getBalance') + sandbox.stub(metamaskController, 'getBalance'); metamaskController.getBalance.withArgs(TEST_ADDRESS).callsFake(() => { - return Promise.resolve('0x14ced5122ce0a000') - }) + return Promise.resolve('0x14ced5122ce0a000'); + }); metamaskController.getBalance.withArgs(TEST_ADDRESS_2).callsFake(() => { - return Promise.resolve('0x0') - }) + return Promise.resolve('0x0'); + }); metamaskController.getBalance.withArgs(TEST_ADDRESS_3).callsFake(() => { - return Promise.resolve('0x14ced5122ce0a000') - }) + return Promise.resolve('0x14ced5122ce0a000'); + }); - const startTime = Date.now() - await metamaskController.createNewVaultAndRestore('foobar1337', TEST_SEED) + const startTime = Date.now(); + await metamaskController.createNewVaultAndRestore( + 'foobar1337', + TEST_SEED, + ); - const identities = cloneDeep(metamaskController.getState().identities) + const identities = cloneDeep(metamaskController.getState().identities); assert.ok( identities[TEST_ADDRESS].lastSelected >= startTime && identities[TEST_ADDRESS].lastSelected <= Date.now(), - ) - delete identities[TEST_ADDRESS].lastSelected + ); + delete identities[TEST_ADDRESS].lastSelected; assert.deepEqual(identities, { [TEST_ADDRESS]: { address: TEST_ADDRESS, name: DEFAULT_LABEL }, [TEST_ADDRESS_2]: { address: TEST_ADDRESS_2, name: DEFAULT_LABEL_2 }, - }) - }) - }) + }); + }); + }); describe('#getBalance', function () { it('should return the balance known by accountTracker', async function () { - const accounts = {} - const balance = '0x14ced5122ce0a000' - accounts[TEST_ADDRESS] = { balance } + const accounts = {}; + const balance = '0x14ced5122ce0a000'; + accounts[TEST_ADDRESS] = { balance }; - metamaskController.accountTracker.store.putState({ accounts }) + metamaskController.accountTracker.store.putState({ accounts }); - const gotten = await metamaskController.getBalance(TEST_ADDRESS) + const gotten = await metamaskController.getBalance(TEST_ADDRESS); - assert.equal(balance, gotten) - }) + assert.equal(balance, gotten); + }); it('should ask the network for a balance when not known by accountTracker', async function () { - const accounts = {} - const balance = '0x14ced5122ce0a000' - const ethQuery = new EthQuery() + const accounts = {}; + const balance = '0x14ced5122ce0a000'; + const ethQuery = new EthQuery(); sinon.stub(ethQuery, 'getBalance').callsFake((_, callback) => { - callback(undefined, balance) - }) + callback(undefined, balance); + }); - metamaskController.accountTracker.store.putState({ accounts }) + metamaskController.accountTracker.store.putState({ accounts }); - const gotten = await metamaskController.getBalance(TEST_ADDRESS, ethQuery) + const gotten = await metamaskController.getBalance( + TEST_ADDRESS, + ethQuery, + ); - assert.equal(balance, gotten) - }) - }) + assert.equal(balance, gotten); + }); + }); describe('#getApi', function () { it('getState', function (done) { - let state - const getApi = metamaskController.getApi() + let state; + const getApi = metamaskController.getApi(); getApi.getState((err, res) => { if (err) { - done(err) + done(err); } else { - state = res + state = res; } - }) - assert.deepEqual(state, metamaskController.getState()) - done() - }) - }) + }); + assert.deepEqual(state, metamaskController.getState()); + done(); + }); + }); describe('preferencesController', function () { it('defaults useBlockie to false', function () { assert.equal( metamaskController.preferencesController.store.getState().useBlockie, false, - ) - }) + ); + }); it('setUseBlockie to true', function () { - metamaskController.setUseBlockie(true, noop) + metamaskController.setUseBlockie(true, noop); assert.equal( metamaskController.preferencesController.store.getState().useBlockie, true, - ) - }) - }) + ); + }); + }); describe('#selectFirstIdentity', function () { - let identities, address + let identities, address; beforeEach(function () { - address = '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc' + address = '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc'; identities = { '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc': { address, @@ -432,21 +444,23 @@ describe('MetaMaskController', function () { address: '0xc42edfcc21ed14dda456aa0756c153f7985d8813', name: 'Account 2', }, - } - metamaskController.preferencesController.store.updateState({ identities }) - metamaskController.selectFirstIdentity() - }) + }; + metamaskController.preferencesController.store.updateState({ + identities, + }); + metamaskController.selectFirstIdentity(); + }); it('changes preferences controller select address', function () { - const preferenceControllerState = metamaskController.preferencesController.store.getState() - assert.equal(preferenceControllerState.selectedAddress, address) - }) + const preferenceControllerState = metamaskController.preferencesController.store.getState(); + assert.equal(preferenceControllerState.selectedAddress, address); + }); it('changes metamask controller selected address', function () { - const metamaskState = metamaskController.getState() - assert.equal(metamaskState.selectedAddress, address) - }) - }) + const metamaskState = metamaskController.getState(); + assert.equal(metamaskState.selectedAddress, address); + }); + }); describe('connectHardware', function () { it('should throw if it receives an unknown device name', async function () { @@ -455,41 +469,41 @@ describe('MetaMaskController', function () { 'Some random device name', 0, `m/44/0'/0'`, - ) + ); } catch (e) { assert.equal( e, 'Error: MetamaskController:getKeyringForDevice - Unknown device', - ) + ); } - }) + }); it('should add the Trezor Hardware keyring', async function () { - sinon.spy(metamaskController.keyringController, 'addNewKeyring') - await metamaskController.connectHardware('trezor', 0).catch(() => null) + sinon.spy(metamaskController.keyringController, 'addNewKeyring'); + await metamaskController.connectHardware('trezor', 0).catch(() => null); const keyrings = await metamaskController.keyringController.getKeyringsByType( 'Trezor Hardware', - ) + ); assert.equal( metamaskController.keyringController.addNewKeyring.getCall(0).args, 'Trezor Hardware', - ) - assert.equal(keyrings.length, 1) - }) + ); + assert.equal(keyrings.length, 1); + }); it('should add the Ledger Hardware keyring', async function () { - sinon.spy(metamaskController.keyringController, 'addNewKeyring') - await metamaskController.connectHardware('ledger', 0).catch(() => null) + sinon.spy(metamaskController.keyringController, 'addNewKeyring'); + await metamaskController.connectHardware('ledger', 0).catch(() => null); const keyrings = await metamaskController.keyringController.getKeyringsByType( 'Ledger Hardware', - ) + ); assert.equal( metamaskController.keyringController.addNewKeyring.getCall(0).args, 'Ledger Hardware', - ) - assert.equal(keyrings.length, 1) - }) - }) + ); + assert.equal(keyrings.length, 1); + }); + }); describe('checkHardwareStatus', function () { it('should throw if it receives an unknown device name', async function () { @@ -497,214 +511,217 @@ describe('MetaMaskController', function () { await metamaskController.checkHardwareStatus( 'Some random device name', `m/44/0'/0'`, - ) + ); } catch (e) { assert.equal( e, 'Error: MetamaskController:getKeyringForDevice - Unknown device', - ) + ); } - }) + }); it('should be locked by default', async function () { - await metamaskController.connectHardware('trezor', 0).catch(() => null) - const status = await metamaskController.checkHardwareStatus('trezor') - assert.equal(status, false) - }) - }) + await metamaskController.connectHardware('trezor', 0).catch(() => null); + const status = await metamaskController.checkHardwareStatus('trezor'); + assert.equal(status, false); + }); + }); describe('forgetDevice', function () { it('should throw if it receives an unknown device name', async function () { try { - await metamaskController.forgetDevice('Some random device name') + await metamaskController.forgetDevice('Some random device name'); } catch (e) { assert.equal( e, 'Error: MetamaskController:getKeyringForDevice - Unknown device', - ) + ); } - }) + }); it('should wipe all the keyring info', async function () { - await metamaskController.connectHardware('trezor', 0).catch(() => null) - await metamaskController.forgetDevice('trezor') + await metamaskController.connectHardware('trezor', 0).catch(() => null); + await metamaskController.forgetDevice('trezor'); const keyrings = await metamaskController.keyringController.getKeyringsByType( 'Trezor Hardware', - ) + ); - assert.deepEqual(keyrings[0].accounts, []) - assert.deepEqual(keyrings[0].page, 0) - assert.deepEqual(keyrings[0].isUnlocked(), false) - }) - }) + assert.deepEqual(keyrings[0].accounts, []); + assert.deepEqual(keyrings[0].page, 0); + assert.deepEqual(keyrings[0].isUnlocked(), false); + }); + }); describe('unlockHardwareWalletAccount', function () { - let accountToUnlock - let windowOpenStub - let addNewAccountStub - let getAccountsStub + let accountToUnlock; + let windowOpenStub; + let addNewAccountStub; + let getAccountsStub; beforeEach(async function () { - accountToUnlock = 10 - windowOpenStub = sinon.stub(window, 'open') - windowOpenStub.returns(noop) + accountToUnlock = 10; + windowOpenStub = sinon.stub(window, 'open'); + windowOpenStub.returns(noop); addNewAccountStub = sinon.stub( metamaskController.keyringController, 'addNewAccount', - ) - addNewAccountStub.returns({}) + ); + addNewAccountStub.returns({}); getAccountsStub = sinon.stub( metamaskController.keyringController, 'getAccounts', - ) + ); // Need to return different address to mock the behavior of // adding a new account from the keyring - getAccountsStub.onCall(0).returns(Promise.resolve(['0x1'])) - getAccountsStub.onCall(1).returns(Promise.resolve(['0x2'])) - getAccountsStub.onCall(2).returns(Promise.resolve(['0x3'])) - getAccountsStub.onCall(3).returns(Promise.resolve(['0x4'])) - sinon.spy(metamaskController.preferencesController, 'setAddresses') - sinon.spy(metamaskController.preferencesController, 'setSelectedAddress') - sinon.spy(metamaskController.preferencesController, 'setAccountLabel') + getAccountsStub.onCall(0).returns(Promise.resolve(['0x1'])); + getAccountsStub.onCall(1).returns(Promise.resolve(['0x2'])); + getAccountsStub.onCall(2).returns(Promise.resolve(['0x3'])); + getAccountsStub.onCall(3).returns(Promise.resolve(['0x4'])); + sinon.spy(metamaskController.preferencesController, 'setAddresses'); + sinon.spy(metamaskController.preferencesController, 'setSelectedAddress'); + sinon.spy(metamaskController.preferencesController, 'setAccountLabel'); await metamaskController .connectHardware('trezor', 0, `m/44/0'/0'`) - .catch(() => null) + .catch(() => null); await metamaskController.unlockHardwareWalletAccount( accountToUnlock, 'trezor', `m/44/0'/0'`, - ) - }) + ); + }); afterEach(function () { - window.open.restore() - metamaskController.keyringController.addNewAccount.restore() - metamaskController.keyringController.getAccounts.restore() - metamaskController.preferencesController.setAddresses.restore() - metamaskController.preferencesController.setSelectedAddress.restore() - metamaskController.preferencesController.setAccountLabel.restore() - }) + window.open.restore(); + metamaskController.keyringController.addNewAccount.restore(); + metamaskController.keyringController.getAccounts.restore(); + metamaskController.preferencesController.setAddresses.restore(); + metamaskController.preferencesController.setSelectedAddress.restore(); + metamaskController.preferencesController.setAccountLabel.restore(); + }); it('should set unlockedAccount in the keyring', async function () { const keyrings = await metamaskController.keyringController.getKeyringsByType( 'Trezor Hardware', - ) - assert.equal(keyrings[0].unlockedAccount, accountToUnlock) - }) + ); + assert.equal(keyrings[0].unlockedAccount, accountToUnlock); + }); it('should call keyringController.addNewAccount', async function () { - assert(metamaskController.keyringController.addNewAccount.calledOnce) - }) + assert(metamaskController.keyringController.addNewAccount.calledOnce); + }); it('should call keyringController.getAccounts ', async function () { - assert(metamaskController.keyringController.getAccounts.called) - }) + assert(metamaskController.keyringController.getAccounts.called); + }); it('should call preferencesController.setAddresses', async function () { - assert(metamaskController.preferencesController.setAddresses.calledOnce) - }) + assert(metamaskController.preferencesController.setAddresses.calledOnce); + }); it('should call preferencesController.setSelectedAddress', async function () { assert( metamaskController.preferencesController.setSelectedAddress.calledOnce, - ) - }) + ); + }); it('should call preferencesController.setAccountLabel', async function () { assert( metamaskController.preferencesController.setAccountLabel.calledOnce, - ) - }) - }) + ); + }); + }); describe('#setCustomRpc', function () { - let rpcUrl + let rpcUrl; beforeEach(function () { rpcUrl = metamaskController.setCustomRpc( CUSTOM_RPC_URL, CUSTOM_RPC_CHAIN_ID, - ) - }) + ); + }); it('returns custom RPC that when called', async function () { - assert.equal(await rpcUrl, CUSTOM_RPC_URL) - }) + assert.equal(await rpcUrl, CUSTOM_RPC_URL); + }); it('changes the network controller rpc', function () { - const networkControllerState = metamaskController.networkController.store.getState() - assert.equal(networkControllerState.provider.rpcUrl, CUSTOM_RPC_URL) - }) - }) + const networkControllerState = metamaskController.networkController.store.getState(); + assert.equal(networkControllerState.provider.rpcUrl, CUSTOM_RPC_URL); + }); + }); describe('#setCurrentCurrency', function () { - let defaultMetaMaskCurrency + let defaultMetaMaskCurrency; beforeEach(function () { defaultMetaMaskCurrency = - metamaskController.currencyRateController.state.currentCurrency - }) + metamaskController.currencyRateController.state.currentCurrency; + }); it('defaults to usd', function () { - assert.equal(defaultMetaMaskCurrency, 'usd') - }) + assert.equal(defaultMetaMaskCurrency, 'usd'); + }); it('sets currency to JPY', function () { - metamaskController.setCurrentCurrency('JPY', noop) + metamaskController.setCurrentCurrency('JPY', noop); assert.equal( metamaskController.currencyRateController.state.currentCurrency, 'JPY', - ) - }) - }) + ); + }); + }); describe('#addNewAccount', function () { it('errors when an primary keyring is does not exist', async function () { - const addNewAccount = metamaskController.addNewAccount() + const addNewAccount = metamaskController.addNewAccount(); try { - await addNewAccount - assert.fail('should throw') + await addNewAccount; + assert.fail('should throw'); } catch (e) { - assert.equal(e.message, 'MetamaskController - No HD Key Tree found') + assert.equal(e.message, 'MetamaskController - No HD Key Tree found'); } - }) - }) + }); + }); describe('#verifyseedPhrase', function () { it('errors when no keying is provided', async function () { try { - await metamaskController.verifySeedPhrase() + await metamaskController.verifySeedPhrase(); } catch (error) { - assert.equal(error.message, 'MetamaskController - No HD Key Tree found') + assert.equal( + error.message, + 'MetamaskController - No HD Key Tree found', + ); } - }) + }); beforeEach(async function () { - await metamaskController.createNewVaultAndKeychain('password') - }) + await metamaskController.createNewVaultAndKeychain('password'); + }); it('#addNewAccount', async function () { - await metamaskController.addNewAccount() - const getAccounts = await metamaskController.keyringController.getAccounts() - assert.equal(getAccounts.length, 2) - }) - }) + await metamaskController.addNewAccount(); + const getAccounts = await metamaskController.keyringController.getAccounts(); + assert.equal(getAccounts.length, 2); + }); + }); describe('#resetAccount', function () { it('wipes transactions from only the correct network id and with the selected address', async function () { const selectedAddressStub = sinon.stub( metamaskController.preferencesController, 'getSelectedAddress', - ) + ); const getNetworkstub = sinon.stub( metamaskController.txController.txStateManager, 'getNetwork', - ) + ); - selectedAddressStub.returns('0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc') - getNetworkstub.returns(42) + selectedAddressStub.returns('0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc'); + getNetworkstub.returns(42); metamaskController.txController.txStateManager._saveTxList([ createTxMeta({ @@ -730,296 +747,296 @@ describe('MetaMaskController', function () { metamaskNetworkId: currentNetworkId, txParams: { from: '0xB09d8505E1F4EF1CeA089D47094f5DD3464083d4' }, }), - ]) + ]); - await metamaskController.resetAccount() + await metamaskController.resetAccount(); assert.equal( metamaskController.txController.txStateManager.getTx(1), undefined, - ) - }) - }) + ); + }); + }); describe('#removeAccount', function () { - let ret - const addressToRemove = '0x1' + let ret; + const addressToRemove = '0x1'; beforeEach(async function () { - sinon.stub(metamaskController.preferencesController, 'removeAddress') - sinon.stub(metamaskController.accountTracker, 'removeAccount') - sinon.stub(metamaskController.keyringController, 'removeAccount') + sinon.stub(metamaskController.preferencesController, 'removeAddress'); + sinon.stub(metamaskController.accountTracker, 'removeAccount'); + sinon.stub(metamaskController.keyringController, 'removeAccount'); sinon.stub( metamaskController.permissionsController, 'removeAllAccountPermissions', - ) + ); - ret = await metamaskController.removeAccount(addressToRemove) - }) + ret = await metamaskController.removeAccount(addressToRemove); + }); afterEach(function () { - metamaskController.keyringController.removeAccount.restore() - metamaskController.accountTracker.removeAccount.restore() - metamaskController.preferencesController.removeAddress.restore() - metamaskController.permissionsController.removeAllAccountPermissions.restore() - }) + metamaskController.keyringController.removeAccount.restore(); + metamaskController.accountTracker.removeAccount.restore(); + metamaskController.preferencesController.removeAddress.restore(); + metamaskController.permissionsController.removeAllAccountPermissions.restore(); + }); it('should call preferencesController.removeAddress', async function () { assert( metamaskController.preferencesController.removeAddress.calledWith( addressToRemove, ), - ) - }) + ); + }); it('should call accountTracker.removeAccount', async function () { assert( metamaskController.accountTracker.removeAccount.calledWith([ addressToRemove, ]), - ) - }) + ); + }); it('should call keyringController.removeAccount', async function () { assert( metamaskController.keyringController.removeAccount.calledWith( addressToRemove, ), - ) - }) + ); + }); it('should call permissionsController.removeAllAccountPermissions', async function () { assert( metamaskController.permissionsController.removeAllAccountPermissions.calledWith( addressToRemove, ), - ) - }) + ); + }); it('should return address', async function () { - assert.equal(ret, '0x1') - }) - }) + assert.equal(ret, '0x1'); + }); + }); describe('#setCurrentLocale', function () { it('checks the default currentLocale', function () { const preferenceCurrentLocale = metamaskController.preferencesController.store.getState() - .currentLocale - assert.equal(preferenceCurrentLocale, 'en_US') - }) + .currentLocale; + assert.equal(preferenceCurrentLocale, 'en_US'); + }); it('sets current locale in preferences controller', function () { - metamaskController.setCurrentLocale('ja', noop) + metamaskController.setCurrentLocale('ja', noop); const preferenceCurrentLocale = metamaskController.preferencesController.store.getState() - .currentLocale - assert.equal(preferenceCurrentLocale, 'ja') - }) - }) + .currentLocale; + assert.equal(preferenceCurrentLocale, 'ja'); + }); + }); describe('#newUnsignedMessage', function () { - let msgParams, metamaskMsgs, messages, msgId + let msgParams, metamaskMsgs, messages, msgId; - const address = '0xc42edfcc21ed14dda456aa0756c153f7985d8813' - const data = '0x43727970746f6b697474696573' + const address = '0xc42edfcc21ed14dda456aa0756c153f7985d8813'; + const data = '0x43727970746f6b697474696573'; beforeEach(async function () { - sandbox.stub(metamaskController, 'getBalance') + sandbox.stub(metamaskController, 'getBalance'); metamaskController.getBalance.callsFake(() => { - return Promise.resolve('0x0') - }) + return Promise.resolve('0x0'); + }); await metamaskController.createNewVaultAndRestore( 'foobar1337', TEST_SEED_ALT, - ) + ); msgParams = { from: address, data, - } + }; - const promise = metamaskController.newUnsignedMessage(msgParams) + const promise = metamaskController.newUnsignedMessage(msgParams); // handle the promise so it doesn't throw an unhandledRejection - promise.then(noop).catch(noop) + promise.then(noop).catch(noop); - metamaskMsgs = metamaskController.messageManager.getUnapprovedMsgs() - messages = metamaskController.messageManager.messages - msgId = Object.keys(metamaskMsgs)[0] - messages[0].msgParams.metamaskId = parseInt(msgId, 10) - }) + metamaskMsgs = metamaskController.messageManager.getUnapprovedMsgs(); + messages = metamaskController.messageManager.messages; + msgId = Object.keys(metamaskMsgs)[0]; + messages[0].msgParams.metamaskId = parseInt(msgId, 10); + }); it('persists address from msg params', function () { - assert.equal(metamaskMsgs[msgId].msgParams.from, address) - }) + assert.equal(metamaskMsgs[msgId].msgParams.from, address); + }); it('persists data from msg params', function () { - assert.equal(metamaskMsgs[msgId].msgParams.data, data) - }) + assert.equal(metamaskMsgs[msgId].msgParams.data, data); + }); it('sets the status to unapproved', function () { - assert.equal(metamaskMsgs[msgId].status, TRANSACTION_STATUSES.UNAPPROVED) - }) + assert.equal(metamaskMsgs[msgId].status, TRANSACTION_STATUSES.UNAPPROVED); + }); it('sets the type to eth_sign', function () { - assert.equal(metamaskMsgs[msgId].type, 'eth_sign') - }) + assert.equal(metamaskMsgs[msgId].type, 'eth_sign'); + }); it('rejects the message', function () { - const msgIdInt = parseInt(msgId, 10) - metamaskController.cancelMessage(msgIdInt, noop) - assert.equal(messages[0].status, TRANSACTION_STATUSES.REJECTED) - }) + const msgIdInt = parseInt(msgId, 10); + metamaskController.cancelMessage(msgIdInt, noop); + assert.equal(messages[0].status, TRANSACTION_STATUSES.REJECTED); + }); it('errors when signing a message', async function () { try { - await metamaskController.signMessage(messages[0].msgParams) + await metamaskController.signMessage(messages[0].msgParams); } catch (error) { - assert.equal(error.message, 'message length is invalid') + assert.equal(error.message, 'message length is invalid'); } - }) - }) + }); + }); describe('#newUnsignedPersonalMessage', function () { - let msgParams, metamaskPersonalMsgs, personalMessages, msgId + let msgParams, metamaskPersonalMsgs, personalMessages, msgId; - const address = '0xc42edfcc21ed14dda456aa0756c153f7985d8813' - const data = '0x43727970746f6b697474696573' + const address = '0xc42edfcc21ed14dda456aa0756c153f7985d8813'; + const data = '0x43727970746f6b697474696573'; beforeEach(async function () { - sandbox.stub(metamaskController, 'getBalance') + sandbox.stub(metamaskController, 'getBalance'); metamaskController.getBalance.callsFake(() => { - return Promise.resolve('0x0') - }) + return Promise.resolve('0x0'); + }); await metamaskController.createNewVaultAndRestore( 'foobar1337', TEST_SEED_ALT, - ) + ); msgParams = { from: address, data, - } + }; - const promise = metamaskController.newUnsignedPersonalMessage(msgParams) + const promise = metamaskController.newUnsignedPersonalMessage(msgParams); // handle the promise so it doesn't throw an unhandledRejection - promise.then(noop).catch(noop) + promise.then(noop).catch(noop); - metamaskPersonalMsgs = metamaskController.personalMessageManager.getUnapprovedMsgs() - personalMessages = metamaskController.personalMessageManager.messages - msgId = Object.keys(metamaskPersonalMsgs)[0] - personalMessages[0].msgParams.metamaskId = parseInt(msgId, 10) - }) + metamaskPersonalMsgs = metamaskController.personalMessageManager.getUnapprovedMsgs(); + personalMessages = metamaskController.personalMessageManager.messages; + msgId = Object.keys(metamaskPersonalMsgs)[0]; + personalMessages[0].msgParams.metamaskId = parseInt(msgId, 10); + }); it('errors with no from in msgParams', async function () { try { await metamaskController.newUnsignedPersonalMessage({ data, - }) - assert.fail('should have thrown') + }); + assert.fail('should have thrown'); } catch (error) { assert.equal( error.message, 'MetaMask Message Signature: from field is required.', - ) + ); } - }) + }); it('persists address from msg params', function () { - assert.equal(metamaskPersonalMsgs[msgId].msgParams.from, address) - }) + assert.equal(metamaskPersonalMsgs[msgId].msgParams.from, address); + }); it('persists data from msg params', function () { - assert.equal(metamaskPersonalMsgs[msgId].msgParams.data, data) - }) + assert.equal(metamaskPersonalMsgs[msgId].msgParams.data, data); + }); it('sets the status to unapproved', function () { assert.equal( metamaskPersonalMsgs[msgId].status, TRANSACTION_STATUSES.UNAPPROVED, - ) - }) + ); + }); it('sets the type to personal_sign', function () { - assert.equal(metamaskPersonalMsgs[msgId].type, 'personal_sign') - }) + assert.equal(metamaskPersonalMsgs[msgId].type, 'personal_sign'); + }); it('rejects the message', function () { - const msgIdInt = parseInt(msgId, 10) - metamaskController.cancelPersonalMessage(msgIdInt, noop) - assert.equal(personalMessages[0].status, TRANSACTION_STATUSES.REJECTED) - }) + const msgIdInt = parseInt(msgId, 10); + metamaskController.cancelPersonalMessage(msgIdInt, noop); + assert.equal(personalMessages[0].status, TRANSACTION_STATUSES.REJECTED); + }); it('errors when signing a message', async function () { await metamaskController.signPersonalMessage( personalMessages[0].msgParams, - ) + ); assert.equal( metamaskPersonalMsgs[msgId].status, TRANSACTION_STATUSES.SIGNED, - ) + ); assert.equal( metamaskPersonalMsgs[msgId].rawSig, '0x6a1b65e2b8ed53cf398a769fad24738f9fbe29841fe6854e226953542c4b6a173473cb152b6b1ae5f06d601d45dd699a129b0a8ca84e78b423031db5baa734741b', - ) - }) - }) + ); + }); + }); describe('#setupUntrustedCommunication', function () { - const mockTxParams = { from: TEST_ADDRESS } + const mockTxParams = { from: TEST_ADDRESS }; beforeEach(function () { - initializeMockMiddlewareLog() - }) + initializeMockMiddlewareLog(); + }); after(function () { - tearDownMockMiddlewareLog() - }) + tearDownMockMiddlewareLog(); + }); it('sets up phishing stream for untrusted communication', async function () { const phishingMessageSender = { url: 'http://myethereumwalletntw.com', tab: {}, - } + }; - const { promise, resolve } = deferredPromise() + const { promise, resolve } = deferredPromise(); const streamTest = createThoughStream((chunk, _, cb) => { if (chunk.name !== 'phishing') { - cb() - return + cb(); + return; } assert.equal( chunk.data.hostname, new URL(phishingMessageSender.url).hostname, - ) - resolve() - cb() - }) + ); + resolve(); + cb(); + }); metamaskController.setupUntrustedCommunication( streamTest, phishingMessageSender, - ) - await promise - streamTest.end() - }) + ); + await promise; + streamTest.end(); + }); it('adds a tabId and origin to requests', function (done) { const messageSender = { url: 'http://mycrypto.com', tab: { id: 456 }, - } + }; const streamTest = createThoughStream((chunk, _, cb) => { if (chunk.data && chunk.data.method) { - cb(null, chunk) - return + cb(null, chunk); + return; } - cb() - }) + cb(); + }); - metamaskController.setupUntrustedCommunication(streamTest, messageSender) + metamaskController.setupUntrustedCommunication(streamTest, messageSender); const message = { id: 1999133338649204, jsonrpc: '2.0', params: [{ ...mockTxParams }], method: 'eth_sendTransaction', - } + }; streamTest.write( { name: 'metamask-provider', @@ -1032,33 +1049,33 @@ describe('MetaMaskController', function () { ...message, origin: 'http://mycrypto.com', tabId: 456, - }) - done() - }) + }); + done(); + }); }, - ) - }) + ); + }); it('should add only origin to request if tabId not provided', function (done) { const messageSender = { url: 'http://mycrypto.com', - } + }; const streamTest = createThoughStream((chunk, _, cb) => { if (chunk.data && chunk.data.method) { - cb(null, chunk) - return + cb(null, chunk); + return; } - cb() - }) + cb(); + }); - metamaskController.setupUntrustedCommunication(streamTest, messageSender) + metamaskController.setupUntrustedCommunication(streamTest, messageSender); const message = { id: 1999133338649204, jsonrpc: '2.0', params: [{ ...mockTxParams }], method: 'eth_sendTransaction', - } + }; streamTest.write( { name: 'metamask-provider', @@ -1070,103 +1087,103 @@ describe('MetaMaskController', function () { assert.deepStrictEqual(loggerMiddlewareMock.requests[0], { ...message, origin: 'http://mycrypto.com', - }) - done() - }) + }); + done(); + }); }, - ) - }) - }) + ); + }); + }); describe('#setupTrustedCommunication', function () { it('sets up controller dnode api for trusted communication', async function () { const messageSender = { url: 'http://mycrypto.com', tab: {}, - } - const { promise, resolve } = deferredPromise() + }; + const { promise, resolve } = deferredPromise(); const streamTest = createThoughStream((chunk, _, cb) => { - assert.equal(chunk.name, 'controller') - resolve() - cb() - }) + assert.equal(chunk.name, 'controller'); + resolve(); + cb(); + }); - metamaskController.setupTrustedCommunication(streamTest, messageSender) - await promise - streamTest.end() - }) - }) + metamaskController.setupTrustedCommunication(streamTest, messageSender); + await promise; + streamTest.end(); + }); + }); describe('#markPasswordForgotten', function () { it('adds and sets forgottenPassword to config data to true', function () { - metamaskController.markPasswordForgotten(noop) - const state = metamaskController.getState() - assert.equal(state.forgottenPassword, true) - }) - }) + metamaskController.markPasswordForgotten(noop); + const state = metamaskController.getState(); + assert.equal(state.forgottenPassword, true); + }); + }); describe('#unMarkPasswordForgotten', function () { it('adds and sets forgottenPassword to config data to false', function () { - metamaskController.unMarkPasswordForgotten(noop) - const state = metamaskController.getState() - assert.equal(state.forgottenPassword, false) - }) - }) + metamaskController.unMarkPasswordForgotten(noop); + const state = metamaskController.getState(); + assert.equal(state.forgottenPassword, false); + }); + }); describe('#_onKeyringControllerUpdate', function () { it('should do nothing if there are no keyrings in state', async function () { - const syncAddresses = sinon.fake() - const syncWithAddresses = sinon.fake() + const syncAddresses = sinon.fake(); + const syncWithAddresses = sinon.fake(); sandbox.replace(metamaskController, 'preferencesController', { syncAddresses, - }) + }); sandbox.replace(metamaskController, 'accountTracker', { syncWithAddresses, - }) + }); - const oldState = metamaskController.getState() - await metamaskController._onKeyringControllerUpdate({ keyrings: [] }) + const oldState = metamaskController.getState(); + await metamaskController._onKeyringControllerUpdate({ keyrings: [] }); - assert.ok(syncAddresses.notCalled) - assert.ok(syncWithAddresses.notCalled) - assert.deepEqual(metamaskController.getState(), oldState) - }) + assert.ok(syncAddresses.notCalled); + assert.ok(syncWithAddresses.notCalled); + assert.deepEqual(metamaskController.getState(), oldState); + }); it('should sync addresses if there are keyrings in state', async function () { - const syncAddresses = sinon.fake() - const syncWithAddresses = sinon.fake() + const syncAddresses = sinon.fake(); + const syncWithAddresses = sinon.fake(); sandbox.replace(metamaskController, 'preferencesController', { syncAddresses, - }) + }); sandbox.replace(metamaskController, 'accountTracker', { syncWithAddresses, - }) + }); - const oldState = metamaskController.getState() + const oldState = metamaskController.getState(); await metamaskController._onKeyringControllerUpdate({ keyrings: [ { accounts: ['0x1', '0x2'], }, ], - }) + }); - assert.deepEqual(syncAddresses.args, [[['0x1', '0x2']]]) - assert.deepEqual(syncWithAddresses.args, [[['0x1', '0x2']]]) - assert.deepEqual(metamaskController.getState(), oldState) - }) + assert.deepEqual(syncAddresses.args, [[['0x1', '0x2']]]); + assert.deepEqual(syncWithAddresses.args, [[['0x1', '0x2']]]); + assert.deepEqual(metamaskController.getState(), oldState); + }); it('should NOT update selected address if already unlocked', async function () { - const syncAddresses = sinon.fake() - const syncWithAddresses = sinon.fake() + const syncAddresses = sinon.fake(); + const syncWithAddresses = sinon.fake(); sandbox.replace(metamaskController, 'preferencesController', { syncAddresses, - }) + }); sandbox.replace(metamaskController, 'accountTracker', { syncWithAddresses, - }) + }); - const oldState = metamaskController.getState() + const oldState = metamaskController.getState(); await metamaskController._onKeyringControllerUpdate({ isUnlocked: true, keyrings: [ @@ -1174,19 +1191,19 @@ describe('MetaMaskController', function () { accounts: ['0x1', '0x2'], }, ], - }) + }); - assert.deepEqual(syncAddresses.args, [[['0x1', '0x2']]]) - assert.deepEqual(syncWithAddresses.args, [[['0x1', '0x2']]]) - assert.deepEqual(metamaskController.getState(), oldState) - }) - }) -}) + assert.deepEqual(syncAddresses.args, [[['0x1', '0x2']]]); + assert.deepEqual(syncWithAddresses.args, [[['0x1', '0x2']]]); + assert.deepEqual(metamaskController.getState(), oldState); + }); + }); +}); function deferredPromise() { - let resolve + let resolve; const promise = new Promise((_resolve) => { - resolve = _resolve - }) - return { promise, resolve } + resolve = _resolve; + }); + return { promise, resolve }; } diff --git a/test/unit/app/controllers/metametrics-test.js b/test/unit/app/controllers/metametrics-test.js index 11c012bfc..8f2de0c02 100644 --- a/test/unit/app/controllers/metametrics-test.js +++ b/test/unit/app/controllers/metametrics-test.js @@ -1,36 +1,36 @@ -import { strict as assert } from 'assert' -import sinon from 'sinon' -import MetaMetricsController from '../../../../app/scripts/controllers/metametrics' -import { ENVIRONMENT_TYPE_BACKGROUND } from '../../../../shared/constants/app' -import { createSegmentMock } from '../../../../app/scripts/lib/segment' +import { strict as assert } from 'assert'; +import sinon from 'sinon'; +import MetaMetricsController from '../../../../app/scripts/controllers/metametrics'; +import { ENVIRONMENT_TYPE_BACKGROUND } from '../../../../shared/constants/app'; +import { createSegmentMock } from '../../../../app/scripts/lib/segment'; import { METAMETRICS_ANONYMOUS_ID, METAMETRICS_BACKGROUND_PAGE_OBJECT, -} from '../../../../shared/constants/metametrics' -import waitUntilCalled from '../../../lib/wait-until-called' +} from '../../../../shared/constants/metametrics'; +import waitUntilCalled from '../../../lib/wait-until-called'; -const segment = createSegmentMock(2, 10000) -const segmentLegacy = createSegmentMock(2, 10000) +const segment = createSegmentMock(2, 10000); +const segmentLegacy = createSegmentMock(2, 10000); -const VERSION = '0.0.1-test' -const NETWORK = 'Mainnet' -const FAKE_CHAIN_ID = '0x1338' -const LOCALE = 'en_US' -const TEST_META_METRICS_ID = '0xabc' +const VERSION = '0.0.1-test'; +const NETWORK = 'Mainnet'; +const FAKE_CHAIN_ID = '0x1338'; +const LOCALE = 'en_US'; +const TEST_META_METRICS_ID = '0xabc'; const DEFAULT_TEST_CONTEXT = { app: { name: 'MetaMask Extension', version: VERSION }, page: METAMETRICS_BACKGROUND_PAGE_OBJECT, referrer: undefined, userAgent: window.navigator.userAgent, -} +}; const DEFAULT_SHARED_PROPERTIES = { chain_id: FAKE_CHAIN_ID, locale: LOCALE.replace('_', '-'), network: NETWORK, environment_type: 'background', -} +}; const DEFAULT_EVENT_PROPERTIES = { category: 'Unit Test', @@ -38,22 +38,22 @@ const DEFAULT_EVENT_PROPERTIES = { value: undefined, currency: undefined, ...DEFAULT_SHARED_PROPERTIES, -} +}; const DEFAULT_PAGE_PROPERTIES = { ...DEFAULT_SHARED_PROPERTIES, -} +}; function getMockNetworkController( chainId = FAKE_CHAIN_ID, provider = { type: NETWORK }, ) { - let networkStore = { chainId, provider } - const on = sinon.stub().withArgs('networkDidChange') + let networkStore = { chainId, provider }; + const on = sinon.stub().withArgs('networkDidChange'); const updateState = (newState) => { - networkStore = { ...networkStore, ...newState } - on.getCall(0).args[1]() - } + networkStore = { ...networkStore, ...newState }; + on.getCall(0).args[1](); + }; return { store: { getState: () => networkStore, @@ -62,23 +62,23 @@ function getMockNetworkController( getCurrentChainId: () => networkStore.chainId, getNetworkIdentifier: () => networkStore.provider.type, on, - } + }; } function getMockPreferencesStore({ currentLocale = LOCALE } = {}) { let preferencesStore = { currentLocale, - } - const subscribe = sinon.stub() + }; + const subscribe = sinon.stub(); const updateState = (newState) => { - preferencesStore = { ...preferencesStore, ...newState } - subscribe.getCall(0).args[0](preferencesStore) - } + preferencesStore = { ...preferencesStore, ...newState }; + subscribe.getCall(0).args[0](preferencesStore); + }; return { getState: sinon.stub().returns(preferencesStore), updateState, subscribe, - } + }; } function getMetaMetricsController({ @@ -109,123 +109,126 @@ function getMetaMetricsController({ metaMetricsId, metaMetricsSendCount, }, - }) + }); } describe('MetaMetricsController', function () { describe('constructor', function () { it('should properly initialize', function () { - const metaMetricsController = getMetaMetricsController() - assert.strictEqual(metaMetricsController.version, VERSION) - assert.strictEqual(metaMetricsController.network, NETWORK) - assert.strictEqual(metaMetricsController.chainId, FAKE_CHAIN_ID) + const metaMetricsController = getMetaMetricsController(); + assert.strictEqual(metaMetricsController.version, VERSION); + assert.strictEqual(metaMetricsController.network, NETWORK); + assert.strictEqual(metaMetricsController.chainId, FAKE_CHAIN_ID); assert.strictEqual( metaMetricsController.state.participateInMetaMetrics, true, - ) + ); assert.strictEqual( metaMetricsController.state.metaMetricsId, TEST_META_METRICS_ID, - ) - assert.strictEqual(metaMetricsController.locale, LOCALE.replace('_', '-')) - }) + ); + assert.strictEqual( + metaMetricsController.locale, + LOCALE.replace('_', '-'), + ); + }); it('should update when network changes', function () { - const networkController = getMockNetworkController() + const networkController = getMockNetworkController(); const metaMetricsController = getMetaMetricsController({ networkController, - }) - assert.strictEqual(metaMetricsController.network, NETWORK) + }); + assert.strictEqual(metaMetricsController.network, NETWORK); networkController.store.updateState({ provider: { type: 'NEW_NETWORK', }, chainId: '0xaab', - }) - assert.strictEqual(metaMetricsController.network, 'NEW_NETWORK') - assert.strictEqual(metaMetricsController.chainId, '0xaab') - }) + }); + assert.strictEqual(metaMetricsController.network, 'NEW_NETWORK'); + assert.strictEqual(metaMetricsController.chainId, '0xaab'); + }); it('should update when preferences changes', function () { - const preferencesStore = getMockPreferencesStore() + const preferencesStore = getMockPreferencesStore(); const metaMetricsController = getMetaMetricsController({ preferencesStore, - }) - assert.strictEqual(metaMetricsController.network, NETWORK) + }); + assert.strictEqual(metaMetricsController.network, NETWORK); preferencesStore.updateState({ currentLocale: 'en_UK', - }) - assert.strictEqual(metaMetricsController.locale, 'en-UK') - }) - }) + }); + assert.strictEqual(metaMetricsController.locale, 'en-UK'); + }); + }); describe('generateMetaMetricsId', function () { it('should generate an 0x prefixed hex string', function () { - const metaMetricsController = getMetaMetricsController() + const metaMetricsController = getMetaMetricsController(); assert.equal( metaMetricsController.generateMetaMetricsId().startsWith('0x'), true, - ) - }) - }) + ); + }); + }); describe('setParticipateInMetaMetrics', function () { it('should update the value of participateInMetaMetrics', function () { const metaMetricsController = getMetaMetricsController({ participateInMetaMetrics: null, metaMetricsId: null, - }) - assert.equal(metaMetricsController.state.participateInMetaMetrics, null) - metaMetricsController.setParticipateInMetaMetrics(true) - assert.equal(metaMetricsController.state.participateInMetaMetrics, true) - metaMetricsController.setParticipateInMetaMetrics(false) - assert.equal(metaMetricsController.state.participateInMetaMetrics, false) - }) + }); + assert.equal(metaMetricsController.state.participateInMetaMetrics, null); + metaMetricsController.setParticipateInMetaMetrics(true); + assert.equal(metaMetricsController.state.participateInMetaMetrics, true); + metaMetricsController.setParticipateInMetaMetrics(false); + assert.equal(metaMetricsController.state.participateInMetaMetrics, false); + }); it('should generate and update the metaMetricsId when set to true', function () { const metaMetricsController = getMetaMetricsController({ participateInMetaMetrics: null, metaMetricsId: null, - }) - assert.equal(metaMetricsController.state.metaMetricsId, null) - metaMetricsController.setParticipateInMetaMetrics(true) - assert.equal(typeof metaMetricsController.state.metaMetricsId, 'string') - }) + }); + assert.equal(metaMetricsController.state.metaMetricsId, null); + metaMetricsController.setParticipateInMetaMetrics(true); + assert.equal(typeof metaMetricsController.state.metaMetricsId, 'string'); + }); it('should nullify the metaMetricsId when set to false', function () { - const metaMetricsController = getMetaMetricsController() - metaMetricsController.setParticipateInMetaMetrics(false) - assert.equal(metaMetricsController.state.metaMetricsId, null) - }) - }) + const metaMetricsController = getMetaMetricsController(); + metaMetricsController.setParticipateInMetaMetrics(false); + assert.equal(metaMetricsController.state.metaMetricsId, null); + }); + }); describe('setMetaMetricsSendCount', function () { it('should update the send count in state', function () { - const metaMetricsController = getMetaMetricsController() - metaMetricsController.setMetaMetricsSendCount(1) - assert.equal(metaMetricsController.state.metaMetricsSendCount, 1) - }) - }) + const metaMetricsController = getMetaMetricsController(); + metaMetricsController.setMetaMetricsSendCount(1); + assert.equal(metaMetricsController.state.metaMetricsSendCount, 1); + }); + }); describe('trackEvent', function () { it('should not track an event if user is not participating in metametrics', function () { - const mock = sinon.mock(segment) + const mock = sinon.mock(segment); const metaMetricsController = getMetaMetricsController({ participateInMetaMetrics: false, - }) - mock.expects('track').never() + }); + mock.expects('track').never(); metaMetricsController.trackEvent({ event: 'Fake Event', category: 'Unit Test', properties: { test: 1, }, - }) - mock.verify() - }) + }); + mock.verify(); + }); it('should track an event if user has not opted in, but isOptIn is true', function () { - const mock = sinon.mock(segment) + const mock = sinon.mock(segment); const metaMetricsController = getMetaMetricsController({ participateInMetaMetrics: false, - }) + }); mock .expects('track') .once() @@ -237,7 +240,7 @@ describe('MetaMetricsController', function () { test: 1, ...DEFAULT_EVENT_PROPERTIES, }, - }) + }); metaMetricsController.trackEvent( { event: 'Fake Event', @@ -247,15 +250,15 @@ describe('MetaMetricsController', function () { }, }, { isOptIn: true }, - ) - mock.verify() - }) + ); + mock.verify(); + }); it('should track an event during optin and allow for metaMetricsId override', function () { - const mock = sinon.mock(segment) + const mock = sinon.mock(segment); const metaMetricsController = getMetaMetricsController({ participateInMetaMetrics: false, - }) + }); mock .expects('track') .once() @@ -267,7 +270,7 @@ describe('MetaMetricsController', function () { test: 1, ...DEFAULT_EVENT_PROPERTIES, }, - }) + }); metaMetricsController.trackEvent( { event: 'Fake Event', @@ -277,13 +280,13 @@ describe('MetaMetricsController', function () { }, }, { isOptIn: true, metaMetricsId: 'TESTID' }, - ) - mock.verify() - }) + ); + mock.verify(); + }); it('should track a legacy event', function () { - const mock = sinon.mock(segmentLegacy) - const metaMetricsController = getMetaMetricsController() + const mock = sinon.mock(segmentLegacy); + const metaMetricsController = getMetaMetricsController(); mock .expects('track') .once() @@ -295,7 +298,7 @@ describe('MetaMetricsController', function () { test: 1, ...DEFAULT_EVENT_PROPERTIES, }, - }) + }); metaMetricsController.trackEvent( { event: 'Fake Event', @@ -305,13 +308,13 @@ describe('MetaMetricsController', function () { }, }, { matomoEvent: true }, - ) - mock.verify() - }) + ); + mock.verify(); + }); it('should track a non legacy event', function () { - const mock = sinon.mock(segment) - const metaMetricsController = getMetaMetricsController() + const mock = sinon.mock(segment); + const metaMetricsController = getMetaMetricsController(); mock .expects('track') .once() @@ -323,22 +326,22 @@ describe('MetaMetricsController', function () { test: 1, ...DEFAULT_EVENT_PROPERTIES, }, - }) + }); metaMetricsController.trackEvent({ event: 'Fake Event', category: 'Unit Test', properties: { test: 1, }, - }) - mock.verify() - }) + }); + mock.verify(); + }); it('should use anonymousId when metametrics send count is not trackable in send flow', function () { - const mock = sinon.mock(segment) + const mock = sinon.mock(segment); const metaMetricsController = getMetaMetricsController({ metaMetricsSendCount: 1, - }) + }); mock .expects('track') .once() @@ -350,20 +353,20 @@ describe('MetaMetricsController', function () { test: 1, ...DEFAULT_EVENT_PROPERTIES, }, - }) + }); metaMetricsController.trackEvent({ event: 'Send Fake Event', category: 'Unit Test', properties: { test: 1, }, - }) - mock.verify() - }) + }); + mock.verify(); + }); it('should use user metametrics id when metametrics send count is trackable in send flow', function () { - const mock = sinon.mock(segment) - const metaMetricsController = getMetaMetricsController() + const mock = sinon.mock(segment); + const metaMetricsController = getMetaMetricsController(); mock .expects('track') .once() @@ -375,7 +378,7 @@ describe('MetaMetricsController', function () { test: 1, ...DEFAULT_EVENT_PROPERTIES, }, - }) + }); metaMetricsController.trackEvent( { event: 'Send Fake Event', @@ -385,41 +388,41 @@ describe('MetaMetricsController', function () { }, }, { metaMetricsSendCount: 0 }, - ) - mock.verify() - }) + ); + mock.verify(); + }); it('should immediately flush queue if flushImmediately set to true', async function () { - const metaMetricsController = getMetaMetricsController() - const flushStub = sinon.stub(segment, 'flush') - const flushCalled = waitUntilCalled(flushStub, segment) + const metaMetricsController = getMetaMetricsController(); + const flushStub = sinon.stub(segment, 'flush'); + const flushCalled = waitUntilCalled(flushStub, segment); metaMetricsController.trackEvent( { event: 'Fake Event', category: 'Unit Test', }, { flushImmediately: true }, - ) - assert.doesNotReject(flushCalled()) - }) + ); + assert.doesNotReject(flushCalled()); + }); it('should throw if event or category not provided', function () { - const metaMetricsController = getMetaMetricsController() + const metaMetricsController = getMetaMetricsController(); assert.rejects( () => metaMetricsController.trackEvent({ event: 'test' }), /Must specify event and category\./u, 'must specify category', - ) + ); assert.rejects( () => metaMetricsController.trackEvent({ category: 'test' }), /Must specify event and category\./u, 'must specify event', - ) - }) + ); + }); it('should throw if provided sensitiveProperties, when excludeMetaMetricsId is true', function () { - const metaMetricsController = getMetaMetricsController() + const metaMetricsController = getMetaMetricsController(); assert.rejects( () => metaMetricsController.trackEvent( @@ -431,18 +434,18 @@ describe('MetaMetricsController', function () { { excludeMetaMetricsId: true }, ), /sensitiveProperties was specified in an event payload that also set the excludeMetaMetricsId flag/u, - ) - }) + ); + }); it('should track sensitiveProperties in a separate, anonymous event', function () { - const metaMetricsController = getMetaMetricsController() - const spy = sinon.spy(segment, 'track') + const metaMetricsController = getMetaMetricsController(); + const spy = sinon.spy(segment, 'track'); metaMetricsController.trackEvent({ event: 'Fake Event', category: 'Unit Test', sensitiveProperties: { foo: 'bar' }, - }) - assert.ok(spy.calledTwice) + }); + assert.ok(spy.calledTwice); assert.ok( spy.calledWith({ event: 'Fake Event', @@ -453,7 +456,7 @@ describe('MetaMetricsController', function () { ...DEFAULT_EVENT_PROPERTIES, }, }), - ) + ); assert.ok( spy.calledWith({ event: 'Fake Event', @@ -461,14 +464,14 @@ describe('MetaMetricsController', function () { context: DEFAULT_TEST_CONTEXT, properties: DEFAULT_EVENT_PROPERTIES, }), - ) - }) - }) + ); + }); + }); describe('trackPage', function () { it('should track a page view', function () { - const mock = sinon.mock(segment) - const metaMetricsController = getMetaMetricsController() + const mock = sinon.mock(segment); + const metaMetricsController = getMetaMetricsController(); mock .expects('page') .once() @@ -480,38 +483,38 @@ describe('MetaMetricsController', function () { params: null, ...DEFAULT_PAGE_PROPERTIES, }, - }) + }); metaMetricsController.trackPage({ name: 'home', params: null, environmentType: ENVIRONMENT_TYPE_BACKGROUND, page: METAMETRICS_BACKGROUND_PAGE_OBJECT, - }) - mock.verify() - }) + }); + mock.verify(); + }); it('should not track a page view if user is not participating in metametrics', function () { - const mock = sinon.mock(segment) + const mock = sinon.mock(segment); const metaMetricsController = getMetaMetricsController({ participateInMetaMetrics: false, - }) - mock.expects('page').never() + }); + mock.expects('page').never(); metaMetricsController.trackPage({ name: 'home', params: null, environmentType: ENVIRONMENT_TYPE_BACKGROUND, page: METAMETRICS_BACKGROUND_PAGE_OBJECT, - }) - mock.verify() - }) + }); + mock.verify(); + }); it('should track a page view if isOptInPath is true and user not yet opted in', function () { - const mock = sinon.mock(segment) + const mock = sinon.mock(segment); const metaMetricsController = getMetaMetricsController({ preferencesStore: getMockPreferencesStore({ participateInMetaMetrics: null, }), - }) + }); mock .expects('page') .once() @@ -523,7 +526,7 @@ describe('MetaMetricsController', function () { params: null, ...DEFAULT_PAGE_PROPERTIES, }, - }) + }); metaMetricsController.trackPage( { name: 'home', @@ -532,15 +535,15 @@ describe('MetaMetricsController', function () { page: METAMETRICS_BACKGROUND_PAGE_OBJECT, }, { isOptInPath: true }, - ) - mock.verify() - }) - }) + ); + mock.verify(); + }); + }); afterEach(function () { // flush the queues manually after each test - segment.flush() - segmentLegacy.flush() - sinon.restore() - }) -}) + segment.flush(); + segmentLegacy.flush(); + sinon.restore(); + }); +}); diff --git a/test/unit/app/controllers/network/network-controller-test.js b/test/unit/app/controllers/network/network-controller-test.js index 2fb123fec..b7e1ab502 100644 --- a/test/unit/app/controllers/network/network-controller-test.js +++ b/test/unit/app/controllers/network/network-controller-test.js @@ -1,73 +1,73 @@ -import { strict as assert } from 'assert' -import sinon from 'sinon' -import NetworkController from '../../../../../app/scripts/controllers/network' -import { getNetworkDisplayName } from '../../../../../app/scripts/controllers/network/util' +import { strict as assert } from 'assert'; +import sinon from 'sinon'; +import NetworkController from '../../../../../app/scripts/controllers/network'; +import { getNetworkDisplayName } from '../../../../../app/scripts/controllers/network/util'; describe('NetworkController', function () { describe('controller', function () { - let networkController - const noop = () => undefined + let networkController; + const noop = () => undefined; const networkControllerProviderConfig = { getAccounts: noop, - } + }; beforeEach(function () { - networkController = new NetworkController() - networkController.setInfuraProjectId('foo') - }) + networkController = new NetworkController(); + networkController.setInfuraProjectId('foo'); + }); describe('#provider', function () { it('provider should be updatable without reassignment', function () { - networkController.initializeProvider(networkControllerProviderConfig) + networkController.initializeProvider(networkControllerProviderConfig); const providerProxy = networkController.getProviderAndBlockTracker() - .provider - assert.equal(providerProxy.test, undefined) - providerProxy.setTarget({ test: true }) - assert.equal(providerProxy.test, true) - }) - }) + .provider; + assert.equal(providerProxy.test, undefined); + providerProxy.setTarget({ test: true }); + assert.equal(providerProxy.test, true); + }); + }); describe('#getNetworkState', function () { it('should return "loading" when new', function () { - const networkState = networkController.getNetworkState() - assert.equal(networkState, 'loading', 'network is loading') - }) - }) + const networkState = networkController.getNetworkState(); + assert.equal(networkState, 'loading', 'network is loading'); + }); + }); describe('#setNetworkState', function () { it('should update the network', function () { - networkController.setNetworkState('1') - const networkState = networkController.getNetworkState() - assert.equal(networkState, '1', 'network is 1') - }) - }) + networkController.setNetworkState('1'); + const networkState = networkController.getNetworkState(); + assert.equal(networkState, '1', 'network is 1'); + }); + }); describe('#setProviderType', function () { it('should update provider.type', function () { - networkController.initializeProvider(networkControllerProviderConfig) - networkController.setProviderType('mainnet') - const { type } = networkController.getProviderConfig() - assert.equal(type, 'mainnet', 'provider type is updated') - }) + networkController.initializeProvider(networkControllerProviderConfig); + networkController.setProviderType('mainnet'); + const { type } = networkController.getProviderConfig(); + assert.equal(type, 'mainnet', 'provider type is updated'); + }); it('should set the network to loading', function () { - networkController.initializeProvider(networkControllerProviderConfig) + networkController.initializeProvider(networkControllerProviderConfig); - const spy = sinon.spy(networkController, 'setNetworkState') - networkController.setProviderType('mainnet') + const spy = sinon.spy(networkController, 'setNetworkState'); + networkController.setProviderType('mainnet'); assert.equal( spy.callCount, 1, 'should have called setNetworkState 2 times', - ) + ); assert.ok( spy.calledOnceWithExactly('loading'), 'should have called with "loading" first', - ) - }) - }) - }) + ); + }); + }); + }); describe('utils', function () { it('getNetworkDisplayName should return the correct network name', function () { @@ -116,11 +116,11 @@ describe('NetworkController', function () { input: 'goerli', expected: 'Goerli', }, - ] + ]; tests.forEach(({ input, expected }) => assert.equal(getNetworkDisplayName(input), expected), - ) - }) - }) -}) + ); + }); + }); +}); diff --git a/test/unit/app/controllers/network/pending-middleware-test.js b/test/unit/app/controllers/network/pending-middleware-test.js index 36b917d16..65e011d09 100644 --- a/test/unit/app/controllers/network/pending-middleware-test.js +++ b/test/unit/app/controllers/network/pending-middleware-test.js @@ -1,56 +1,56 @@ -import assert from 'assert' +import assert from 'assert'; import { createPendingNonceMiddleware, createPendingTxMiddleware, -} from '../../../../../app/scripts/controllers/network/middleware/pending' -import { txMetaStub } from './stubs' +} from '../../../../../app/scripts/controllers/network/middleware/pending'; +import { txMetaStub } from './stubs'; describe('PendingNonceMiddleware', function () { describe('#createPendingNonceMiddleware', function () { - const getPendingNonce = async () => '0x2' - const address = '0xF231D46dD78806E1DD93442cf33C7671f8538748' + const getPendingNonce = async () => '0x2'; + const address = '0xF231D46dD78806E1DD93442cf33C7671f8538748'; const pendingNonceMiddleware = createPendingNonceMiddleware({ getPendingNonce, - }) + }); it('should call next if not a eth_getTransactionCount request', function (done) { - const req = { method: 'eth_getBlockByNumber' } - const res = {} - pendingNonceMiddleware(req, res, () => done()) - }) + const req = { method: 'eth_getBlockByNumber' }; + const res = {}; + pendingNonceMiddleware(req, res, () => done()); + }); it('should call next if not a "pending" block request', function (done) { - const req = { method: 'eth_getTransactionCount', params: [address] } - const res = {} - pendingNonceMiddleware(req, res, () => done()) - }) + const req = { method: 'eth_getTransactionCount', params: [address] }; + const res = {}; + pendingNonceMiddleware(req, res, () => done()); + }); it('should fill the result with a the "pending" nonce', function (done) { const req = { method: 'eth_getTransactionCount', params: [address, 'pending'], - } - const res = {} + }; + const res = {}; pendingNonceMiddleware( req, res, () => { - done(new Error('should not have called next')) + done(new Error('should not have called next')); }, () => { - assert(res.result === '0x2') - done() + assert(res.result === '0x2'); + done(); }, - ) - }) - }) + ); + }); + }); describe('#createPendingTxMiddleware', function () { - let returnUndefined = true + let returnUndefined = true; const getPendingTransactionByHash = () => - returnUndefined ? undefined : txMetaStub - const address = '0xF231D46dD78806E1DD93442cf33C7671f8538748' + returnUndefined ? undefined : txMetaStub; + const address = '0xF231D46dD78806E1DD93442cf33C7671f8538748'; const pendingTxMiddleware = createPendingTxMiddleware({ getPendingTransactionByHash, - }) + }); const spec = { blockHash: null, blockNumber: null, @@ -67,41 +67,41 @@ describe('PendingNonceMiddleware', function () { v: '0x2c', r: '0x5f973e540f2d3c2f06d3725a626b75247593cb36477187ae07ecfe0a4db3cf57', s: '0x0259b52ee8c58baaa385fb05c3f96116e58de89bcc165cb3bfdfc708672fed8a', - } + }; it('should call next if not a eth_getTransactionByHash request', function (done) { - const req = { method: 'eth_getBlockByNumber' } - const res = {} - pendingTxMiddleware(req, res, () => done()) - }) + const req = { method: 'eth_getBlockByNumber' }; + const res = {}; + pendingTxMiddleware(req, res, () => done()); + }); it('should call next if no pending txMeta is in history', function (done) { - const req = { method: 'eth_getTransactionByHash', params: [address] } - const res = {} - pendingTxMiddleware(req, res, () => done()) - }) + const req = { method: 'eth_getTransactionByHash', params: [address] }; + const res = {}; + pendingTxMiddleware(req, res, () => done()); + }); it('should fill the result with a the "pending" tx the result should match the rpc spec', function (done) { - returnUndefined = false + returnUndefined = false; const req = { method: 'eth_getTransactionByHash', params: [address, 'pending'], - } - const res = {} + }; + const res = {}; pendingTxMiddleware( req, res, () => { - done(new Error('should not have called next')) + done(new Error('should not have called next')); }, () => { assert.deepStrictEqual( res.result, spec, new Error('result does not match the spec object'), - ) - done() + ); + done(); }, - ) - }) - }) -}) + ); + }); + }); +}); diff --git a/test/unit/app/controllers/network/stubs.js b/test/unit/app/controllers/network/stubs.js index 0388e8d08..421e125a8 100644 --- a/test/unit/app/controllers/network/stubs.js +++ b/test/unit/app/controllers/network/stubs.js @@ -2,7 +2,7 @@ import { TRANSACTION_CATEGORIES, TRANSACTION_STATUSES, TRANSACTION_TYPES, -} from '../../../../../shared/constants/transaction' +} from '../../../../../shared/constants/transaction'; export const txMetaStub = { firstRetryBlockNumber: '0x51a402', @@ -207,4 +207,4 @@ export const txMetaStub = { }, type: TRANSACTION_TYPES.STANDARD, v: '0x2c', -} +}; diff --git a/test/unit/app/controllers/permissions/helpers.js b/test/unit/app/controllers/permissions/helpers.js index 0524be1e9..d0e4f57dd 100644 --- a/test/unit/app/controllers/permissions/helpers.js +++ b/test/unit/app/controllers/permissions/helpers.js @@ -1,6 +1,6 @@ -import { strict as assert } from 'assert' +import { strict as assert } from 'assert'; -import { noop } from './mocks' +import { noop } from './mocks'; /** * Grants the given permissions to the given origin, using the given permissions @@ -13,7 +13,7 @@ import { noop } from './mocks' * @param {Object} permissions - The permissions to grant. */ export function grantPermissions(permController, origin, permissions) { - permController.permissions.grantNewPermissions(origin, permissions, {}, noop) + permController.permissions.grantNewPermissions(origin, permissions, {}, noop); } /** @@ -34,8 +34,8 @@ export function getRequestUserApprovalHelper(permController) { return (id, origin = 'defaultOrigin') => { return permController.permissions.requestUserApproval({ metadata: { id, origin }, - }) - } + }); + }; } /** @@ -50,15 +50,15 @@ export function getRequestUserApprovalHelper(permController) { * has been set. */ export function getUserApprovalPromise(permController) { - const originalFunction = permController.permissions.requestUserApproval + const originalFunction = permController.permissions.requestUserApproval; return new Promise((resolveHelperPromise) => { permController.permissions.requestUserApproval = (req) => { - const userApprovalPromise = originalFunction(req) - permController.permissions.requestUserApproval = originalFunction - resolveHelperPromise() - return userApprovalPromise - } - }) + const userApprovalPromise = originalFunction(req); + permController.permissions.requestUserApproval = originalFunction; + resolveHelperPromise(); + return userApprovalPromise; + }; + }); } /** @@ -73,46 +73,50 @@ export function getUserApprovalPromise(permController) { */ export function validateActivityEntry(entry, req, res, methodType, success) { assert.doesNotThrow(() => { - _validateActivityEntry(entry, req, res, methodType, success) - }, 'should have expected activity entry') + _validateActivityEntry(entry, req, res, methodType, success); + }, 'should have expected activity entry'); } function _validateActivityEntry(entry, req, res, methodType, success) { - assert.ok(entry, 'entry should exist') + assert.ok(entry, 'entry should exist'); - assert.equal(entry.id, req.id) - assert.equal(entry.method, req.method) - assert.equal(entry.origin, req.origin) - assert.equal(entry.methodType, methodType) - assert.deepEqual(entry.request, req, 'entry.request should equal the request') + assert.equal(entry.id, req.id); + assert.equal(entry.method, req.method); + assert.equal(entry.origin, req.origin); + assert.equal(entry.methodType, methodType); + assert.deepEqual( + entry.request, + req, + 'entry.request should equal the request', + ); if (res) { assert.ok( Number.isInteger(entry.requestTime) && Number.isInteger(entry.responseTime), 'request and response times should be numbers', - ) + ); assert.ok( entry.requestTime <= entry.responseTime, 'request time should be less than response time', - ) + ); - assert.equal(entry.success, success) + assert.equal(entry.success, success); assert.deepEqual( entry.response, res, 'entry.response should equal the response', - ) + ); } else { assert.ok( Number.isInteger(entry.requestTime) && entry.requestTime > 0, 'entry should have non-zero request time', - ) + ); assert.ok( entry.success === null && entry.responseTime === null && entry.response === null, 'entry response values should be null', - ) + ); } } diff --git a/test/unit/app/controllers/permissions/mocks.js b/test/unit/app/controllers/permissions/mocks.js index be4a2321b..ddbf9ff41 100644 --- a/test/unit/app/controllers/permissions/mocks.js +++ b/test/unit/app/controllers/permissions/mocks.js @@ -1,15 +1,15 @@ -import { ethErrors, errorCodes } from 'eth-rpc-errors' -import deepFreeze from 'deep-freeze-strict' +import { ethErrors, errorCodes } from 'eth-rpc-errors'; +import deepFreeze from 'deep-freeze-strict'; -import { ApprovalController } from '@metamask/controllers' +import { ApprovalController } from '@metamask/controllers'; -import _getRestrictedMethods from '../../../../../app/scripts/controllers/permissions/restrictedMethods' +import _getRestrictedMethods from '../../../../../app/scripts/controllers/permissions/restrictedMethods'; -import { CAVEAT_NAMES } from '../../../../../shared/constants/permissions' +import { CAVEAT_NAMES } from '../../../../../shared/constants/permissions'; import { CAVEAT_TYPES, NOTIFICATION_NAMES, -} from '../../../../../app/scripts/controllers/permissions/enums' +} from '../../../../../app/scripts/controllers/permissions/enums'; /** * README @@ -21,7 +21,7 @@ import { * - Immutable mock values like Ethereum accounts and expected states */ -export const noop = () => undefined +export const noop = () => undefined; /** * Mock Permissions Controller and Middleware @@ -32,14 +32,14 @@ const keyringAccounts = deepFreeze([ '0xc42edfcc21ed14dda456aa0756c153f7985d8813', '0x7ae1cdd37bcbdb0e1f491974da8022bfdbf9c2bf', '0xcc74c7a59194e5d9268476955650d1e285be703c', -]) +]); const getIdentities = () => { return keyringAccounts.reduce((identities, address, index) => { - identities[address] = { address, name: `Account ${index}` } - return identities - }, {}) -} + identities[address] = { address, name: `Account ${index}` }; + return identities; + }, {}); +}; // perm controller initialization helper const getRestrictedMethods = (permController) => { @@ -52,15 +52,15 @@ const getRestrictedMethods = (permController) => { description: `This method is only for testing.`, method: (req, res, __, end) => { if (req.params[0]) { - res.result = 1 + res.result = 1; } else { - res.result = 0 + res.result = 0; } - end() + end(); }, }, - } -} + }; +}; /** * Gets default mock constructor options for a permissions controller. @@ -84,12 +84,12 @@ export function getPermControllerOpts() { return { identities: getIdentities(), selectedAddress: keyringAccounts[0], - } + }; }, subscribe: noop, }, showPermissionRequest: noop, - } + }; } /** @@ -102,24 +102,24 @@ export function getPermControllerOpts() { * @returns {Function} A Promise-wrapped middleware function with convenient default args. */ export function getPermissionsMiddleware(permController, origin, extensionId) { - const middleware = permController.createMiddleware({ origin, extensionId }) + const middleware = permController.createMiddleware({ origin, extensionId }); return (req, res = {}, next = noop, end) => { return new Promise((resolve, reject) => { // eslint-disable-next-line no-param-reassign - end = end || _end + end = end || _end; - middleware(req, res, next, end) + middleware(req, res, next, end); // emulates json-rpc-engine error handling function _end(err) { if (err || res.error) { - reject(err || res.error) + reject(err || res.error); } else { - resolve(res) + resolve(res); } } - }) - } + }); + }; } /** @@ -132,8 +132,8 @@ export const getNotifyDomain = (notifications = {}) => ( origin, notification, ) => { - notifications[origin].push(notification) -} + notifications[origin].push(notification); +}; /** * @param {Object} notifications - An object that will store notifications produced @@ -143,9 +143,9 @@ export const getNotifyDomain = (notifications = {}) => ( */ export const getNotifyAllDomains = (notifications = {}) => (notification) => { Object.keys(notifications).forEach((origin) => { - notifications[origin].push(notification) - }) -} + notifications[origin].push(notification); + }); +}; /** * Constants and Mock Objects @@ -156,13 +156,13 @@ const DOMAINS = { a: { origin: 'https://foo.xyz', host: 'foo.xyz' }, b: { origin: 'https://bar.abc', host: 'bar.abc' }, c: { origin: 'https://baz.def', host: 'baz.def' }, -} +}; const PERM_NAMES = { eth_accounts: 'eth_accounts', test_method: 'test_method', does_not_exist: 'does_not_exist', -} +}; const ACCOUNTS = { a: { @@ -177,7 +177,7 @@ const ACCOUNTS = { permitted: [keyringAccounts[1]], primary: keyringAccounts[1], }, -} +}; /** * Helpers for getting mock caveats. @@ -201,9 +201,9 @@ const CAVEATS = { value: accounts, name: CAVEAT_NAMES.exposedAccounts, }, - ] + ]; }, -} +}; /** * Each function here corresponds to what would be a type or interface consumed @@ -219,7 +219,7 @@ const PERMS = { return { permissions: { ...permissions }, metadata: { id }, - } + }; }, /** @@ -230,21 +230,21 @@ const PERMS = { * @returns {Object} A permissions request object with eth_accounts */ eth_accounts: () => { - return { eth_accounts: {} } + return { eth_accounts: {} }; }, /** * @returns {Object} A permissions request object with test_method */ test_method: () => { - return { test_method: {} } + return { test_method: {} }; }, /** * @returns {Object} A permissions request object with does_not_exist */ does_not_exist: () => { - return { does_not_exist: {} } + return { does_not_exist: {} }; }, }, @@ -261,7 +261,7 @@ const PERMS = { eth_accounts: { caveats: CAVEATS.eth_accounts(accounts), }, - } + }; }, /** @@ -270,7 +270,7 @@ const PERMS = { test_method: () => { return { test_method: {}, - } + }; }, }, @@ -288,7 +288,7 @@ const PERMS = { return { parentCapability: PERM_NAMES.eth_accounts, caveats: CAVEATS.eth_accounts(accounts), - } + }; }, /** @@ -297,10 +297,10 @@ const PERMS = { test_method: () => { return { parentCapability: PERM_NAMES.test_method, - } + }; }, }, -} +}; /** * Objects with function values for getting correctly formatted permissions, @@ -320,14 +320,14 @@ export const getters = deepFreeze({ return { name: 'Error', message: 'Must provide non-empty array of account(s).', - } + }; }, nonKeyringAccount: (account) => { return { name: 'Error', message: `Unknown account: ${account}`, - } + }; }, }, @@ -337,7 +337,7 @@ export const getters = deepFreeze({ // name: 'EthereumRpcError', message: `Failed to add 'eth_accounts' to '${origin}'.`, code: errorCodes.rpc.internal, - } + }; }, }, @@ -345,17 +345,17 @@ export const getters = deepFreeze({ alreadyPermitted: () => { return { message: 'Account is already permitted for origin', - } + }; }, invalidOrigin: () => { return { message: 'Unrecognized domain', - } + }; }, noEthAccountsPermission: () => { return { message: `Origin does not have 'eth_accounts' permission`, - } + }; }, }, @@ -363,17 +363,17 @@ export const getters = deepFreeze({ notPermitted: () => { return { message: 'Account is not permitted for origin', - } + }; }, invalidOrigin: () => { return { message: 'Unrecognized domain', - } + }; }, noEthAccountsPermission: () => { return { message: `Origin does not have 'eth_accounts' permission`, - } + }; }, }, @@ -382,7 +382,7 @@ export const getters = deepFreeze({ return { name: 'Error', message: 'Selected account should be a non-empty string.', - } + }; }, }, @@ -390,7 +390,7 @@ export const getters = deepFreeze({ noPermsRequested: () => { return { message: 'Must request at least one permission.', - } + }; }, }, @@ -398,12 +398,12 @@ export const getters = deepFreeze({ rejection: () => { return { message: ethErrors.provider.userRejectedRequest().message, - } + }; }, methodNotFound: (methodName) => { return { message: `The method '${methodName}' does not exist / is not available.`, - } + }; }, }, @@ -411,7 +411,7 @@ export const getters = deepFreeze({ badOrigin: () => { return { message: 'Must provide non-empty string origin.', - } + }; }, }, @@ -419,7 +419,7 @@ export const getters = deepFreeze({ unauthorized: () => { return { code: 4100, - } + }; }, }, @@ -427,12 +427,12 @@ export const getters = deepFreeze({ duplicateOriginOrId: (id, origin) => { return { message: `Pending approval with id '${id}' or origin '${origin}' already exists.`, - } + }; }, requestAlreadyPending: (origin) => { return { message: `Request of type 'wallet_requestPermissions' already pending for origin ${origin}. Please wait.`, - } + }; }, }, @@ -440,7 +440,7 @@ export const getters = deepFreeze({ requestAlreadyPending: () => { return { message: 'Already processing eth_requestAccounts. Please wait.', - } + }; }, }, @@ -448,12 +448,12 @@ export const getters = deepFreeze({ invalidOrigin: (origin) => { return { message: `Invalid origin: '${origin}'`, - } + }; }, invalidAccounts: () => { return { message: 'Invalid accounts', - } + }; }, }, }, @@ -471,7 +471,7 @@ export const getters = deepFreeze({ return { method: NOTIFICATION_NAMES.accountsChanged, params: [], - } + }; }, /** @@ -484,7 +484,7 @@ export const getters = deepFreeze({ return { method: NOTIFICATION_NAMES.accountsChanged, params: accounts, - } + }; }, }, @@ -506,11 +506,11 @@ export const getters = deepFreeze({ origin, method, params, - } + }; if (id !== undefined) { - req.id = id + req.id = id; } - return req + return req; }, /** @@ -524,7 +524,7 @@ export const getters = deepFreeze({ origin, method: 'eth_accounts', params: [], - } + }; }, /** @@ -539,7 +539,7 @@ export const getters = deepFreeze({ origin, method: 'test_method', params: [param], - } + }; }, /** @@ -553,7 +553,7 @@ export const getters = deepFreeze({ origin, method: 'eth_requestAccounts', params: [], - } + }; }, /** @@ -569,7 +569,7 @@ export const getters = deepFreeze({ origin, method: 'wallet_requestPermissions', params: [PERMS.requests[permissionName]()], - } + }; }, /** @@ -585,7 +585,7 @@ export const getters = deepFreeze({ origin, method: 'wallet_requestPermissions', params: [permissions], - } + }; }, /** @@ -604,10 +604,10 @@ export const getters = deepFreeze({ ...args, name, }, - } + }; }, }, -}) +}); /** * Objects with immutable mock values. @@ -733,4 +733,4 @@ export const constants = deepFreeze({ }, ], }, -}) +}); diff --git a/test/unit/app/controllers/permissions/permissions-controller-test.js b/test/unit/app/controllers/permissions/permissions-controller-test.js index 2eee261f1..9fb2529a4 100644 --- a/test/unit/app/controllers/permissions/permissions-controller-test.js +++ b/test/unit/app/controllers/permissions/permissions-controller-test.js @@ -1,15 +1,15 @@ -import { strict as assert } from 'assert' -import { find } from 'lodash' -import sinon from 'sinon' +import { strict as assert } from 'assert'; +import { find } from 'lodash'; +import sinon from 'sinon'; import { METADATA_STORE_KEY, METADATA_CACHE_MAX_SIZE, -} from '../../../../../app/scripts/controllers/permissions/enums' +} from '../../../../../app/scripts/controllers/permissions/enums'; -import { PermissionsController } from '../../../../../app/scripts/controllers/permissions' +import { PermissionsController } from '../../../../../app/scripts/controllers/permissions'; -import { getRequestUserApprovalHelper, grantPermissions } from './helpers' +import { getRequestUserApprovalHelper, grantPermissions } from './helpers'; import { constants, @@ -17,9 +17,9 @@ import { getNotifyDomain, getNotifyAllDomains, getPermControllerOpts, -} from './mocks' +} from './mocks'; -const { ERRORS, NOTIFICATIONS, PERMS } = getters +const { ERRORS, NOTIFICATIONS, PERMS } = getters; const { ALL_ACCOUNTS, @@ -29,22 +29,22 @@ const { PERM_NAMES, REQUEST_IDS, EXTRA_ACCOUNT, -} = constants +} = constants; const initNotifications = () => { return Object.values(DOMAINS).reduce((acc, domain) => { - acc[domain.origin] = [] - return acc - }, {}) -} + acc[domain.origin] = []; + return acc; + }, {}); +}; const initPermController = (notifications = initNotifications()) => { return new PermissionsController({ ...getPermControllerOpts(), notifyDomain: getNotifyDomain(notifications), notifyAllDomains: getNotifyAllDomains(notifications), - }) -} + }); +}; describe('permissions controller', function () { describe('constructor', function () { @@ -52,393 +52,393 @@ describe('permissions controller', function () { assert.throws( () => new PermissionsController(), 'should throw on undefined argument', - ) - }) - }) + ); + }); + }); describe('getAccounts', function () { - let permController + let permController; beforeEach(function () { - permController = initPermController() + permController = initPermController(); grantPermissions( permController, DOMAINS.a.origin, PERMS.finalizedRequests.eth_accounts(ACCOUNTS.a.permitted), - ) + ); grantPermissions( permController, DOMAINS.b.origin, PERMS.finalizedRequests.eth_accounts(ACCOUNTS.b.permitted), - ) - }) + ); + }); it('gets permitted accounts for permitted origins', async function () { - const aAccounts = await permController.getAccounts(DOMAINS.a.origin) - const bAccounts = await permController.getAccounts(DOMAINS.b.origin) + const aAccounts = await permController.getAccounts(DOMAINS.a.origin); + const bAccounts = await permController.getAccounts(DOMAINS.b.origin); assert.deepEqual( aAccounts, [ACCOUNTS.a.primary], 'first origin should have correct accounts', - ) + ); assert.deepEqual( bAccounts, [ACCOUNTS.b.primary], 'second origin should have correct accounts', - ) - }) + ); + }); it('does not get accounts for unpermitted origins', async function () { - const cAccounts = await permController.getAccounts(DOMAINS.c.origin) - assert.deepEqual(cAccounts, [], 'origin should have no accounts') - }) + const cAccounts = await permController.getAccounts(DOMAINS.c.origin); + assert.deepEqual(cAccounts, [], 'origin should have no accounts'); + }); it('does not handle "metamask" origin as special case', async function () { - const metamaskAccounts = await permController.getAccounts('metamask') - assert.deepEqual(metamaskAccounts, [], 'origin should have no accounts') - }) - }) + const metamaskAccounts = await permController.getAccounts('metamask'); + assert.deepEqual(metamaskAccounts, [], 'origin should have no accounts'); + }); + }); describe('hasPermission', function () { it('returns correct values', async function () { - const permController = initPermController() + const permController = initPermController(); grantPermissions( permController, DOMAINS.a.origin, PERMS.finalizedRequests.eth_accounts(ACCOUNTS.a.permitted), - ) + ); grantPermissions( permController, DOMAINS.b.origin, PERMS.finalizedRequests.test_method(), - ) + ); assert.ok( permController.hasPermission(DOMAINS.a.origin, 'eth_accounts'), 'should return true for granted permission', - ) + ); assert.ok( permController.hasPermission(DOMAINS.b.origin, 'test_method'), 'should return true for granted permission', - ) + ); assert.ok( !permController.hasPermission(DOMAINS.a.origin, 'test_method'), 'should return false for non-granted permission', - ) + ); assert.ok( !permController.hasPermission(DOMAINS.b.origin, 'eth_accounts'), 'should return true for non-granted permission', - ) + ); assert.ok( !permController.hasPermission('foo', 'eth_accounts'), 'should return false for unknown origin', - ) + ); assert.ok( !permController.hasPermission(DOMAINS.b.origin, 'foo'), 'should return false for unknown permission', - ) - }) - }) + ); + }); + }); describe('clearPermissions', function () { it('notifies all appropriate domains and removes permissions', async function () { - const notifications = initNotifications() - const permController = initPermController(notifications) + const notifications = initNotifications(); + const permController = initPermController(notifications); grantPermissions( permController, DOMAINS.a.origin, PERMS.finalizedRequests.eth_accounts(ACCOUNTS.a.permitted), - ) + ); grantPermissions( permController, DOMAINS.b.origin, PERMS.finalizedRequests.eth_accounts(ACCOUNTS.b.permitted), - ) + ); grantPermissions( permController, DOMAINS.c.origin, PERMS.finalizedRequests.eth_accounts(ACCOUNTS.c.permitted), - ) + ); - let aAccounts = await permController.getAccounts(DOMAINS.a.origin) - let bAccounts = await permController.getAccounts(DOMAINS.b.origin) - let cAccounts = await permController.getAccounts(DOMAINS.c.origin) + let aAccounts = await permController.getAccounts(DOMAINS.a.origin); + let bAccounts = await permController.getAccounts(DOMAINS.b.origin); + let cAccounts = await permController.getAccounts(DOMAINS.c.origin); assert.deepEqual( aAccounts, [ACCOUNTS.a.primary], 'first origin should have correct accounts', - ) + ); assert.deepEqual( bAccounts, [ACCOUNTS.b.primary], 'second origin should have correct accounts', - ) + ); assert.deepEqual( cAccounts, [ACCOUNTS.c.primary], 'third origin should have correct accounts', - ) + ); - permController.clearPermissions() + permController.clearPermissions(); Object.keys(notifications).forEach((origin) => { assert.deepEqual( notifications[origin], [NOTIFICATIONS.removedAccounts()], 'origin should have single metamask_accountsChanged:[] notification', - ) - }) + ); + }); - aAccounts = await permController.getAccounts(DOMAINS.a.origin) - bAccounts = await permController.getAccounts(DOMAINS.b.origin) - cAccounts = await permController.getAccounts(DOMAINS.c.origin) + aAccounts = await permController.getAccounts(DOMAINS.a.origin); + bAccounts = await permController.getAccounts(DOMAINS.b.origin); + cAccounts = await permController.getAccounts(DOMAINS.c.origin); - assert.deepEqual(aAccounts, [], 'first origin should have no accounts') - assert.deepEqual(bAccounts, [], 'second origin should have no accounts') - assert.deepEqual(cAccounts, [], 'third origin should have no accounts') + assert.deepEqual(aAccounts, [], 'first origin should have no accounts'); + assert.deepEqual(bAccounts, [], 'second origin should have no accounts'); + assert.deepEqual(cAccounts, [], 'third origin should have no accounts'); Object.keys(notifications).forEach((origin) => { assert.deepEqual( permController.permissions.getPermissionsForDomain(origin), [], 'origin should have no permissions', - ) - }) + ); + }); assert.deepEqual( Object.keys(permController.permissions.getDomains()), [], 'all domains should be deleted', - ) - }) - }) + ); + }); + }); describe('removePermissionsFor', function () { - let permController, notifications + let permController, notifications; beforeEach(function () { - notifications = initNotifications() - permController = initPermController(notifications) + notifications = initNotifications(); + permController = initPermController(notifications); grantPermissions( permController, DOMAINS.a.origin, PERMS.finalizedRequests.eth_accounts(ACCOUNTS.a.permitted), - ) + ); grantPermissions( permController, DOMAINS.b.origin, PERMS.finalizedRequests.eth_accounts(ACCOUNTS.b.permitted), - ) - }) + ); + }); it('removes permissions for multiple domains', async function () { - let aAccounts = await permController.getAccounts(DOMAINS.a.origin) - let bAccounts = await permController.getAccounts(DOMAINS.b.origin) + let aAccounts = await permController.getAccounts(DOMAINS.a.origin); + let bAccounts = await permController.getAccounts(DOMAINS.b.origin); assert.deepEqual( aAccounts, [ACCOUNTS.a.primary], 'first origin should have correct accounts', - ) + ); assert.deepEqual( bAccounts, [ACCOUNTS.b.primary], 'second origin should have correct accounts', - ) + ); permController.removePermissionsFor({ [DOMAINS.a.origin]: [PERM_NAMES.eth_accounts], [DOMAINS.b.origin]: [PERM_NAMES.eth_accounts], - }) + }); - aAccounts = await permController.getAccounts(DOMAINS.a.origin) - bAccounts = await permController.getAccounts(DOMAINS.b.origin) + aAccounts = await permController.getAccounts(DOMAINS.a.origin); + bAccounts = await permController.getAccounts(DOMAINS.b.origin); - assert.deepEqual(aAccounts, [], 'first origin should have no accounts') - assert.deepEqual(bAccounts, [], 'second origin should have no accounts') + assert.deepEqual(aAccounts, [], 'first origin should have no accounts'); + assert.deepEqual(bAccounts, [], 'second origin should have no accounts'); assert.deepEqual( notifications[DOMAINS.a.origin], [NOTIFICATIONS.removedAccounts()], 'first origin should have correct notification', - ) + ); assert.deepEqual( notifications[DOMAINS.b.origin], [NOTIFICATIONS.removedAccounts()], 'second origin should have correct notification', - ) + ); assert.deepEqual( Object.keys(permController.permissions.getDomains()), [], 'all domains should be deleted', - ) - }) + ); + }); it('only removes targeted permissions from single domain', async function () { grantPermissions( permController, DOMAINS.b.origin, PERMS.finalizedRequests.test_method(), - ) + ); let bPermissions = permController.permissions.getPermissionsForDomain( DOMAINS.b.origin, - ) + ); assert.ok( bPermissions.length === 2 && find(bPermissions, { parentCapability: PERM_NAMES.eth_accounts }) && find(bPermissions, { parentCapability: PERM_NAMES.test_method }), 'origin should have correct permissions', - ) + ); permController.removePermissionsFor({ [DOMAINS.b.origin]: [PERM_NAMES.test_method], - }) + }); bPermissions = permController.permissions.getPermissionsForDomain( DOMAINS.b.origin, - ) + ); assert.ok( bPermissions.length === 1 && find(bPermissions, { parentCapability: PERM_NAMES.eth_accounts }), 'only targeted permission should have been removed', - ) - }) + ); + }); it('removes permissions for a single domain, without affecting another', async function () { permController.removePermissionsFor({ [DOMAINS.b.origin]: [PERM_NAMES.eth_accounts], - }) + }); - const aAccounts = await permController.getAccounts(DOMAINS.a.origin) - const bAccounts = await permController.getAccounts(DOMAINS.b.origin) + const aAccounts = await permController.getAccounts(DOMAINS.a.origin); + const bAccounts = await permController.getAccounts(DOMAINS.b.origin); assert.deepEqual( aAccounts, [ACCOUNTS.a.primary], 'first origin should have correct accounts', - ) - assert.deepEqual(bAccounts, [], 'second origin should have no accounts') + ); + assert.deepEqual(bAccounts, [], 'second origin should have no accounts'); assert.deepEqual( notifications[DOMAINS.a.origin], [], 'first origin should have no notifications', - ) + ); assert.deepEqual( notifications[DOMAINS.b.origin], [NOTIFICATIONS.removedAccounts()], 'second origin should have correct notification', - ) + ); assert.deepEqual( Object.keys(permController.permissions.getDomains()), [DOMAINS.a.origin], 'only first origin should remain', - ) - }) + ); + }); it('send notification but does not affect permissions for unknown domain', async function () { // it knows nothing of this origin permController.removePermissionsFor({ [DOMAINS.c.origin]: [PERM_NAMES.eth_accounts], - }) + }); assert.deepEqual( notifications[DOMAINS.c.origin], [NOTIFICATIONS.removedAccounts()], 'unknown origin should have notification', - ) + ); - const aAccounts = await permController.getAccounts(DOMAINS.a.origin) - const bAccounts = await permController.getAccounts(DOMAINS.b.origin) + const aAccounts = await permController.getAccounts(DOMAINS.a.origin); + const bAccounts = await permController.getAccounts(DOMAINS.b.origin); assert.deepEqual( aAccounts, [ACCOUNTS.a.primary], 'first origin should have correct accounts', - ) + ); assert.deepEqual( bAccounts, [ACCOUNTS.b.primary], 'second origin should have correct accounts', - ) + ); assert.deepEqual( Object.keys(permController.permissions.getDomains()), [DOMAINS.a.origin, DOMAINS.b.origin], 'should have correct domains', - ) - }) - }) + ); + }); + }); describe('validatePermittedAccounts', function () { - let permController + let permController; beforeEach(function () { - permController = initPermController() + permController = initPermController(); grantPermissions( permController, DOMAINS.a.origin, PERMS.finalizedRequests.eth_accounts(ACCOUNTS.a.permitted), - ) + ); grantPermissions( permController, DOMAINS.b.origin, PERMS.finalizedRequests.eth_accounts(ACCOUNTS.b.permitted), - ) - }) + ); + }); it('throws error on non-array accounts', async function () { await assert.throws( () => permController.validatePermittedAccounts(undefined), ERRORS.validatePermittedAccounts.invalidParam(), 'should throw on undefined', - ) + ); await assert.throws( () => permController.validatePermittedAccounts(false), ERRORS.validatePermittedAccounts.invalidParam(), 'should throw on false', - ) + ); await assert.throws( () => permController.validatePermittedAccounts(true), ERRORS.validatePermittedAccounts.invalidParam(), 'should throw on true', - ) + ); await assert.throws( () => permController.validatePermittedAccounts({}), ERRORS.validatePermittedAccounts.invalidParam(), 'should throw on non-array object', - ) - }) + ); + }); it('throws error on empty array of accounts', async function () { await assert.throws( () => permController.validatePermittedAccounts([]), ERRORS.validatePermittedAccounts.invalidParam(), 'should throw on empty array', - ) - }) + ); + }); it('throws error if any account value is not in keyring', async function () { - const keyringAccounts = await permController.getKeyringAccounts() + const keyringAccounts = await permController.getKeyringAccounts(); await assert.throws( () => permController.validatePermittedAccounts([DUMMY_ACCOUNT]), ERRORS.validatePermittedAccounts.nonKeyringAccount(DUMMY_ACCOUNT), 'should throw on non-keyring account', - ) + ); await assert.throws( () => @@ -447,54 +447,54 @@ describe('permissions controller', function () { ), ERRORS.validatePermittedAccounts.nonKeyringAccount(DUMMY_ACCOUNT), 'should throw on non-keyring account with other accounts', - ) - }) + ); + }); it('succeeds if all accounts are in keyring', async function () { - const keyringAccounts = await permController.getKeyringAccounts() + const keyringAccounts = await permController.getKeyringAccounts(); await assert.doesNotThrow( () => permController.validatePermittedAccounts(keyringAccounts), 'should not throw on all keyring accounts', - ) + ); await assert.doesNotThrow( () => permController.validatePermittedAccounts([keyringAccounts[0]]), 'should not throw on single keyring account', - ) + ); await assert.doesNotThrow( () => permController.validatePermittedAccounts([keyringAccounts[1]]), 'should not throw on single keyring account', - ) - }) - }) + ); + }); + }); describe('addPermittedAccount', function () { - let permController, notifications + let permController, notifications; beforeEach(function () { - notifications = initNotifications() - permController = initPermController(notifications) + notifications = initNotifications(); + permController = initPermController(notifications); grantPermissions( permController, DOMAINS.a.origin, PERMS.finalizedRequests.eth_accounts(ACCOUNTS.a.permitted), - ) + ); grantPermissions( permController, DOMAINS.b.origin, PERMS.finalizedRequests.eth_accounts(ACCOUNTS.b.permitted), - ) - }) + ); + }); it('should throw if account is not a string', async function () { await assert.rejects( () => permController.addPermittedAccount(DOMAINS.a.origin, {}), ERRORS.validatePermittedAccounts.nonKeyringAccount({}), 'should throw on non-string account param', - ) - }) + ); + }); it('should throw if given account is not in keyring', async function () { await assert.rejects( @@ -502,16 +502,16 @@ describe('permissions controller', function () { permController.addPermittedAccount(DOMAINS.a.origin, DUMMY_ACCOUNT), ERRORS.validatePermittedAccounts.nonKeyringAccount(DUMMY_ACCOUNT), 'should throw on non-keyring account', - ) - }) + ); + }); it('should throw if origin is invalid', async function () { await assert.rejects( () => permController.addPermittedAccount(false, EXTRA_ACCOUNT), ERRORS.addPermittedAccount.invalidOrigin(), 'should throw on invalid origin', - ) - }) + ); + }); it('should throw if origin lacks any permissions', async function () { await assert.rejects( @@ -519,23 +519,23 @@ describe('permissions controller', function () { permController.addPermittedAccount(DOMAINS.c.origin, EXTRA_ACCOUNT), ERRORS.addPermittedAccount.invalidOrigin(), 'should throw on origin without permissions', - ) - }) + ); + }); it('should throw if origin lacks eth_accounts permission', async function () { grantPermissions( permController, DOMAINS.c.origin, PERMS.finalizedRequests.test_method(), - ) + ); await assert.rejects( () => permController.addPermittedAccount(DOMAINS.c.origin, EXTRA_ACCOUNT), ERRORS.addPermittedAccount.noEthAccountsPermission(), 'should throw on origin without eth_accounts permission', - ) - }) + ); + }); it('should throw if account is already permitted', async function () { await assert.rejects( @@ -546,55 +546,55 @@ describe('permissions controller', function () { ), ERRORS.addPermittedAccount.alreadyPermitted(), 'should throw if account is already permitted', - ) - }) + ); + }); it('should successfully add permitted account', async function () { - await permController.addPermittedAccount(DOMAINS.a.origin, EXTRA_ACCOUNT) + await permController.addPermittedAccount(DOMAINS.a.origin, EXTRA_ACCOUNT); const accounts = await permController._getPermittedAccounts( DOMAINS.a.origin, - ) + ); assert.deepEqual( accounts, [...ACCOUNTS.a.permitted, EXTRA_ACCOUNT], 'origin should have correct accounts', - ) + ); assert.deepEqual( notifications[DOMAINS.a.origin][0], NOTIFICATIONS.newAccounts([ACCOUNTS.a.primary]), 'origin should have correct notification', - ) - }) - }) + ); + }); + }); describe('removePermittedAccount', function () { - let permController, notifications + let permController, notifications; beforeEach(function () { - notifications = initNotifications() - permController = initPermController(notifications) + notifications = initNotifications(); + permController = initPermController(notifications); grantPermissions( permController, DOMAINS.a.origin, PERMS.finalizedRequests.eth_accounts(ACCOUNTS.a.permitted), - ) + ); grantPermissions( permController, DOMAINS.b.origin, PERMS.finalizedRequests.eth_accounts(ACCOUNTS.b.permitted), - ) - }) + ); + }); it('should throw if account is not a string', async function () { await assert.rejects( () => permController.removePermittedAccount(DOMAINS.a.origin, {}), ERRORS.validatePermittedAccounts.nonKeyringAccount({}), 'should throw on non-string account param', - ) - }) + ); + }); it('should throw if given account is not in keyring', async function () { await assert.rejects( @@ -605,16 +605,16 @@ describe('permissions controller', function () { ), ERRORS.validatePermittedAccounts.nonKeyringAccount(DUMMY_ACCOUNT), 'should throw on non-keyring account', - ) - }) + ); + }); it('should throw if origin is invalid', async function () { await assert.rejects( () => permController.removePermittedAccount(false, EXTRA_ACCOUNT), ERRORS.removePermittedAccount.invalidOrigin(), 'should throw on invalid origin', - ) - }) + ); + }); it('should throw if origin lacks any permissions', async function () { await assert.rejects( @@ -625,15 +625,15 @@ describe('permissions controller', function () { ), ERRORS.removePermittedAccount.invalidOrigin(), 'should throw on origin without permissions', - ) - }) + ); + }); it('should throw if origin lacks eth_accounts permission', async function () { grantPermissions( permController, DOMAINS.c.origin, PERMS.finalizedRequests.test_method(), - ) + ); await assert.rejects( () => @@ -643,8 +643,8 @@ describe('permissions controller', function () { ), ERRORS.removePermittedAccount.noEthAccountsPermission(), 'should throw on origin without eth_accounts permission', - ) - }) + ); + }); it('should throw if account is not permitted', async function () { await assert.rejects( @@ -655,174 +655,174 @@ describe('permissions controller', function () { ), ERRORS.removePermittedAccount.notPermitted(), 'should throw if account is not permitted', - ) - }) + ); + }); it('should successfully remove permitted account', async function () { await permController.removePermittedAccount( DOMAINS.a.origin, ACCOUNTS.a.permitted[1], - ) + ); const accounts = await permController._getPermittedAccounts( DOMAINS.a.origin, - ) + ); assert.deepEqual( accounts, ACCOUNTS.a.permitted.filter((acc) => acc !== ACCOUNTS.a.permitted[1]), 'origin should have correct accounts', - ) + ); assert.deepEqual( notifications[DOMAINS.a.origin][0], NOTIFICATIONS.newAccounts([ACCOUNTS.a.primary]), 'origin should have correct notification', - ) - }) + ); + }); it('should remove eth_accounts permission if removing only permitted account', async function () { await permController.removePermittedAccount( DOMAINS.b.origin, ACCOUNTS.b.permitted[0], - ) + ); - const accounts = await permController.getAccounts(DOMAINS.b.origin) + const accounts = await permController.getAccounts(DOMAINS.b.origin); - assert.deepEqual(accounts, [], 'origin should have no accounts') + assert.deepEqual(accounts, [], 'origin should have no accounts'); const permission = await permController.permissions.getPermission( DOMAINS.b.origin, PERM_NAMES.eth_accounts, - ) + ); assert.equal( permission, undefined, 'origin should not have eth_accounts permission', - ) + ); assert.deepEqual( notifications[DOMAINS.b.origin][0], NOTIFICATIONS.removedAccounts(), 'origin should have correct notification', - ) - }) - }) + ); + }); + }); describe('removeAllAccountPermissions', function () { - let permController, notifications + let permController, notifications; beforeEach(function () { - notifications = initNotifications() - permController = initPermController(notifications) + notifications = initNotifications(); + permController = initPermController(notifications); grantPermissions( permController, DOMAINS.a.origin, PERMS.finalizedRequests.eth_accounts(ACCOUNTS.a.permitted), - ) + ); grantPermissions( permController, DOMAINS.b.origin, PERMS.finalizedRequests.eth_accounts(ACCOUNTS.b.permitted), - ) + ); grantPermissions( permController, DOMAINS.c.origin, PERMS.finalizedRequests.eth_accounts(ACCOUNTS.b.permitted), - ) - }) + ); + }); it('should throw if account is not a string', async function () { await assert.rejects( () => permController.removeAllAccountPermissions({}), ERRORS.validatePermittedAccounts.nonKeyringAccount({}), 'should throw on non-string account param', - ) - }) + ); + }); it('should throw if given account is not in keyring', async function () { await assert.rejects( () => permController.removeAllAccountPermissions(DUMMY_ACCOUNT), ERRORS.validatePermittedAccounts.nonKeyringAccount(DUMMY_ACCOUNT), 'should throw on non-keyring account', - ) - }) + ); + }); it('should remove permitted account from single origin', async function () { - await permController.removeAllAccountPermissions(ACCOUNTS.a.permitted[1]) + await permController.removeAllAccountPermissions(ACCOUNTS.a.permitted[1]); const accounts = await permController._getPermittedAccounts( DOMAINS.a.origin, - ) + ); assert.deepEqual( accounts, ACCOUNTS.a.permitted.filter((acc) => acc !== ACCOUNTS.a.permitted[1]), 'origin should have correct accounts', - ) + ); assert.deepEqual( notifications[DOMAINS.a.origin][0], NOTIFICATIONS.newAccounts([ACCOUNTS.a.primary]), 'origin should have correct notification', - ) - }) + ); + }); it('should permitted account from multiple origins', async function () { - await permController.removeAllAccountPermissions(ACCOUNTS.b.permitted[0]) + await permController.removeAllAccountPermissions(ACCOUNTS.b.permitted[0]); - const bAccounts = await permController.getAccounts(DOMAINS.b.origin) - assert.deepEqual(bAccounts, [], 'first origin should no accounts') + const bAccounts = await permController.getAccounts(DOMAINS.b.origin); + assert.deepEqual(bAccounts, [], 'first origin should no accounts'); - const cAccounts = await permController.getAccounts(DOMAINS.c.origin) - assert.deepEqual(cAccounts, [], 'second origin no accounts') + const cAccounts = await permController.getAccounts(DOMAINS.c.origin); + assert.deepEqual(cAccounts, [], 'second origin no accounts'); assert.deepEqual( notifications[DOMAINS.b.origin][0], NOTIFICATIONS.removedAccounts(), 'first origin should have correct notification', - ) + ); assert.deepEqual( notifications[DOMAINS.c.origin][0], NOTIFICATIONS.removedAccounts(), 'second origin should have correct notification', - ) - }) + ); + }); it('should remove eth_accounts permission if removing only permitted account', async function () { - await permController.removeAllAccountPermissions(ACCOUNTS.b.permitted[0]) + await permController.removeAllAccountPermissions(ACCOUNTS.b.permitted[0]); - const accounts = await permController.getAccounts(DOMAINS.b.origin) + const accounts = await permController.getAccounts(DOMAINS.b.origin); - assert.deepEqual(accounts, [], 'origin should have no accounts') + assert.deepEqual(accounts, [], 'origin should have no accounts'); const permission = await permController.permissions.getPermission( DOMAINS.b.origin, PERM_NAMES.eth_accounts, - ) + ); assert.equal( permission, undefined, 'origin should not have eth_accounts permission', - ) + ); assert.deepEqual( notifications[DOMAINS.b.origin][0], NOTIFICATIONS.removedAccounts(), 'origin should have correct notification', - ) - }) - }) + ); + }); + }); describe('finalizePermissionsRequest', function () { - let permController + let permController; beforeEach(function () { - permController = initPermController() - }) + permController = initPermController(); + }); it('throws on non-keyring accounts', async function () { await assert.rejects( @@ -832,71 +832,71 @@ describe('permissions controller', function () { ), ERRORS.validatePermittedAccounts.nonKeyringAccount(DUMMY_ACCOUNT), 'should throw on non-keyring account', - ) - }) + ); + }); it('adds caveat to eth_accounts permission', async function () { const perm = await permController.finalizePermissionsRequest( PERMS.requests.eth_accounts(), ACCOUNTS.a.permitted, - ) + ); assert.deepEqual( perm, PERMS.finalizedRequests.eth_accounts(ACCOUNTS.a.permitted), - ) - }) + ); + }); it('replaces caveat of eth_accounts permission', async function () { const perm = await permController.finalizePermissionsRequest( PERMS.finalizedRequests.eth_accounts(ACCOUNTS.a.permitted), ACCOUNTS.b.permitted, - ) + ); assert.deepEqual( perm, PERMS.finalizedRequests.eth_accounts(ACCOUNTS.b.permitted), 'permission should have correct caveat', - ) - }) + ); + }); it('handles non-eth_accounts permission', async function () { const perm = await permController.finalizePermissionsRequest( PERMS.finalizedRequests.test_method(), ACCOUNTS.b.permitted, - ) + ); assert.deepEqual( perm, PERMS.finalizedRequests.test_method(), 'permission should have correct caveat', - ) - }) - }) + ); + }); + }); describe('preferences state update', function () { - let permController, notifications, preferences, identities + let permController, notifications, preferences, identities; beforeEach(function () { identities = ALL_ACCOUNTS.reduce((identitiesAcc, account) => { - identitiesAcc[account] = {} - return identitiesAcc - }, {}) + identitiesAcc[account] = {}; + return identitiesAcc; + }, {}); preferences = { getState: sinon.stub(), subscribe: sinon.stub(), - } + }; preferences.getState.returns({ identities, selectedAddress: DUMMY_ACCOUNT, - }) - notifications = initNotifications() + }); + notifications = initNotifications(); permController = new PermissionsController({ ...getPermControllerOpts(), notifyDomain: getNotifyDomain(notifications), notifyAllDomains: getNotifyAllDomains(notifications), preferences, - }) + }); grantPermissions( permController, DOMAINS.b.origin, @@ -904,467 +904,467 @@ describe('permissions controller', function () { ...ACCOUNTS.a.permitted, EXTRA_ACCOUNT, ]), - ) + ); grantPermissions( permController, DOMAINS.c.origin, PERMS.finalizedRequests.eth_accounts(ACCOUNTS.a.permitted), - ) - }) + ); + }); it('should throw if given invalid account', async function () { - assert(preferences.subscribe.calledOnce) - assert(preferences.subscribe.firstCall.args.length === 1) - const onPreferencesUpdate = preferences.subscribe.firstCall.args[0] + assert(preferences.subscribe.calledOnce); + assert(preferences.subscribe.firstCall.args.length === 1); + const onPreferencesUpdate = preferences.subscribe.firstCall.args[0]; await assert.rejects( () => onPreferencesUpdate({ selectedAddress: {} }), ERRORS._handleAccountSelected.invalidParams(), 'should throw if account is not a string', - ) - }) + ); + }); it('should do nothing if account not permitted for any origins', async function () { - assert(preferences.subscribe.calledOnce) - assert(preferences.subscribe.firstCall.args.length === 1) - const onPreferencesUpdate = preferences.subscribe.firstCall.args[0] + assert(preferences.subscribe.calledOnce); + assert(preferences.subscribe.firstCall.args.length === 1); + const onPreferencesUpdate = preferences.subscribe.firstCall.args[0]; - await onPreferencesUpdate({ selectedAddress: DUMMY_ACCOUNT }) + await onPreferencesUpdate({ selectedAddress: DUMMY_ACCOUNT }); assert.deepEqual( notifications[DOMAINS.b.origin], [], 'should not have emitted notification', - ) + ); assert.deepEqual( notifications[DOMAINS.c.origin], [], 'should not have emitted notification', - ) - }) + ); + }); it('should emit notification if account already first in array for each connected site', async function () { - identities[ACCOUNTS.a.permitted[0]] = { lastSelected: 1000 } - assert(preferences.subscribe.calledOnce) - assert(preferences.subscribe.firstCall.args.length === 1) - const onPreferencesUpdate = preferences.subscribe.firstCall.args[0] + identities[ACCOUNTS.a.permitted[0]] = { lastSelected: 1000 }; + assert(preferences.subscribe.calledOnce); + assert(preferences.subscribe.firstCall.args.length === 1); + const onPreferencesUpdate = preferences.subscribe.firstCall.args[0]; - await onPreferencesUpdate({ selectedAddress: ACCOUNTS.a.permitted[0] }) + await onPreferencesUpdate({ selectedAddress: ACCOUNTS.a.permitted[0] }); assert.deepEqual( notifications[DOMAINS.b.origin], [NOTIFICATIONS.newAccounts([ACCOUNTS.a.primary])], 'should not have emitted notification', - ) + ); assert.deepEqual( notifications[DOMAINS.c.origin], [NOTIFICATIONS.newAccounts([ACCOUNTS.a.primary])], 'should not have emitted notification', - ) - }) + ); + }); it('should emit notification just for connected domains', async function () { - identities[EXTRA_ACCOUNT] = { lastSelected: 1000 } - assert(preferences.subscribe.calledOnce) - assert(preferences.subscribe.firstCall.args.length === 1) - const onPreferencesUpdate = preferences.subscribe.firstCall.args[0] + identities[EXTRA_ACCOUNT] = { lastSelected: 1000 }; + assert(preferences.subscribe.calledOnce); + assert(preferences.subscribe.firstCall.args.length === 1); + const onPreferencesUpdate = preferences.subscribe.firstCall.args[0]; - await onPreferencesUpdate({ selectedAddress: EXTRA_ACCOUNT }) + await onPreferencesUpdate({ selectedAddress: EXTRA_ACCOUNT }); assert.deepEqual( notifications[DOMAINS.b.origin], [NOTIFICATIONS.newAccounts([EXTRA_ACCOUNT])], 'should have emitted notification', - ) + ); assert.deepEqual( notifications[DOMAINS.c.origin], [], 'should not have emitted notification', - ) - }) + ); + }); it('should emit notification for multiple connected domains', async function () { - identities[ACCOUNTS.a.permitted[1]] = { lastSelected: 1000 } - assert(preferences.subscribe.calledOnce) - assert(preferences.subscribe.firstCall.args.length === 1) - const onPreferencesUpdate = preferences.subscribe.firstCall.args[0] + identities[ACCOUNTS.a.permitted[1]] = { lastSelected: 1000 }; + assert(preferences.subscribe.calledOnce); + assert(preferences.subscribe.firstCall.args.length === 1); + const onPreferencesUpdate = preferences.subscribe.firstCall.args[0]; - await onPreferencesUpdate({ selectedAddress: ACCOUNTS.a.permitted[1] }) + await onPreferencesUpdate({ selectedAddress: ACCOUNTS.a.permitted[1] }); assert.deepEqual( notifications[DOMAINS.b.origin], [NOTIFICATIONS.newAccounts([ACCOUNTS.a.permitted[1]])], 'should have emitted notification', - ) + ); assert.deepEqual( notifications[DOMAINS.c.origin], [NOTIFICATIONS.newAccounts([ACCOUNTS.c.primary])], 'should have emitted notification', - ) - }) - }) + ); + }); + }); describe('approvePermissionsRequest', function () { - let permController, requestUserApproval + let permController, requestUserApproval; beforeEach(function () { - permController = initPermController() - requestUserApproval = getRequestUserApprovalHelper(permController) - }) + permController = initPermController(); + requestUserApproval = getRequestUserApprovalHelper(permController); + }); it('does nothing if called on non-existing request', async function () { - sinon.spy(permController, 'finalizePermissionsRequest') + sinon.spy(permController, 'finalizePermissionsRequest'); - const request = PERMS.approvedRequest(REQUEST_IDS.a, null) + const request = PERMS.approvedRequest(REQUEST_IDS.a, null); await assert.doesNotReject( permController.approvePermissionsRequest(request, null), 'should not throw on non-existing request', - ) + ); assert.ok( permController.finalizePermissionsRequest.notCalled, 'should not call finalizePermissionRequest', - ) - }) + ); + }); it('rejects request with bad accounts param', async function () { const request = PERMS.approvedRequest( REQUEST_IDS.a, PERMS.requests.eth_accounts(), - ) + ); const rejectionPromise = assert.rejects( requestUserApproval(REQUEST_IDS.a), ERRORS.validatePermittedAccounts.invalidParam(), 'should reject with "null" accounts', - ) + ); - await permController.approvePermissionsRequest(request, null) - await rejectionPromise - }) + await permController.approvePermissionsRequest(request, null); + await rejectionPromise; + }); it('rejects request with no permissions', async function () { - const request = PERMS.approvedRequest(REQUEST_IDS.a, {}) + const request = PERMS.approvedRequest(REQUEST_IDS.a, {}); const requestRejection = assert.rejects( requestUserApproval(REQUEST_IDS.a), ERRORS.approvePermissionsRequest.noPermsRequested(), 'should reject if no permissions in request', - ) + ); await permController.approvePermissionsRequest( request, ACCOUNTS.a.permitted, - ) - await requestRejection - }) + ); + await requestRejection; + }); it('approves valid request', async function () { const request = PERMS.approvedRequest( REQUEST_IDS.a, PERMS.requests.eth_accounts(), - ) + ); - let perms + let perms; const requestApproval = assert.doesNotReject(async () => { - perms = await requestUserApproval(REQUEST_IDS.a) - }, 'should not reject single valid request') + perms = await requestUserApproval(REQUEST_IDS.a); + }, 'should not reject single valid request'); await permController.approvePermissionsRequest( request, ACCOUNTS.a.permitted, - ) - await requestApproval + ); + await requestApproval; assert.deepEqual( perms, PERMS.finalizedRequests.eth_accounts(ACCOUNTS.a.permitted), 'should produce expected approved permissions', - ) - }) + ); + }); it('approves valid requests regardless of order', async function () { const request1 = PERMS.approvedRequest( REQUEST_IDS.a, PERMS.requests.eth_accounts(), - ) + ); const request2 = PERMS.approvedRequest( REQUEST_IDS.b, PERMS.requests.eth_accounts(), - ) + ); const request3 = PERMS.approvedRequest( REQUEST_IDS.c, PERMS.requests.eth_accounts(), - ) + ); - let perms1, perms2 + let perms1, perms2; const approval1 = assert.doesNotReject(async () => { - perms1 = await requestUserApproval(REQUEST_IDS.a, DOMAINS.a.origin) - }, 'should not reject request') + perms1 = await requestUserApproval(REQUEST_IDS.a, DOMAINS.a.origin); + }, 'should not reject request'); const approval2 = assert.doesNotReject(async () => { - perms2 = await requestUserApproval(REQUEST_IDS.b, DOMAINS.b.origin) - }, 'should not reject request') + perms2 = await requestUserApproval(REQUEST_IDS.b, DOMAINS.b.origin); + }, 'should not reject request'); // approve out of order await permController.approvePermissionsRequest( request2, ACCOUNTS.b.permitted, - ) + ); // add a non-existing request to the mix await permController.approvePermissionsRequest( request3, ACCOUNTS.c.permitted, - ) + ); await permController.approvePermissionsRequest( request1, ACCOUNTS.a.permitted, - ) + ); - await approval1 - await approval2 + await approval1; + await approval2; assert.deepEqual( perms1, PERMS.finalizedRequests.eth_accounts(ACCOUNTS.a.permitted), 'first request should produce expected approved permissions', - ) + ); assert.deepEqual( perms2, PERMS.finalizedRequests.eth_accounts(ACCOUNTS.b.permitted), 'second request should produce expected approved permissions', - ) - }) - }) + ); + }); + }); describe('rejectPermissionsRequest', function () { - let permController, requestUserApproval + let permController, requestUserApproval; beforeEach(async function () { - permController = initPermController() - requestUserApproval = getRequestUserApprovalHelper(permController) - }) + permController = initPermController(); + requestUserApproval = getRequestUserApprovalHelper(permController); + }); it('does nothing if called on non-existing request', async function () { permController.approvals.add = sinon.fake.throws( new Error('should not call add'), - ) + ); await assert.doesNotReject( permController.rejectPermissionsRequest(REQUEST_IDS.a), 'should not throw on non-existing request', - ) - }) + ); + }); it('rejects single existing request', async function () { const requestRejection = assert.rejects( requestUserApproval(REQUEST_IDS.a), ERRORS.rejectPermissionsRequest.rejection(), 'should reject with expected error', - ) + ); - await permController.rejectPermissionsRequest(REQUEST_IDS.a) - await requestRejection - }) + await permController.rejectPermissionsRequest(REQUEST_IDS.a); + await requestRejection; + }); it('rejects requests regardless of order', async function () { const requestRejection1 = assert.rejects( requestUserApproval(REQUEST_IDS.b, DOMAINS.b.origin), ERRORS.rejectPermissionsRequest.rejection(), 'should reject with expected error', - ) + ); const requestRejection2 = assert.rejects( requestUserApproval(REQUEST_IDS.c, DOMAINS.c.origin), ERRORS.rejectPermissionsRequest.rejection(), 'should reject with expected error', - ) + ); // reject out of order - await permController.rejectPermissionsRequest(REQUEST_IDS.c) + await permController.rejectPermissionsRequest(REQUEST_IDS.c); // add a non-existing request to the mix - await permController.rejectPermissionsRequest(REQUEST_IDS.a) - await permController.rejectPermissionsRequest(REQUEST_IDS.b) + await permController.rejectPermissionsRequest(REQUEST_IDS.a); + await permController.rejectPermissionsRequest(REQUEST_IDS.b); - await requestRejection1 - await requestRejection2 - }) - }) + await requestRejection1; + await requestRejection2; + }); + }); // see permissions-middleware-test for testing the middleware itself describe('createMiddleware', function () { - let permController, clock + let permController, clock; beforeEach(function () { - permController = initPermController() - clock = sinon.useFakeTimers(1) - }) + permController = initPermController(); + clock = sinon.useFakeTimers(1); + }); afterEach(function () { - clock.restore() - }) + clock.restore(); + }); it('should throw on bad origin', function () { assert.throws( () => permController.createMiddleware({ origin: {} }), ERRORS.createMiddleware.badOrigin(), 'should throw expected error', - ) + ); assert.throws( () => permController.createMiddleware({ origin: '' }), ERRORS.createMiddleware.badOrigin(), 'should throw expected error', - ) + ); assert.throws( () => permController.createMiddleware({}), ERRORS.createMiddleware.badOrigin(), 'should throw expected error', - ) - }) + ); + }); it('should create a middleware', function () { - let middleware + let middleware; assert.doesNotThrow(() => { middleware = permController.createMiddleware({ origin: DOMAINS.a.origin, - }) - }, 'should not throw') + }); + }, 'should not throw'); - assert.equal(typeof middleware, 'function', 'should return function') - }) + assert.equal(typeof middleware, 'function', 'should return function'); + }); it('should create a middleware with extensionId', function () { - const extensionId = 'fooExtension' + const extensionId = 'fooExtension'; - let middleware + let middleware; assert.doesNotThrow(() => { middleware = permController.createMiddleware({ origin: DOMAINS.a.origin, extensionId, - }) - }, 'should not throw') + }); + }, 'should not throw'); - assert.equal(typeof middleware, 'function', 'should return function') + assert.equal(typeof middleware, 'function', 'should return function'); - const metadataStore = permController.store.getState()[METADATA_STORE_KEY] + const metadataStore = permController.store.getState()[METADATA_STORE_KEY]; assert.deepEqual( metadataStore[DOMAINS.a.origin], { extensionId, lastUpdated: 1 }, 'metadata should be stored', - ) - }) - }) + ); + }); + }); describe('notifyAccountsChanged', function () { - let notifications, permController + let notifications, permController; beforeEach(function () { - notifications = initNotifications() - permController = initPermController(notifications) - sinon.spy(permController.permissionsLog, 'updateAccountsHistory') - }) + notifications = initNotifications(); + permController = initPermController(notifications); + sinon.spy(permController.permissionsLog, 'updateAccountsHistory'); + }); it('notifyAccountsChanged records history and sends notification', async function () { - sinon.spy(permController, '_isUnlocked') + sinon.spy(permController, '_isUnlocked'); permController.notifyAccountsChanged( DOMAINS.a.origin, ACCOUNTS.a.permitted, - ) + ); assert.ok( permController._isUnlocked.calledOnce, '_isUnlocked should have been called once', - ) + ); assert.ok( permController.permissionsLog.updateAccountsHistory.calledOnce, 'permissionsLog.updateAccountsHistory should have been called once', - ) + ); assert.deepEqual( notifications[DOMAINS.a.origin], [NOTIFICATIONS.newAccounts(ACCOUNTS.a.permitted)], 'origin should have correct notification', - ) - }) + ); + }); it('notifyAccountsChanged does nothing if _isUnlocked returns false', async function () { - permController._isUnlocked = sinon.fake.returns(false) + permController._isUnlocked = sinon.fake.returns(false); permController.notifyAccountsChanged( DOMAINS.a.origin, ACCOUNTS.a.permitted, - ) + ); assert.ok( permController._isUnlocked.calledOnce, '_isUnlocked should have been called once', - ) + ); assert.ok( permController.permissionsLog.updateAccountsHistory.notCalled, 'permissionsLog.updateAccountsHistory should not have been called', - ) - }) + ); + }); it('notifyAccountsChanged throws on invalid origin', async function () { assert.throws( () => permController.notifyAccountsChanged(4, ACCOUNTS.a.permitted), ERRORS.notifyAccountsChanged.invalidOrigin(4), 'should throw expected error for non-string origin', - ) + ); assert.throws( () => permController.notifyAccountsChanged('', ACCOUNTS.a.permitted), ERRORS.notifyAccountsChanged.invalidOrigin(''), 'should throw expected error for empty string origin', - ) - }) + ); + }); it('notifyAccountsChanged throws on invalid accounts', async function () { assert.throws( () => permController.notifyAccountsChanged(DOMAINS.a.origin, 4), ERRORS.notifyAccountsChanged.invalidAccounts(), 'should throw expected error for truthy non-array accounts', - ) + ); assert.throws( () => permController.notifyAccountsChanged(DOMAINS.a.origin, null), ERRORS.notifyAccountsChanged.invalidAccounts(), 'should throw expected error for falsy non-array accounts', - ) - }) - }) + ); + }); + }); describe('addDomainMetadata', function () { - let permController, clock + let permController, clock; function getMockMetadata(size) { - const dummyData = {} + const dummyData = {}; for (let i = 0; i < size; i++) { - const key = i.toString() - dummyData[key] = {} + const key = i.toString(); + dummyData[key] = {}; } - return dummyData + return dummyData; } beforeEach(function () { - permController = initPermController() - permController._setDomainMetadata = sinon.fake() - clock = sinon.useFakeTimers(1) - }) + permController = initPermController(); + permController._setDomainMetadata = sinon.fake(); + clock = sinon.useFakeTimers(1); + }); afterEach(function () { - clock.restore() - }) + clock.restore(); + }); it('calls setter function with expected new state when adding domain', function () { permController.store.getState = sinon.fake.returns({ @@ -1373,19 +1373,19 @@ describe('permissions controller', function () { foo: 'bar', }, }, - }) + }); - permController.addDomainMetadata(DOMAINS.b.origin, { foo: 'bar' }) + permController.addDomainMetadata(DOMAINS.b.origin, { foo: 'bar' }); assert.ok( permController.store.getState.called, 'should have called store.getState', - ) + ); assert.equal( permController._setDomainMetadata.getCalls().length, 1, 'should have called _setDomainMetadata once', - ) + ); assert.deepEqual(permController._setDomainMetadata.lastCall.args, [ { [DOMAINS.a.origin]: { @@ -1397,8 +1397,8 @@ describe('permissions controller', function () { lastUpdated: 1, }, }, - ]) - }) + ]); + }); it('calls setter function with expected new states when updating existing domain', function () { permController.store.getState = sinon.fake.returns({ @@ -1410,19 +1410,19 @@ describe('permissions controller', function () { bar: 'baz', }, }, - }) + }); - permController.addDomainMetadata(DOMAINS.b.origin, { foo: 'bar' }) + permController.addDomainMetadata(DOMAINS.b.origin, { foo: 'bar' }); assert.ok( permController.store.getState.called, 'should have called store.getState', - ) + ); assert.equal( permController._setDomainMetadata.getCalls().length, 1, 'should have called _setDomainMetadata once', - ) + ); assert.deepEqual(permController._setDomainMetadata.lastCall.args, [ { [DOMAINS.a.origin]: { @@ -1435,31 +1435,31 @@ describe('permissions controller', function () { lastUpdated: 1, }, }, - ]) - }) + ]); + }); it('pops metadata on add when too many origins are pending', function () { - sinon.spy(permController._pendingSiteMetadata, 'delete') + sinon.spy(permController._pendingSiteMetadata, 'delete'); - const mockMetadata = getMockMetadata(METADATA_CACHE_MAX_SIZE) - const expectedDeletedOrigin = Object.keys(mockMetadata)[0] + const mockMetadata = getMockMetadata(METADATA_CACHE_MAX_SIZE); + const expectedDeletedOrigin = Object.keys(mockMetadata)[0]; permController.store.getState = sinon.fake.returns({ [METADATA_STORE_KEY]: { ...mockMetadata }, - }) + }); // populate permController._pendingSiteMetadata, as though these origins // were actually added Object.keys(mockMetadata).forEach((origin) => { - permController._pendingSiteMetadata.add(origin) - }) + permController._pendingSiteMetadata.add(origin); + }); - permController.addDomainMetadata(DOMAINS.a.origin, { foo: 'bar' }) + permController.addDomainMetadata(DOMAINS.a.origin, { foo: 'bar' }); assert.ok( permController.store.getState.called, 'should have called store.getState', - ) + ); const expectedMetadata = { ...mockMetadata, @@ -1468,71 +1468,71 @@ describe('permissions controller', function () { host: DOMAINS.a.host, lastUpdated: 1, }, - } - delete expectedMetadata[expectedDeletedOrigin] + }; + delete expectedMetadata[expectedDeletedOrigin]; assert.ok( permController._pendingSiteMetadata.delete.calledOnceWithExactly( expectedDeletedOrigin, ), 'should have called _pendingSiteMetadata.delete once', - ) + ); assert.equal( permController._setDomainMetadata.getCalls().length, 1, 'should have called _setDomainMetadata once', - ) + ); assert.deepEqual(permController._setDomainMetadata.lastCall.args, [ expectedMetadata, - ]) - }) - }) + ]); + }); + }); describe('_trimDomainMetadata', function () { - const permController = initPermController() + const permController = initPermController(); it('trims domain metadata for domains without permissions', function () { const metadataArg = { [DOMAINS.a.origin]: {}, [DOMAINS.b.origin]: {}, - } + }; permController.permissions.getDomains = sinon.fake.returns({ [DOMAINS.a.origin]: {}, - }) + }); - const metadataResult = permController._trimDomainMetadata(metadataArg) + const metadataResult = permController._trimDomainMetadata(metadataArg); assert.equal( permController.permissions.getDomains.getCalls().length, 1, 'should have called permissions.getDomains once', - ) + ); assert.deepEqual( metadataResult, { [DOMAINS.a.origin]: {}, }, 'should have produced expected state', - ) - }) - }) + ); + }); + }); describe('miscellanea and edge cases', function () { it('requestAccountsPermissionWithId calls _requestAccountsPermission with an explicit request ID', async function () { - const permController = initPermController() + const permController = initPermController(); const _requestPermissions = sinon .stub(permController, '_requestPermissions') - .resolves() - await permController.requestAccountsPermissionWithId('example.com') + .resolves(); + await permController.requestAccountsPermissionWithId('example.com'); assert.ok( _requestPermissions.calledOnceWithExactly( sinon.match.object.and(sinon.match.has('origin')), { eth_accounts: {} }, sinon.match.string.and(sinon.match.truthy), ), - ) - _requestPermissions.restore() - }) - }) -}) + ); + _requestPermissions.restore(); + }); + }); +}); diff --git a/test/unit/app/controllers/permissions/permissions-log-controller-test.js b/test/unit/app/controllers/permissions/permissions-log-controller-test.js index d98db8453..05ff47a37 100644 --- a/test/unit/app/controllers/permissions/permissions-log-controller-test.js +++ b/test/unit/app/controllers/permissions/permissions-log-controller-test.js @@ -1,20 +1,20 @@ -import { strict as assert } from 'assert' -import { ObservableStore } from '@metamask/obs-store' -import nanoid from 'nanoid' -import { useFakeTimers } from 'sinon' +import { strict as assert } from 'assert'; +import { ObservableStore } from '@metamask/obs-store'; +import nanoid from 'nanoid'; +import { useFakeTimers } from 'sinon'; -import PermissionsLogController from '../../../../../app/scripts/controllers/permissions/permissionsLog' +import PermissionsLogController from '../../../../../app/scripts/controllers/permissions/permissionsLog'; import { LOG_LIMIT, LOG_METHOD_TYPES, -} from '../../../../../app/scripts/controllers/permissions/enums' +} from '../../../../../app/scripts/controllers/permissions/enums'; -import { validateActivityEntry } from './helpers' +import { validateActivityEntry } from './helpers'; -import { constants, getters, noop } from './mocks' +import { constants, getters, noop } from './mocks'; -const { PERMS, RPC_REQUESTS } = getters +const { PERMS, RPC_REQUESTS } = getters; const { ACCOUNTS, @@ -23,174 +23,174 @@ const { PERM_NAMES, REQUEST_IDS, RESTRICTED_METHODS, -} = constants +} = constants; -let clock +let clock; const initPermLog = () => { return new PermissionsLogController({ store: new ObservableStore(), restrictedMethods: RESTRICTED_METHODS, - }) -} + }); +}; const mockNext = (handler) => { if (handler) { - handler(noop) + handler(noop); } -} +}; const initMiddleware = (permLog) => { - const middleware = permLog.createMiddleware() + const middleware = permLog.createMiddleware(); return (req, res, next = mockNext) => { - middleware(req, res, next) - } -} + middleware(req, res, next); + }; +}; const initClock = () => { // useFakeTimers, is in fact, not a react-hook // eslint-disable-next-line clock = useFakeTimers(1) -} +}; const tearDownClock = () => { - clock.restore() -} + clock.restore(); +}; const getSavedMockNext = (arr) => (handler) => { - arr.push(handler) -} + arr.push(handler); +}; describe('permissions log', function () { describe('activity log', function () { - let permLog, logMiddleware + let permLog, logMiddleware; beforeEach(function () { - permLog = initPermLog() - logMiddleware = initMiddleware(permLog) - }) + permLog = initPermLog(); + logMiddleware = initMiddleware(permLog); + }); it('records activity for restricted methods', function () { - let log, req, res + let log, req, res; // test_method, success - req = RPC_REQUESTS.test_method(DOMAINS.a.origin) - req.id = REQUEST_IDS.a - res = { foo: 'bar' } + req = RPC_REQUESTS.test_method(DOMAINS.a.origin); + req.id = REQUEST_IDS.a; + res = { foo: 'bar' }; - logMiddleware({ ...req }, res) + logMiddleware({ ...req }, res); - log = permLog.getActivityLog() - const entry1 = log[0] + log = permLog.getActivityLog(); + const entry1 = log[0]; - assert.equal(log.length, 1, 'log should have single entry') + assert.equal(log.length, 1, 'log should have single entry'); validateActivityEntry( entry1, { ...req }, { ...res }, LOG_METHOD_TYPES.restricted, true, - ) + ); // eth_accounts, failure - req = RPC_REQUESTS.eth_accounts(DOMAINS.b.origin) - req.id = REQUEST_IDS.b - res = { error: new Error('Unauthorized.') } + req = RPC_REQUESTS.eth_accounts(DOMAINS.b.origin); + req.id = REQUEST_IDS.b; + res = { error: new Error('Unauthorized.') }; - logMiddleware({ ...req }, res) + logMiddleware({ ...req }, res); - log = permLog.getActivityLog() - const entry2 = log[1] + log = permLog.getActivityLog(); + const entry2 = log[1]; - assert.equal(log.length, 2, 'log should have 2 entries') + assert.equal(log.length, 2, 'log should have 2 entries'); validateActivityEntry( entry2, { ...req }, { ...res }, LOG_METHOD_TYPES.restricted, false, - ) + ); // eth_requestAccounts, success - req = RPC_REQUESTS.eth_requestAccounts(DOMAINS.c.origin) - req.id = REQUEST_IDS.c - res = { result: ACCOUNTS.c.permitted } + req = RPC_REQUESTS.eth_requestAccounts(DOMAINS.c.origin); + req.id = REQUEST_IDS.c; + res = { result: ACCOUNTS.c.permitted }; - logMiddleware({ ...req }, res) + logMiddleware({ ...req }, res); - log = permLog.getActivityLog() - const entry3 = log[2] + log = permLog.getActivityLog(); + const entry3 = log[2]; - assert.equal(log.length, 3, 'log should have 3 entries') + assert.equal(log.length, 3, 'log should have 3 entries'); validateActivityEntry( entry3, { ...req }, { ...res }, LOG_METHOD_TYPES.restricted, true, - ) + ); // test_method, no response - req = RPC_REQUESTS.test_method(DOMAINS.a.origin) - req.id = REQUEST_IDS.a - res = null + req = RPC_REQUESTS.test_method(DOMAINS.a.origin); + req.id = REQUEST_IDS.a; + res = null; - logMiddleware({ ...req }, res) + logMiddleware({ ...req }, res); - log = permLog.getActivityLog() - const entry4 = log[3] + log = permLog.getActivityLog(); + const entry4 = log[3]; - assert.equal(log.length, 4, 'log should have 4 entries') + assert.equal(log.length, 4, 'log should have 4 entries'); validateActivityEntry( entry4, { ...req }, null, LOG_METHOD_TYPES.restricted, false, - ) + ); // validate final state - assert.equal(entry1, log[0], 'first log entry should remain') - assert.equal(entry2, log[1], 'second log entry should remain') - assert.equal(entry3, log[2], 'third log entry should remain') - assert.equal(entry4, log[3], 'fourth log entry should remain') - }) + assert.equal(entry1, log[0], 'first log entry should remain'); + assert.equal(entry2, log[1], 'second log entry should remain'); + assert.equal(entry3, log[2], 'third log entry should remain'); + assert.equal(entry4, log[3], 'fourth log entry should remain'); + }); it('handles responses added out of order', function () { - let log + let log; - const handlerArray = [] + const handlerArray = []; - const id1 = nanoid() - const id2 = nanoid() - const id3 = nanoid() + const id1 = nanoid(); + const id2 = nanoid(); + const id3 = nanoid(); - const req = RPC_REQUESTS.test_method(DOMAINS.a.origin) + const req = RPC_REQUESTS.test_method(DOMAINS.a.origin); // get make requests - req.id = id1 - const res1 = { foo: id1 } - logMiddleware({ ...req }, { ...res1 }, getSavedMockNext(handlerArray)) + req.id = id1; + const res1 = { foo: id1 }; + logMiddleware({ ...req }, { ...res1 }, getSavedMockNext(handlerArray)); - req.id = id2 - const res2 = { foo: id2 } - logMiddleware({ ...req }, { ...res2 }, getSavedMockNext(handlerArray)) + req.id = id2; + const res2 = { foo: id2 }; + logMiddleware({ ...req }, { ...res2 }, getSavedMockNext(handlerArray)); - req.id = id3 - const res3 = { foo: id3 } - logMiddleware({ ...req }, { ...res3 }, getSavedMockNext(handlerArray)) + req.id = id3; + const res3 = { foo: id3 }; + logMiddleware({ ...req }, { ...res3 }, getSavedMockNext(handlerArray)); // verify log state - log = permLog.getActivityLog() - assert.equal(log.length, 3, 'log should have 3 entries') - const entry1 = log[0] - const entry2 = log[1] - const entry3 = log[2] + log = permLog.getActivityLog(); + assert.equal(log.length, 3, 'log should have 3 entries'); + const entry1 = log[0]; + const entry2 = log[1]; + const entry3 = log[2]; assert.ok( entry1.id === id1 && entry1.response === null && @@ -199,19 +199,19 @@ describe('permissions log', function () { entry3.id === id3 && entry3.response === null, 'all entries should be in correct order and without responses', - ) + ); // call response handlers for (const i of [1, 2, 0]) { - handlerArray[i](noop) + handlerArray[i](noop); } // verify log state again - log = permLog.getActivityLog() - assert.equal(log.length, 3, 'log should have 3 entries') + log = permLog.getActivityLog(); + assert.equal(log.length, 3, 'log should have 3 entries'); // verify all entries - log = permLog.getActivityLog() + log = permLog.getActivityLog(); validateActivityEntry( log[0], @@ -219,7 +219,7 @@ describe('permissions log', function () { { ...res1 }, LOG_METHOD_TYPES.restricted, true, - ) + ); validateActivityEntry( log[1], @@ -227,7 +227,7 @@ describe('permissions log', function () { { ...res2 }, LOG_METHOD_TYPES.restricted, true, - ) + ); validateActivityEntry( log[2], @@ -235,90 +235,90 @@ describe('permissions log', function () { { ...res3 }, LOG_METHOD_TYPES.restricted, true, - ) - }) + ); + }); it('handles a lack of response', function () { - let req = RPC_REQUESTS.test_method(DOMAINS.a.origin) - req.id = REQUEST_IDS.a - let res = { foo: 'bar' } + let req = RPC_REQUESTS.test_method(DOMAINS.a.origin); + req.id = REQUEST_IDS.a; + let res = { foo: 'bar' }; // noop for next handler prevents recording of response - logMiddleware({ ...req }, res, noop) + logMiddleware({ ...req }, res, noop); - let log = permLog.getActivityLog() - const entry1 = log[0] + let log = permLog.getActivityLog(); + const entry1 = log[0]; - assert.equal(log.length, 1, 'log should have single entry') + assert.equal(log.length, 1, 'log should have single entry'); validateActivityEntry( entry1, { ...req }, null, LOG_METHOD_TYPES.restricted, true, - ) + ); // next request should be handled as normal - req = RPC_REQUESTS.eth_accounts(DOMAINS.b.origin) - req.id = REQUEST_IDS.b - res = { result: ACCOUNTS.b.permitted } + req = RPC_REQUESTS.eth_accounts(DOMAINS.b.origin); + req.id = REQUEST_IDS.b; + res = { result: ACCOUNTS.b.permitted }; - logMiddleware({ ...req }, res) + logMiddleware({ ...req }, res); - log = permLog.getActivityLog() - const entry2 = log[1] - assert.equal(log.length, 2, 'log should have 2 entries') + log = permLog.getActivityLog(); + const entry2 = log[1]; + assert.equal(log.length, 2, 'log should have 2 entries'); validateActivityEntry( entry2, { ...req }, { ...res }, LOG_METHOD_TYPES.restricted, true, - ) + ); // validate final state - assert.equal(entry1, log[0], 'first log entry remains') - assert.equal(entry2, log[1], 'second log entry remains') - }) + assert.equal(entry1, log[0], 'first log entry remains'); + assert.equal(entry2, log[1], 'second log entry remains'); + }); it('ignores expected methods', function () { - let log = permLog.getActivityLog() - assert.equal(log.length, 0, 'log should be empty') + let log = permLog.getActivityLog(); + assert.equal(log.length, 0, 'log should be empty'); - const res = { foo: 'bar' } + const res = { foo: 'bar' }; const req1 = RPC_REQUESTS.metamask_sendDomainMetadata( DOMAINS.c.origin, 'foobar', - ) - const req2 = RPC_REQUESTS.custom(DOMAINS.b.origin, 'eth_getBlockNumber') - const req3 = RPC_REQUESTS.custom(DOMAINS.b.origin, 'net_version') + ); + const req2 = RPC_REQUESTS.custom(DOMAINS.b.origin, 'eth_getBlockNumber'); + const req3 = RPC_REQUESTS.custom(DOMAINS.b.origin, 'net_version'); - logMiddleware(req1, res) - logMiddleware(req2, res) - logMiddleware(req3, res) + logMiddleware(req1, res); + logMiddleware(req2, res); + logMiddleware(req3, res); - log = permLog.getActivityLog() - assert.equal(log.length, 0, 'log should still be empty') - }) + log = permLog.getActivityLog(); + assert.equal(log.length, 0, 'log should still be empty'); + }); it('enforces log limit', function () { - const req = RPC_REQUESTS.test_method(DOMAINS.a.origin) - const res = { foo: 'bar' } + const req = RPC_REQUESTS.test_method(DOMAINS.a.origin); + const res = { foo: 'bar' }; // max out log - let lastId + let lastId; for (let i = 0; i < LOG_LIMIT; i++) { - lastId = nanoid() - logMiddleware({ ...req, id: lastId }, { ...res }) + lastId = nanoid(); + logMiddleware({ ...req, id: lastId }, { ...res }); } // check last entry valid - let log = permLog.getActivityLog() + let log = permLog.getActivityLog(); assert.equal( log.length, LOG_LIMIT, 'log should have LOG_LIMIT num entries', - ) + ); validateActivityEntry( log[LOG_LIMIT - 1], @@ -326,22 +326,22 @@ describe('permissions log', function () { res, LOG_METHOD_TYPES.restricted, true, - ) + ); // store the id of the current second entry - const nextFirstId = log[1].id + const nextFirstId = log[1].id; // add one more entry to log, putting it over the limit - lastId = nanoid() - logMiddleware({ ...req, id: lastId }, { ...res }) + lastId = nanoid(); + logMiddleware({ ...req, id: lastId }, { ...res }); // check log length - log = permLog.getActivityLog() + log = permLog.getActivityLog(); assert.equal( log.length, LOG_LIMIT, 'log should have LOG_LIMIT num entries', - ) + ); // check first and last entries validateActivityEntry( @@ -350,7 +350,7 @@ describe('permissions log', function () { res, LOG_METHOD_TYPES.restricted, true, - ) + ); validateActivityEntry( log[LOG_LIMIT - 1], @@ -358,122 +358,122 @@ describe('permissions log', function () { res, LOG_METHOD_TYPES.restricted, true, - ) - }) - }) + ); + }); + }); describe('permissions history', function () { - let permLog, logMiddleware + let permLog, logMiddleware; beforeEach(function () { - permLog = initPermLog() - logMiddleware = initMiddleware(permLog) - initClock() - }) + permLog = initPermLog(); + logMiddleware = initMiddleware(permLog); + initClock(); + }); afterEach(function () { - tearDownClock() - }) + tearDownClock(); + }); it('only updates history on responses', function () { - let permHistory + let permHistory; const req = RPC_REQUESTS.requestPermission( DOMAINS.a.origin, PERM_NAMES.test_method, - ) - const res = { result: [PERMS.granted.test_method()] } + ); + const res = { result: [PERMS.granted.test_method()] }; // noop => no response - logMiddleware({ ...req }, { ...res }, noop) + logMiddleware({ ...req }, { ...res }, noop); - permHistory = permLog.getHistory() - assert.deepEqual(permHistory, {}, 'history should not have been updated') + permHistory = permLog.getHistory(); + assert.deepEqual(permHistory, {}, 'history should not have been updated'); // response => records granted permissions - logMiddleware({ ...req }, { ...res }) + logMiddleware({ ...req }, { ...res }); - permHistory = permLog.getHistory() + permHistory = permLog.getHistory(); assert.equal( Object.keys(permHistory).length, 1, 'history should have single origin', - ) + ); assert.ok( Boolean(permHistory[DOMAINS.a.origin]), 'history should have expected origin', - ) - }) + ); + }); it('ignores malformed permissions requests', function () { const req = RPC_REQUESTS.requestPermission( DOMAINS.a.origin, PERM_NAMES.test_method, - ) - delete req.params - const res = { result: [PERMS.granted.test_method()] } + ); + delete req.params; + const res = { result: [PERMS.granted.test_method()] }; // no params => no response - logMiddleware({ ...req }, { ...res }) + logMiddleware({ ...req }, { ...res }); assert.deepEqual( permLog.getHistory(), {}, 'history should not have been updated', - ) - }) + ); + }); it('records and updates account history as expected', async function () { - let permHistory + let permHistory; const req = RPC_REQUESTS.requestPermission( DOMAINS.a.origin, PERM_NAMES.eth_accounts, - ) + ); const res = { result: [PERMS.granted.eth_accounts(ACCOUNTS.a.permitted)], - } + }; - logMiddleware({ ...req }, { ...res }) + logMiddleware({ ...req }, { ...res }); // validate history - permHistory = permLog.getHistory() + permHistory = permLog.getHistory(); assert.deepEqual( permHistory, EXPECTED_HISTORIES.case1[0], 'should have correct history', - ) + ); // mock permission requested again, with another approved account - clock.tick(1) + clock.tick(1); - res.result = [PERMS.granted.eth_accounts([ACCOUNTS.a.permitted[0]])] + res.result = [PERMS.granted.eth_accounts([ACCOUNTS.a.permitted[0]])]; - logMiddleware({ ...req }, { ...res }) + logMiddleware({ ...req }, { ...res }); - permHistory = permLog.getHistory() + permHistory = permLog.getHistory(); assert.deepEqual( permHistory, EXPECTED_HISTORIES.case1[1], 'should have correct history', - ) - }) + ); + }); it('handles eth_accounts response without caveats', async function () { const req = RPC_REQUESTS.requestPermission( DOMAINS.a.origin, PERM_NAMES.eth_accounts, - ) + ); const res = { result: [PERMS.granted.eth_accounts(ACCOUNTS.a.permitted)], - } - delete res.result[0].caveats + }; + delete res.result[0].caveats; - logMiddleware({ ...req }, { ...res }) + logMiddleware({ ...req }, { ...res }); // validate history @@ -481,20 +481,20 @@ describe('permissions log', function () { permLog.getHistory(), EXPECTED_HISTORIES.case2[0], 'should have expected history', - ) - }) + ); + }); it('handles extra caveats for eth_accounts', async function () { const req = RPC_REQUESTS.requestPermission( DOMAINS.a.origin, PERM_NAMES.eth_accounts, - ) + ); const res = { result: [PERMS.granted.eth_accounts(ACCOUNTS.a.permitted)], - } - res.result[0].caveats.push({ foo: 'bar' }) + }; + res.result[0].caveats.push({ foo: 'bar' }); - logMiddleware({ ...req }, { ...res }) + logMiddleware({ ...req }, { ...res }); // validate history @@ -502,8 +502,8 @@ describe('permissions log', function () { permLog.getHistory(), EXPECTED_HISTORIES.case1[0], 'should have correct history', - ) - }) + ); + }); // wallet_requestPermissions returns all permissions approved for the // requesting origin, including old ones @@ -511,15 +511,15 @@ describe('permissions log', function () { const req = RPC_REQUESTS.requestPermission( DOMAINS.a.origin, PERM_NAMES.eth_accounts, - ) + ); const res = { result: [ PERMS.granted.eth_accounts(ACCOUNTS.a.permitted), PERMS.granted.test_method(), ], - } + }; - logMiddleware({ ...req }, { ...res }) + logMiddleware({ ...req }, { ...res }); // validate history @@ -527,19 +527,19 @@ describe('permissions log', function () { permLog.getHistory(), EXPECTED_HISTORIES.case1[0], 'should have correct history', - ) - }) + ); + }); it('does not update history if no new permissions are approved', async function () { let req = RPC_REQUESTS.requestPermission( DOMAINS.a.origin, PERM_NAMES.test_method, - ) + ); let res = { result: [PERMS.granted.test_method()], - } + }; - logMiddleware({ ...req }, { ...res }) + logMiddleware({ ...req }, { ...res }); // validate history @@ -547,21 +547,21 @@ describe('permissions log', function () { permLog.getHistory(), EXPECTED_HISTORIES.case4[0], 'should have correct history', - ) + ); // new permission requested, but not approved - clock.tick(1) + clock.tick(1); req = RPC_REQUESTS.requestPermission( DOMAINS.a.origin, PERM_NAMES.eth_accounts, - ) + ); res = { result: [PERMS.granted.test_method()], - } + }; - logMiddleware({ ...req }, { ...res }) + logMiddleware({ ...req }, { ...res }); // validate history @@ -569,16 +569,16 @@ describe('permissions log', function () { permLog.getHistory(), EXPECTED_HISTORIES.case4[0], 'should have same history as before', - ) - }) + ); + }); it('records and updates history for multiple origins, regardless of response order', async function () { - let permHistory + let permHistory; // make first round of requests - const round1 = [] - const handlers1 = [] + const round1 = []; + const handlers1 = []; // first origin round1.push({ @@ -589,7 +589,7 @@ describe('permissions log', function () { res: { result: [PERMS.granted.test_method()], }, - }) + }); // second origin round1.push({ @@ -600,7 +600,7 @@ describe('permissions log', function () { res: { result: [PERMS.granted.eth_accounts(ACCOUNTS.b.permitted)], }, - }) + }); // third origin round1.push({ @@ -614,31 +614,31 @@ describe('permissions log', function () { PERMS.granted.eth_accounts(ACCOUNTS.c.permitted), ], }, - }) + }); // make requests and process responses out of order round1.forEach((x) => { - logMiddleware({ ...x.req }, { ...x.res }, getSavedMockNext(handlers1)) - }) + logMiddleware({ ...x.req }, { ...x.res }, getSavedMockNext(handlers1)); + }); for (const i of [1, 2, 0]) { - handlers1[i](noop) + handlers1[i](noop); } // validate history - permHistory = permLog.getHistory() + permHistory = permLog.getHistory(); assert.deepEqual( permHistory, EXPECTED_HISTORIES.case3[0], 'should have expected history', - ) + ); // make next round of requests - clock.tick(1) + clock.tick(1); - const round2 = [] + const round2 = []; // we're just gonna process these in order // first origin @@ -650,7 +650,7 @@ describe('permissions log', function () { res: { result: [PERMS.granted.test_method()], }, - }) + }); // nothing for second origin @@ -662,21 +662,21 @@ describe('permissions log', function () { res: { result: [PERMS.granted.eth_accounts(ACCOUNTS.b.permitted)], }, - }) + }); // make requests round2.forEach((x) => { - logMiddleware({ ...x.req }, { ...x.res }) - }) + logMiddleware({ ...x.req }, { ...x.res }); + }); // validate history - permHistory = permLog.getHistory() + permHistory = permLog.getHistory(); assert.deepEqual( permHistory, EXPECTED_HISTORIES.case3[1], 'should have expected history', - ) - }) - }) -}) + ); + }); + }); +}); diff --git a/test/unit/app/controllers/permissions/permissions-middleware-test.js b/test/unit/app/controllers/permissions/permissions-middleware-test.js index 9e2769ed6..acb89ac05 100644 --- a/test/unit/app/controllers/permissions/permissions-middleware-test.js +++ b/test/unit/app/controllers/permissions/permissions-middleware-test.js @@ -1,128 +1,128 @@ -import { strict as assert } from 'assert' -import sinon from 'sinon' +import { strict as assert } from 'assert'; +import sinon from 'sinon'; -import { METADATA_STORE_KEY } from '../../../../../app/scripts/controllers/permissions/enums' +import { METADATA_STORE_KEY } from '../../../../../app/scripts/controllers/permissions/enums'; -import { PermissionsController } from '../../../../../app/scripts/controllers/permissions' +import { PermissionsController } from '../../../../../app/scripts/controllers/permissions'; -import { getUserApprovalPromise, grantPermissions } from './helpers' +import { getUserApprovalPromise, grantPermissions } from './helpers'; import { constants, getters, getPermControllerOpts, getPermissionsMiddleware, -} from './mocks' +} from './mocks'; -const { CAVEATS, ERRORS, PERMS, RPC_REQUESTS } = getters +const { CAVEATS, ERRORS, PERMS, RPC_REQUESTS } = getters; -const { ACCOUNTS, DOMAINS, PERM_NAMES } = constants +const { ACCOUNTS, DOMAINS, PERM_NAMES } = constants; const initPermController = () => { return new PermissionsController({ ...getPermControllerOpts(), - }) -} + }); +}; const createApprovalSpies = (permController) => { - sinon.spy(permController.approvals, '_add') -} + sinon.spy(permController.approvals, '_add'); +}; const getNextApprovalId = (permController) => { - return permController.approvals._approvals.keys().next().value -} + return permController.approvals._approvals.keys().next().value; +}; const validatePermission = (perm, name, origin, caveats) => { assert.equal( name, perm.parentCapability, 'should have expected permission name', - ) - assert.equal(origin, perm.invoker, 'should have expected permission origin') + ); + assert.equal(origin, perm.invoker, 'should have expected permission origin'); if (caveats) { assert.deepEqual( caveats, perm.caveats, 'should have expected permission caveats', - ) + ); } else { - assert.ok(!perm.caveats, 'should not have any caveats') + assert.ok(!perm.caveats, 'should not have any caveats'); } -} +}; describe('permissions middleware', function () { describe('wallet_requestPermissions', function () { - let permController + let permController; beforeEach(function () { - permController = initPermController() - permController.notifyAccountsChanged = sinon.fake() - }) + permController = initPermController(); + permController.notifyAccountsChanged = sinon.fake(); + }); it('grants permissions on user approval', async function () { - createApprovalSpies(permController) + createApprovalSpies(permController); const aMiddleware = getPermissionsMiddleware( permController, DOMAINS.a.origin, - ) + ); const req = RPC_REQUESTS.requestPermission( DOMAINS.a.origin, PERM_NAMES.eth_accounts, - ) - const res = {} + ); + const res = {}; - const userApprovalPromise = getUserApprovalPromise(permController) + const userApprovalPromise = getUserApprovalPromise(permController); const pendingApproval = assert.doesNotReject( aMiddleware(req, res), 'should not reject permissions request', - ) + ); - await userApprovalPromise + await userApprovalPromise; assert.ok( permController.approvals._add.calledOnce, 'should have added single approval request', - ) + ); - const id = getNextApprovalId(permController) + const id = getNextApprovalId(permController); const approvedReq = PERMS.approvedRequest( id, PERMS.requests.eth_accounts(), - ) + ); await permController.approvePermissionsRequest( approvedReq, ACCOUNTS.a.permitted, - ) - await pendingApproval + ); + await pendingApproval; assert.ok( res.result && !res.error, 'response should have result and no error', - ) + ); assert.equal( res.result.length, 1, 'origin should have single approved permission', - ) + ); validatePermission( res.result[0], PERM_NAMES.eth_accounts, DOMAINS.a.origin, CAVEATS.eth_accounts(ACCOUNTS.a.permitted), - ) + ); - const aAccounts = await permController.getAccounts(DOMAINS.a.origin) + const aAccounts = await permController.getAccounts(DOMAINS.a.origin); assert.deepEqual( aAccounts, [ACCOUNTS.a.primary], 'origin should have correct accounts', - ) + ); assert.ok( permController.notifyAccountsChanged.calledOnceWith( @@ -130,71 +130,71 @@ describe('permissions middleware', function () { aAccounts, ), 'expected notification call should have been made', - ) - }) + ); + }); it('handles serial approved requests that overwrite existing permissions', async function () { const aMiddleware = getPermissionsMiddleware( permController, DOMAINS.a.origin, - ) + ); // create first request const req1 = RPC_REQUESTS.requestPermission( DOMAINS.a.origin, PERM_NAMES.eth_accounts, - ) - const res1 = {} + ); + const res1 = {}; // send, approve, and validate first request // note use of ACCOUNTS.a.permitted - let userApprovalPromise = getUserApprovalPromise(permController) + let userApprovalPromise = getUserApprovalPromise(permController); const pendingApproval1 = assert.doesNotReject( aMiddleware(req1, res1), 'should not reject permissions request', - ) + ); - await userApprovalPromise + await userApprovalPromise; - const id1 = getNextApprovalId(permController) + const id1 = getNextApprovalId(permController); const approvedReq1 = PERMS.approvedRequest( id1, PERMS.requests.eth_accounts(), - ) + ); await permController.approvePermissionsRequest( approvedReq1, ACCOUNTS.a.permitted, - ) - await pendingApproval1 + ); + await pendingApproval1; assert.ok( res1.result && !res1.error, 'response should have result and no error', - ) + ); assert.equal( res1.result.length, 1, 'origin should have single approved permission', - ) + ); validatePermission( res1.result[0], PERM_NAMES.eth_accounts, DOMAINS.a.origin, CAVEATS.eth_accounts(ACCOUNTS.a.permitted), - ) + ); - const accounts1 = await permController.getAccounts(DOMAINS.a.origin) + const accounts1 = await permController.getAccounts(DOMAINS.a.origin); assert.deepEqual( accounts1, [ACCOUNTS.a.primary], 'origin should have correct accounts', - ) + ); assert.ok( permController.notifyAccountsChanged.calledOnceWith( @@ -202,77 +202,77 @@ describe('permissions middleware', function () { accounts1, ), 'expected notification call should have been made', - ) + ); // create second request const requestedPerms2 = { ...PERMS.requests.eth_accounts(), ...PERMS.requests.test_method(), - } + }; const req2 = RPC_REQUESTS.requestPermissions(DOMAINS.a.origin, { ...requestedPerms2, - }) - const res2 = {} + }); + const res2 = {}; // send, approve, and validate second request // note use of ACCOUNTS.b.permitted - userApprovalPromise = getUserApprovalPromise(permController) + userApprovalPromise = getUserApprovalPromise(permController); const pendingApproval2 = assert.doesNotReject( aMiddleware(req2, res2), 'should not reject permissions request', - ) + ); - await userApprovalPromise + await userApprovalPromise; - const id2 = getNextApprovalId(permController) - const approvedReq2 = PERMS.approvedRequest(id2, { ...requestedPerms2 }) + const id2 = getNextApprovalId(permController); + const approvedReq2 = PERMS.approvedRequest(id2, { ...requestedPerms2 }); await permController.approvePermissionsRequest( approvedReq2, ACCOUNTS.b.permitted, - ) - await pendingApproval2 + ); + await pendingApproval2; assert.ok( res2.result && !res2.error, 'response should have result and no error', - ) + ); assert.equal( res2.result.length, 2, 'origin should have single approved permission', - ) + ); validatePermission( res2.result[0], PERM_NAMES.eth_accounts, DOMAINS.a.origin, CAVEATS.eth_accounts(ACCOUNTS.b.permitted), - ) + ); validatePermission( res2.result[1], PERM_NAMES.test_method, DOMAINS.a.origin, - ) + ); - const accounts2 = await permController.getAccounts(DOMAINS.a.origin) + const accounts2 = await permController.getAccounts(DOMAINS.a.origin); assert.deepEqual( accounts2, [ACCOUNTS.b.primary], 'origin should have correct accounts', - ) + ); assert.equal( permController.notifyAccountsChanged.callCount, 2, 'should have called notification method 2 times in total', - ) + ); assert.ok( permController.notifyAccountsChanged.lastCall.calledWith( @@ -280,155 +280,155 @@ describe('permissions middleware', function () { accounts2, ), 'expected notification call should have been made', - ) - }) + ); + }); it('rejects permissions on user rejection', async function () { - createApprovalSpies(permController) + createApprovalSpies(permController); const aMiddleware = getPermissionsMiddleware( permController, DOMAINS.a.origin, - ) + ); const req = RPC_REQUESTS.requestPermission( DOMAINS.a.origin, PERM_NAMES.eth_accounts, - ) - const res = {} + ); + const res = {}; - const expectedError = ERRORS.rejectPermissionsRequest.rejection() + const expectedError = ERRORS.rejectPermissionsRequest.rejection(); - const userApprovalPromise = getUserApprovalPromise(permController) + const userApprovalPromise = getUserApprovalPromise(permController); const requestRejection = assert.rejects( aMiddleware(req, res), expectedError, 'request should be rejected with correct error', - ) + ); - await userApprovalPromise + await userApprovalPromise; assert.ok( permController.approvals._add.calledOnce, 'should have added single approval request', - ) + ); - const id = getNextApprovalId(permController) + const id = getNextApprovalId(permController); - await permController.rejectPermissionsRequest(id) - await requestRejection + await permController.rejectPermissionsRequest(id); + await requestRejection; assert.ok( !res.result && res.error && res.error.message === expectedError.message, 'response should have expected error and no result', - ) + ); - const aAccounts = await permController.getAccounts(DOMAINS.a.origin) + const aAccounts = await permController.getAccounts(DOMAINS.a.origin); assert.deepEqual( aAccounts, [], 'origin should have have correct accounts', - ) + ); assert.ok( permController.notifyAccountsChanged.notCalled, 'should not have called notification method', - ) - }) + ); + }); it('rejects requests with unknown permissions', async function () { - createApprovalSpies(permController) + createApprovalSpies(permController); const aMiddleware = getPermissionsMiddleware( permController, DOMAINS.a.origin, - ) + ); const req = RPC_REQUESTS.requestPermissions(DOMAINS.a.origin, { ...PERMS.requests.does_not_exist(), ...PERMS.requests.test_method(), - }) - const res = {} + }); + const res = {}; const expectedError = ERRORS.rejectPermissionsRequest.methodNotFound( PERM_NAMES.does_not_exist, - ) + ); await assert.rejects( aMiddleware(req, res), expectedError, 'request should be rejected with correct error', - ) + ); assert.ok( permController.approvals._add.notCalled, 'no approval requests should have been added', - ) + ); assert.ok( !res.result && res.error && res.error.message === expectedError.message, 'response should have expected error and no result', - ) + ); assert.ok( permController.notifyAccountsChanged.notCalled, 'should not have called notification method', - ) - }) + ); + }); it('accepts only a single pending permissions request per origin', async function () { - createApprovalSpies(permController) + createApprovalSpies(permController); // two middlewares for two origins const aMiddleware = getPermissionsMiddleware( permController, DOMAINS.a.origin, - ) + ); const bMiddleware = getPermissionsMiddleware( permController, DOMAINS.b.origin, - ) + ); // create and start processing first request for first origin const reqA1 = RPC_REQUESTS.requestPermission( DOMAINS.a.origin, PERM_NAMES.test_method, - ) - const resA1 = {} + ); + const resA1 = {}; - let userApprovalPromise = getUserApprovalPromise(permController) + let userApprovalPromise = getUserApprovalPromise(permController); const requestApproval1 = assert.doesNotReject( aMiddleware(reqA1, resA1), 'should not reject permissions request', - ) + ); - await userApprovalPromise + await userApprovalPromise; // create and start processing first request for second origin const reqB1 = RPC_REQUESTS.requestPermission( DOMAINS.b.origin, PERM_NAMES.test_method, - ) - const resB1 = {} + ); + const resB1 = {}; - userApprovalPromise = getUserApprovalPromise(permController) + userApprovalPromise = getUserApprovalPromise(permController); const requestApproval2 = assert.doesNotReject( bMiddleware(reqB1, resB1), 'should not reject permissions request', - ) + ); - await userApprovalPromise + await userApprovalPromise; assert.ok( permController.approvals._add.calledTwice, 'should have added two approval requests', - ) + ); // create and start processing second request for first origin, // which should throw @@ -436,422 +436,422 @@ describe('permissions middleware', function () { const reqA2 = RPC_REQUESTS.requestPermission( DOMAINS.a.origin, PERM_NAMES.test_method, - ) - const resA2 = {} + ); + const resA2 = {}; - userApprovalPromise = getUserApprovalPromise(permController) + userApprovalPromise = getUserApprovalPromise(permController); const expectedError = ERRORS.pendingApprovals.requestAlreadyPending( DOMAINS.a.origin, - ) + ); const requestApprovalFail = assert.rejects( aMiddleware(reqA2, resA2), expectedError, 'request should be rejected with correct error', - ) + ); - await userApprovalPromise - await requestApprovalFail + await userApprovalPromise; + await requestApprovalFail; assert.ok( !resA2.result && resA2.error && resA2.error.message === expectedError.message, 'response should have expected error and no result', - ) + ); assert.equal( permController.approvals._add.callCount, 3, 'should have attempted to create three pending approvals', - ) + ); assert.equal( permController.approvals._approvals.size, 2, 'should only have created two pending approvals', - ) + ); // now, remaining pending requests should be approved without issue for (const id of permController.approvals._approvals.keys()) { await permController.approvePermissionsRequest( PERMS.approvedRequest(id, PERMS.requests.test_method()), - ) + ); } - await requestApproval1 - await requestApproval2 + await requestApproval1; + await requestApproval2; assert.ok( resA1.result && !resA1.error, 'first response should have result and no error', - ) + ); assert.equal( resA1.result.length, 1, 'first origin should have single approved permission', - ) + ); assert.ok( resB1.result && !resB1.error, 'second response should have result and no error', - ) + ); assert.equal( resB1.result.length, 1, 'second origin should have single approved permission', - ) - }) - }) + ); + }); + }); describe('restricted methods', function () { - let permController + let permController; beforeEach(function () { - permController = initPermController() - }) + permController = initPermController(); + }); it('prevents restricted method access for unpermitted domain', async function () { const aMiddleware = getPermissionsMiddleware( permController, DOMAINS.a.origin, - ) + ); - const req = RPC_REQUESTS.test_method(DOMAINS.a.origin) - const res = {} + const req = RPC_REQUESTS.test_method(DOMAINS.a.origin); + const res = {}; - const expectedError = ERRORS.rpcCap.unauthorized() + const expectedError = ERRORS.rpcCap.unauthorized(); await assert.rejects( aMiddleware(req, res), expectedError, 'request should be rejected with correct error', - ) + ); assert.ok( !res.result && res.error && res.error.code === expectedError.code, 'response should have expected error and no result', - ) - }) + ); + }); it('allows restricted method access for permitted domain', async function () { const bMiddleware = getPermissionsMiddleware( permController, DOMAINS.b.origin, - ) + ); grantPermissions( permController, DOMAINS.b.origin, PERMS.finalizedRequests.test_method(), - ) + ); - const req = RPC_REQUESTS.test_method(DOMAINS.b.origin, true) - const res = {} + const req = RPC_REQUESTS.test_method(DOMAINS.b.origin, true); + const res = {}; - await assert.doesNotReject(bMiddleware(req, res), 'should not reject') + await assert.doesNotReject(bMiddleware(req, res), 'should not reject'); assert.ok( res.result && res.result === 1, 'response should have correct result', - ) - }) - }) + ); + }); + }); describe('eth_accounts', function () { - let permController + let permController; beforeEach(function () { - permController = initPermController() - }) + permController = initPermController(); + }); it('returns empty array for non-permitted domain', async function () { const aMiddleware = getPermissionsMiddleware( permController, DOMAINS.a.origin, - ) + ); - const req = RPC_REQUESTS.eth_accounts(DOMAINS.a.origin) - const res = {} + const req = RPC_REQUESTS.eth_accounts(DOMAINS.a.origin); + const res = {}; - await assert.doesNotReject(aMiddleware(req, res), 'should not reject') + await assert.doesNotReject(aMiddleware(req, res), 'should not reject'); assert.ok( res.result && !res.error, 'response should have result and no error', - ) - assert.deepEqual(res.result, [], 'response should have correct result') - }) + ); + assert.deepEqual(res.result, [], 'response should have correct result'); + }); it('returns correct accounts for permitted domain', async function () { const aMiddleware = getPermissionsMiddleware( permController, DOMAINS.a.origin, - ) + ); grantPermissions( permController, DOMAINS.a.origin, PERMS.finalizedRequests.eth_accounts(ACCOUNTS.a.permitted), - ) + ); - const req = RPC_REQUESTS.eth_accounts(DOMAINS.a.origin) - const res = {} + const req = RPC_REQUESTS.eth_accounts(DOMAINS.a.origin); + const res = {}; - await assert.doesNotReject(aMiddleware(req, res), 'should not reject') + await assert.doesNotReject(aMiddleware(req, res), 'should not reject'); assert.ok( res.result && !res.error, 'response should have result and no error', - ) + ); assert.deepEqual( res.result, [ACCOUNTS.a.primary], 'response should have correct result', - ) - }) - }) + ); + }); + }); describe('eth_requestAccounts', function () { - let permController + let permController; beforeEach(function () { - permController = initPermController() - }) + permController = initPermController(); + }); it('requests accounts for unpermitted origin, and approves on user approval', async function () { - createApprovalSpies(permController) + createApprovalSpies(permController); - const userApprovalPromise = getUserApprovalPromise(permController) + const userApprovalPromise = getUserApprovalPromise(permController); const aMiddleware = getPermissionsMiddleware( permController, DOMAINS.a.origin, - ) + ); - const req = RPC_REQUESTS.eth_requestAccounts(DOMAINS.a.origin) - const res = {} + const req = RPC_REQUESTS.eth_requestAccounts(DOMAINS.a.origin); + const res = {}; const pendingApproval = assert.doesNotReject( aMiddleware(req, res), 'should not reject permissions request', - ) + ); - await userApprovalPromise + await userApprovalPromise; assert.ok( permController.approvals._add.calledOnce, 'should have added single approval request', - ) + ); - const id = getNextApprovalId(permController) + const id = getNextApprovalId(permController); const approvedReq = PERMS.approvedRequest( id, PERMS.requests.eth_accounts(), - ) + ); await permController.approvePermissionsRequest( approvedReq, ACCOUNTS.a.permitted, - ) + ); // wait for permission to be granted - await pendingApproval + await pendingApproval; const perms = permController.permissions.getPermissionsForDomain( DOMAINS.a.origin, - ) + ); assert.equal( perms.length, 1, 'domain should have correct number of permissions', - ) + ); validatePermission( perms[0], PERM_NAMES.eth_accounts, DOMAINS.a.origin, CAVEATS.eth_accounts(ACCOUNTS.a.permitted), - ) + ); // we should also see the accounts on the response assert.ok( res.result && !res.error, 'response should have result and no error', - ) + ); assert.deepEqual( res.result, [ACCOUNTS.a.primary], 'result should have correct accounts', - ) + ); // we should also be able to get the accounts independently - const aAccounts = await permController.getAccounts(DOMAINS.a.origin) + const aAccounts = await permController.getAccounts(DOMAINS.a.origin); assert.deepEqual( aAccounts, [ACCOUNTS.a.primary], 'origin should have have correct accounts', - ) - }) + ); + }); it('requests accounts for unpermitted origin, and rejects on user rejection', async function () { - createApprovalSpies(permController) + createApprovalSpies(permController); - const userApprovalPromise = getUserApprovalPromise(permController) + const userApprovalPromise = getUserApprovalPromise(permController); const aMiddleware = getPermissionsMiddleware( permController, DOMAINS.a.origin, - ) + ); - const req = RPC_REQUESTS.eth_requestAccounts(DOMAINS.a.origin) - const res = {} + const req = RPC_REQUESTS.eth_requestAccounts(DOMAINS.a.origin); + const res = {}; - const expectedError = ERRORS.rejectPermissionsRequest.rejection() + const expectedError = ERRORS.rejectPermissionsRequest.rejection(); const requestRejection = assert.rejects( aMiddleware(req, res), expectedError, 'request should be rejected with correct error', - ) + ); - await userApprovalPromise + await userApprovalPromise; assert.ok( permController.approvals._add.calledOnce, 'should have added single approval request', - ) + ); - const id = getNextApprovalId(permController) + const id = getNextApprovalId(permController); - await permController.rejectPermissionsRequest(id) - await requestRejection + await permController.rejectPermissionsRequest(id); + await requestRejection; assert.ok( !res.result && res.error && res.error.message === expectedError.message, 'response should have expected error and no result', - ) + ); - const aAccounts = await permController.getAccounts(DOMAINS.a.origin) + const aAccounts = await permController.getAccounts(DOMAINS.a.origin); assert.deepEqual( aAccounts, [], 'origin should have have correct accounts', - ) - }) + ); + }); it('directly returns accounts for permitted domain', async function () { const cMiddleware = getPermissionsMiddleware( permController, DOMAINS.c.origin, - ) + ); grantPermissions( permController, DOMAINS.c.origin, PERMS.finalizedRequests.eth_accounts(ACCOUNTS.c.permitted), - ) + ); - const req = RPC_REQUESTS.eth_requestAccounts(DOMAINS.c.origin) - const res = {} + const req = RPC_REQUESTS.eth_requestAccounts(DOMAINS.c.origin); + const res = {}; - await assert.doesNotReject(cMiddleware(req, res), 'should not reject') + await assert.doesNotReject(cMiddleware(req, res), 'should not reject'); assert.ok( res.result && !res.error, 'response should have result and no error', - ) + ); assert.deepEqual( res.result, [ACCOUNTS.c.primary], 'response should have correct result', - ) - }) + ); + }); it('rejects new requests when request already pending', async function () { - let unlock + let unlock; const unlockPromise = new Promise((resolve) => { - unlock = resolve - }) + unlock = resolve; + }); - permController.getUnlockPromise = () => unlockPromise + permController.getUnlockPromise = () => unlockPromise; const cMiddleware = getPermissionsMiddleware( permController, DOMAINS.c.origin, - ) + ); grantPermissions( permController, DOMAINS.c.origin, PERMS.finalizedRequests.eth_accounts(ACCOUNTS.c.permitted), - ) + ); - const req = RPC_REQUESTS.eth_requestAccounts(DOMAINS.c.origin) - const res = {} + const req = RPC_REQUESTS.eth_requestAccounts(DOMAINS.c.origin); + const res = {}; // this will block until we resolve the unlock Promise const requestApproval = assert.doesNotReject( cMiddleware(req, res), 'should not reject', - ) + ); // this will reject because of the already pending request await assert.rejects( cMiddleware({ ...req }, {}), ERRORS.eth_requestAccounts.requestAlreadyPending(DOMAINS.c.origin), - ) + ); // now unlock and let through the first request - unlock() + unlock(); - await requestApproval + await requestApproval; assert.ok( res.result && !res.error, 'response should have result and no error', - ) + ); assert.deepEqual( res.result, [ACCOUNTS.c.primary], 'response should have correct result', - ) - }) - }) + ); + }); + }); describe('metamask_sendDomainMetadata', function () { - let permController, clock + let permController, clock; beforeEach(function () { - permController = initPermController() - clock = sinon.useFakeTimers(1) - }) + permController = initPermController(); + clock = sinon.useFakeTimers(1); + }); afterEach(function () { - clock.restore() - }) + clock.restore(); + }); it('records domain metadata', async function () { - const name = 'BAZ' + const name = 'BAZ'; const cMiddleware = getPermissionsMiddleware( permController, DOMAINS.c.origin, - ) + ); const req = RPC_REQUESTS.metamask_sendDomainMetadata( DOMAINS.c.origin, name, - ) - const res = {} + ); + const res = {}; - await assert.doesNotReject(cMiddleware(req, res), 'should not reject') + await assert.doesNotReject(cMiddleware(req, res), 'should not reject'); - assert.ok(res.result, 'result should be true') + assert.ok(res.result, 'result should be true'); - const metadataStore = permController.store.getState()[METADATA_STORE_KEY] + const metadataStore = permController.store.getState()[METADATA_STORE_KEY]; assert.deepEqual( metadataStore, @@ -863,87 +863,87 @@ describe('permissions middleware', function () { }, }, 'metadata should have been added to store', - ) - }) + ); + }); it('records domain metadata and preserves extensionId', async function () { - const extensionId = 'fooExtension' + const extensionId = 'fooExtension'; - const name = 'BAZ' + const name = 'BAZ'; const cMiddleware = getPermissionsMiddleware( permController, DOMAINS.c.origin, extensionId, - ) + ); const req = RPC_REQUESTS.metamask_sendDomainMetadata( DOMAINS.c.origin, name, - ) - const res = {} + ); + const res = {}; - await assert.doesNotReject(cMiddleware(req, res), 'should not reject') + await assert.doesNotReject(cMiddleware(req, res), 'should not reject'); - assert.ok(res.result, 'result should be true') + assert.ok(res.result, 'result should be true'); - const metadataStore = permController.store.getState()[METADATA_STORE_KEY] + const metadataStore = permController.store.getState()[METADATA_STORE_KEY]; assert.deepEqual( metadataStore, { [DOMAINS.c.origin]: { name, extensionId, lastUpdated: 1 } }, 'metadata should have been added to store', - ) - }) + ); + }); it('should not record domain metadata if no name', async function () { - const name = null + const name = null; const cMiddleware = getPermissionsMiddleware( permController, DOMAINS.c.origin, - ) + ); const req = RPC_REQUESTS.metamask_sendDomainMetadata( DOMAINS.c.origin, name, - ) - const res = {} + ); + const res = {}; - await assert.doesNotReject(cMiddleware(req, res), 'should not reject') + await assert.doesNotReject(cMiddleware(req, res), 'should not reject'); - assert.ok(res.result, 'result should be true') + assert.ok(res.result, 'result should be true'); - const metadataStore = permController.store.getState()[METADATA_STORE_KEY] + const metadataStore = permController.store.getState()[METADATA_STORE_KEY]; assert.deepEqual( metadataStore, {}, 'metadata should not have been added to store', - ) - }) + ); + }); it('should not record domain metadata if no metadata', async function () { const cMiddleware = getPermissionsMiddleware( permController, DOMAINS.c.origin, - ) + ); - const req = RPC_REQUESTS.metamask_sendDomainMetadata(DOMAINS.c.origin) - delete req.domainMetadata - const res = {} + const req = RPC_REQUESTS.metamask_sendDomainMetadata(DOMAINS.c.origin); + delete req.domainMetadata; + const res = {}; - await assert.doesNotReject(cMiddleware(req, res), 'should not reject') + await assert.doesNotReject(cMiddleware(req, res), 'should not reject'); - assert.ok(res.result, 'result should be true') + assert.ok(res.result, 'result should be true'); - const metadataStore = permController.store.getState()[METADATA_STORE_KEY] + const metadataStore = permController.store.getState()[METADATA_STORE_KEY]; assert.deepEqual( metadataStore, {}, 'metadata should not have been added to store', - ) - }) - }) -}) + ); + }); + }); +}); diff --git a/test/unit/app/controllers/permissions/restricted-methods-test.js b/test/unit/app/controllers/permissions/restricted-methods-test.js index 2b7361110..a5cf3dc0b 100644 --- a/test/unit/app/controllers/permissions/restricted-methods-test.js +++ b/test/unit/app/controllers/permissions/restricted-methods-test.js @@ -1,137 +1,137 @@ -import { strict as assert } from 'assert' -import pify from 'pify' +import { strict as assert } from 'assert'; +import pify from 'pify'; -import getRestrictedMethods from '../../../../../app/scripts/controllers/permissions/restrictedMethods' +import getRestrictedMethods from '../../../../../app/scripts/controllers/permissions/restrictedMethods'; describe('restricted methods', function () { describe('eth_accounts', function () { it('should handle getKeyringAccounts error', async function () { const restrictedMethods = getRestrictedMethods({ getKeyringAccounts: async () => { - throw new Error('foo') + throw new Error('foo'); }, - }) - const ethAccountsMethod = pify(restrictedMethods.eth_accounts.method) + }); + const ethAccountsMethod = pify(restrictedMethods.eth_accounts.method); - const res = {} - const fooError = new Error('foo') + const res = {}; + const fooError = new Error('foo'); await assert.rejects( ethAccountsMethod(null, res, null), fooError, 'Should reject with expected error', - ) + ); assert.deepEqual( res, { error: fooError }, 'response should have expected error and no result', - ) - }) + ); + }); it('should handle missing identity for first account when sorting', async function () { const restrictedMethods = getRestrictedMethods({ getIdentities: () => { - return { '0x7e57e2': {} } + return { '0x7e57e2': {} }; }, getKeyringAccounts: async () => ['0x7e57e2', '0x7e57e3'], - }) - const ethAccountsMethod = pify(restrictedMethods.eth_accounts.method) + }); + const ethAccountsMethod = pify(restrictedMethods.eth_accounts.method); - const res = {} - await assert.rejects(ethAccountsMethod(null, res, null)) - assert.ok(res.error instanceof Error, 'result should have error') + const res = {}; + await assert.rejects(ethAccountsMethod(null, res, null)); + assert.ok(res.error instanceof Error, 'result should have error'); assert.deepEqual( Object.keys(res), ['error'], 'result should only contain error', - ) - }) + ); + }); it('should handle missing identity for second account when sorting', async function () { const restrictedMethods = getRestrictedMethods({ getIdentities: () => { - return { '0x7e57e3': {} } + return { '0x7e57e3': {} }; }, getKeyringAccounts: async () => ['0x7e57e2', '0x7e57e3'], - }) - const ethAccountsMethod = pify(restrictedMethods.eth_accounts.method) + }); + const ethAccountsMethod = pify(restrictedMethods.eth_accounts.method); - const res = {} - await assert.rejects(ethAccountsMethod(null, res, null)) - assert.ok(res.error instanceof Error, 'result should have error') + const res = {}; + await assert.rejects(ethAccountsMethod(null, res, null)); + assert.ok(res.error instanceof Error, 'result should have error'); assert.deepEqual( Object.keys(res), ['error'], 'result should only contain error', - ) - }) + ); + }); it('should return accounts in keyring order when none are selected', async function () { - const keyringAccounts = ['0x7e57e2', '0x7e57e3', '0x7e57e4', '0x7e57e5'] + const keyringAccounts = ['0x7e57e2', '0x7e57e3', '0x7e57e4', '0x7e57e5']; const restrictedMethods = getRestrictedMethods({ getIdentities: () => { return keyringAccounts.reduce((identities, address) => { - identities[address] = {} - return identities - }, {}) + identities[address] = {}; + return identities; + }, {}); }, getKeyringAccounts: async () => [...keyringAccounts], - }) - const ethAccountsMethod = pify(restrictedMethods.eth_accounts.method) + }); + const ethAccountsMethod = pify(restrictedMethods.eth_accounts.method); - const res = {} - await ethAccountsMethod(null, res, null) + const res = {}; + await ethAccountsMethod(null, res, null); assert.deepEqual( res, { result: keyringAccounts }, 'should return accounts in correct order', - ) - }) + ); + }); it('should return accounts in keyring order when all have same last selected time', async function () { - const keyringAccounts = ['0x7e57e2', '0x7e57e3', '0x7e57e4', '0x7e57e5'] + const keyringAccounts = ['0x7e57e2', '0x7e57e3', '0x7e57e4', '0x7e57e5']; const restrictedMethods = getRestrictedMethods({ getIdentities: () => { return keyringAccounts.reduce((identities, address) => { - identities[address] = { lastSelected: 1000 } - return identities - }, {}) + identities[address] = { lastSelected: 1000 }; + return identities; + }, {}); }, getKeyringAccounts: async () => [...keyringAccounts], - }) - const ethAccountsMethod = pify(restrictedMethods.eth_accounts.method) + }); + const ethAccountsMethod = pify(restrictedMethods.eth_accounts.method); - const res = {} - await ethAccountsMethod(null, res, null) + const res = {}; + await ethAccountsMethod(null, res, null); assert.deepEqual( res, { result: keyringAccounts }, 'should return accounts in correct order', - ) - }) + ); + }); it('should return accounts sorted by last selected (descending)', async function () { - const keyringAccounts = ['0x7e57e2', '0x7e57e3', '0x7e57e4', '0x7e57e5'] - const expectedResult = keyringAccounts.slice().reverse() + const keyringAccounts = ['0x7e57e2', '0x7e57e3', '0x7e57e4', '0x7e57e5']; + const expectedResult = keyringAccounts.slice().reverse(); const restrictedMethods = getRestrictedMethods({ getIdentities: () => { return keyringAccounts.reduce((identities, address, index) => { - identities[address] = { lastSelected: index * 1000 } - return identities - }, {}) + identities[address] = { lastSelected: index * 1000 }; + return identities; + }, {}); }, getKeyringAccounts: async () => [...keyringAccounts], - }) - const ethAccountsMethod = pify(restrictedMethods.eth_accounts.method) + }); + const ethAccountsMethod = pify(restrictedMethods.eth_accounts.method); - const res = {} - await ethAccountsMethod(null, res, null) + const res = {}; + await ethAccountsMethod(null, res, null); assert.deepEqual( res, { result: expectedResult }, 'should return accounts in correct order', - ) - }) + ); + }); it('should return accounts sorted by last selected (descending) with unselected accounts last, in keyring order', async function () { const keyringAccounts = [ @@ -140,14 +140,14 @@ describe('restricted methods', function () { '0x7e57e4', '0x7e57e5', '0x7e57e6', - ] + ]; const expectedResult = [ '0x7e57e4', '0x7e57e2', '0x7e57e3', '0x7e57e5', '0x7e57e6', - ] + ]; const restrictedMethods = getRestrictedMethods({ getIdentities: () => { return { @@ -156,19 +156,19 @@ describe('restricted methods', function () { '0x7e57e4': { lastSelected: 2000 }, '0x7e57e5': {}, '0x7e57e6': {}, - } + }; }, getKeyringAccounts: async () => [...keyringAccounts], - }) - const ethAccountsMethod = pify(restrictedMethods.eth_accounts.method) + }); + const ethAccountsMethod = pify(restrictedMethods.eth_accounts.method); - const res = {} - await ethAccountsMethod(null, res, null) + const res = {}; + await ethAccountsMethod(null, res, null); assert.deepEqual( res, { result: expectedResult }, 'should return accounts in correct order', - ) - }) - }) -}) + ); + }); + }); +}); diff --git a/test/unit/app/controllers/preferences-controller-test.js b/test/unit/app/controllers/preferences-controller-test.js index 065d35782..d2a85d12c 100644 --- a/test/unit/app/controllers/preferences-controller-test.js +++ b/test/unit/app/controllers/preferences-controller-test.js @@ -1,30 +1,30 @@ -import assert from 'assert' -import { ObservableStore } from '@metamask/obs-store' -import sinon from 'sinon' -import PreferencesController from '../../../../app/scripts/controllers/preferences' +import assert from 'assert'; +import { ObservableStore } from '@metamask/obs-store'; +import sinon from 'sinon'; +import PreferencesController from '../../../../app/scripts/controllers/preferences'; describe('preferences controller', function () { - let preferencesController - let network - const migrateAddressBookState = sinon.stub() + let preferencesController; + let network; + const migrateAddressBookState = sinon.stub(); beforeEach(function () { - network = { providerStore: new ObservableStore({ type: 'mainnet' }) } + network = { providerStore: new ObservableStore({ type: 'mainnet' }) }; preferencesController = new PreferencesController({ migrateAddressBookState, network, - }) - }) + }); + }); afterEach(function () { - sinon.restore() - }) + sinon.restore(); + }); describe('setAddresses', function () { it('should keep a map of addresses to names and addresses in the store', function () { - preferencesController.setAddresses(['0xda22le', '0x7e57e2']) + preferencesController.setAddresses(['0xda22le', '0x7e57e2']); - const { identities } = preferencesController.store.getState() + const { identities } = preferencesController.store.getState(); assert.deepEqual(identities, { '0xda22le': { name: 'Account 1', @@ -34,25 +34,25 @@ describe('preferences controller', function () { name: 'Account 2', address: '0x7e57e2', }, - }) - }) + }); + }); it('should create account tokens for each account in the store', function () { - preferencesController.setAddresses(['0xda22le', '0x7e57e2']) + preferencesController.setAddresses(['0xda22le', '0x7e57e2']); - const { accountTokens } = preferencesController.store.getState() + const { accountTokens } = preferencesController.store.getState(); assert.deepEqual(accountTokens, { '0xda22le': {}, '0x7e57e2': {}, - }) - }) + }); + }); it('should replace its list of addresses', function () { - preferencesController.setAddresses(['0xda22le', '0x7e57e2']) - preferencesController.setAddresses(['0xda22le77', '0x7e57e277']) + preferencesController.setAddresses(['0xda22le', '0x7e57e2']); + preferencesController.setAddresses(['0xda22le77', '0x7e57e277']); - const { identities } = preferencesController.store.getState() + const { identities } = preferencesController.store.getState(); assert.deepEqual(identities, { '0xda22le77': { name: 'Account 1', @@ -62,46 +62,46 @@ describe('preferences controller', function () { name: 'Account 2', address: '0x7e57e277', }, - }) - }) - }) + }); + }); + }); describe('removeAddress', function () { it('should remove an address from state', function () { - preferencesController.setAddresses(['0xda22le', '0x7e57e2']) + preferencesController.setAddresses(['0xda22le', '0x7e57e2']); - preferencesController.removeAddress('0xda22le') + preferencesController.removeAddress('0xda22le'); assert.equal( preferencesController.store.getState().identities['0xda22le'], undefined, - ) - }) + ); + }); it('should remove an address from state and respective tokens', function () { - preferencesController.setAddresses(['0xda22le', '0x7e57e2']) + preferencesController.setAddresses(['0xda22le', '0x7e57e2']); - preferencesController.removeAddress('0xda22le') + preferencesController.removeAddress('0xda22le'); assert.equal( preferencesController.store.getState().accountTokens['0xda22le'], undefined, - ) - }) + ); + }); it('should switch accounts if the selected address is removed', function () { - preferencesController.setAddresses(['0xda22le', '0x7e57e2']) + preferencesController.setAddresses(['0xda22le', '0x7e57e2']); - preferencesController.setSelectedAddress('0x7e57e2') - preferencesController.removeAddress('0x7e57e2') + preferencesController.setSelectedAddress('0x7e57e2'); + preferencesController.removeAddress('0x7e57e2'); - assert.equal(preferencesController.getSelectedAddress(), '0xda22le') - }) - }) + assert.equal(preferencesController.getSelectedAddress(), '0xda22le'); + }); + }); describe('setAccountLabel', function () { it('should update a label for the given account', function () { - preferencesController.setAddresses(['0xda22le', '0x7e57e2']) + preferencesController.setAddresses(['0xda22le', '0x7e57e2']); assert.deepEqual( preferencesController.store.getState().identities['0xda22le'], @@ -109,408 +109,412 @@ describe('preferences controller', function () { name: 'Account 1', address: '0xda22le', }, - ) + ); - preferencesController.setAccountLabel('0xda22le', 'Dazzle') + preferencesController.setAccountLabel('0xda22le', 'Dazzle'); assert.deepEqual( preferencesController.store.getState().identities['0xda22le'], { name: 'Dazzle', address: '0xda22le', }, - ) - }) - }) + ); + }); + }); describe('getTokens', function () { it('should return an empty list initially', async function () { - preferencesController.setAddresses(['0x7e57e2']) - await preferencesController.setSelectedAddress('0x7e57e2') + preferencesController.setAddresses(['0x7e57e2']); + await preferencesController.setSelectedAddress('0x7e57e2'); - const tokens = preferencesController.getTokens() - assert.equal(tokens.length, 0, 'empty list of tokens') - }) - }) + const tokens = preferencesController.getTokens(); + assert.equal(tokens.length, 0, 'empty list of tokens'); + }); + }); describe('addToken', function () { it('should add that token to its state', async function () { - const address = '0xabcdef1234567' - const symbol = 'ABBR' - const decimals = 5 + const address = '0xabcdef1234567'; + const symbol = 'ABBR'; + const decimals = 5; - preferencesController.setAddresses(['0x7e57e2']) - await preferencesController.setSelectedAddress('0x7e57e2') - await preferencesController.addToken(address, symbol, decimals) + preferencesController.setAddresses(['0x7e57e2']); + await preferencesController.setSelectedAddress('0x7e57e2'); + await preferencesController.addToken(address, symbol, decimals); - const tokens = preferencesController.getTokens() - assert.equal(tokens.length, 1, 'one token added') + const tokens = preferencesController.getTokens(); + assert.equal(tokens.length, 1, 'one token added'); - const added = tokens[0] - assert.equal(added.address, address, 'set address correctly') - assert.equal(added.symbol, symbol, 'set symbol correctly') - assert.equal(added.decimals, decimals, 'set decimals correctly') - }) + const added = tokens[0]; + assert.equal(added.address, address, 'set address correctly'); + assert.equal(added.symbol, symbol, 'set symbol correctly'); + assert.equal(added.decimals, decimals, 'set decimals correctly'); + }); it('should allow updating a token value', async function () { - const address = '0xabcdef1234567' - const symbol = 'ABBR' - const decimals = 5 + const address = '0xabcdef1234567'; + const symbol = 'ABBR'; + const decimals = 5; - preferencesController.setAddresses(['0x7e57e2']) - await preferencesController.setSelectedAddress('0x7e57e2') - await preferencesController.addToken(address, symbol, decimals) + preferencesController.setAddresses(['0x7e57e2']); + await preferencesController.setSelectedAddress('0x7e57e2'); + await preferencesController.addToken(address, symbol, decimals); - const newDecimals = 6 - await preferencesController.addToken(address, symbol, newDecimals) + const newDecimals = 6; + await preferencesController.addToken(address, symbol, newDecimals); - const tokens = preferencesController.getTokens() - assert.equal(tokens.length, 1, 'one token added') + const tokens = preferencesController.getTokens(); + assert.equal(tokens.length, 1, 'one token added'); - const added = tokens[0] - assert.equal(added.address, address, 'set address correctly') - assert.equal(added.symbol, symbol, 'set symbol correctly') - assert.equal(added.decimals, newDecimals, 'updated decimals correctly') - }) + const added = tokens[0]; + assert.equal(added.address, address, 'set address correctly'); + assert.equal(added.symbol, symbol, 'set symbol correctly'); + assert.equal(added.decimals, newDecimals, 'updated decimals correctly'); + }); it('should allow adding tokens to two separate addresses', async function () { - const address = '0xabcdef1234567' - const symbol = 'ABBR' - const decimals = 5 + const address = '0xabcdef1234567'; + const symbol = 'ABBR'; + const decimals = 5; - preferencesController.setAddresses(['0x7e57e2', '0xda22le']) + preferencesController.setAddresses(['0x7e57e2', '0xda22le']); - await preferencesController.setSelectedAddress('0x7e57e2') - await preferencesController.addToken(address, symbol, decimals) + await preferencesController.setSelectedAddress('0x7e57e2'); + await preferencesController.addToken(address, symbol, decimals); assert.equal( preferencesController.getTokens().length, 1, 'one token added for 1st address', - ) + ); - await preferencesController.setSelectedAddress('0xda22le') - await preferencesController.addToken(address, symbol, decimals) + await preferencesController.setSelectedAddress('0xda22le'); + await preferencesController.addToken(address, symbol, decimals); assert.equal( preferencesController.getTokens().length, 1, 'one token added for 2nd address', - ) - }) + ); + }); it('should add token per account', async function () { - const addressFirst = '0xabcdef1234567' - const addressSecond = '0xabcdef1234568' - const symbolFirst = 'ABBR' - const symbolSecond = 'ABBB' - const decimals = 5 + const addressFirst = '0xabcdef1234567'; + const addressSecond = '0xabcdef1234568'; + const symbolFirst = 'ABBR'; + const symbolSecond = 'ABBB'; + const decimals = 5; - preferencesController.setAddresses(['0x7e57e2', '0xda22le']) + preferencesController.setAddresses(['0x7e57e2', '0xda22le']); - await preferencesController.setSelectedAddress('0x7e57e2') - await preferencesController.addToken(addressFirst, symbolFirst, decimals) - const tokensFirstAddress = preferencesController.getTokens() + await preferencesController.setSelectedAddress('0x7e57e2'); + await preferencesController.addToken(addressFirst, symbolFirst, decimals); + const tokensFirstAddress = preferencesController.getTokens(); - await preferencesController.setSelectedAddress('0xda22le') + await preferencesController.setSelectedAddress('0xda22le'); await preferencesController.addToken( addressSecond, symbolSecond, decimals, - ) - const tokensSeconAddress = preferencesController.getTokens() + ); + const tokensSeconAddress = preferencesController.getTokens(); assert.notEqual( tokensFirstAddress, tokensSeconAddress, 'add different tokens for two account and tokens are equal', - ) - }) + ); + }); it('should add token per network', async function () { - const addressFirst = '0xabcdef1234567' - const addressSecond = '0xabcdef1234568' - const symbolFirst = 'ABBR' - const symbolSecond = 'ABBB' - const decimals = 5 + const addressFirst = '0xabcdef1234567'; + const addressSecond = '0xabcdef1234568'; + const symbolFirst = 'ABBR'; + const symbolSecond = 'ABBB'; + const decimals = 5; - network.providerStore.updateState({ type: 'mainnet' }) - await preferencesController.addToken(addressFirst, symbolFirst, decimals) - const tokensFirstAddress = preferencesController.getTokens() + network.providerStore.updateState({ type: 'mainnet' }); + await preferencesController.addToken(addressFirst, symbolFirst, decimals); + const tokensFirstAddress = preferencesController.getTokens(); - network.providerStore.updateState({ type: 'rinkeby' }) + network.providerStore.updateState({ type: 'rinkeby' }); await preferencesController.addToken( addressSecond, symbolSecond, decimals, - ) - const tokensSeconAddress = preferencesController.getTokens() + ); + const tokensSeconAddress = preferencesController.getTokens(); assert.notEqual( tokensFirstAddress, tokensSeconAddress, 'add different tokens for two networks and tokens are equal', - ) - }) - }) + ); + }); + }); describe('removeToken', function () { it('should remove the only token from its state', async function () { - preferencesController.setAddresses(['0x7e57e2']) - await preferencesController.setSelectedAddress('0x7e57e2') - await preferencesController.addToken('0xa', 'A', 5) - await preferencesController.removeToken('0xa') + preferencesController.setAddresses(['0x7e57e2']); + await preferencesController.setSelectedAddress('0x7e57e2'); + await preferencesController.addToken('0xa', 'A', 5); + await preferencesController.removeToken('0xa'); - const tokens = preferencesController.getTokens() - assert.equal(tokens.length, 0, 'one token removed') - }) + const tokens = preferencesController.getTokens(); + assert.equal(tokens.length, 0, 'one token removed'); + }); it('should remove a token from its state', async function () { - preferencesController.setAddresses(['0x7e57e2']) - await preferencesController.setSelectedAddress('0x7e57e2') - await preferencesController.addToken('0xa', 'A', 4) - await preferencesController.addToken('0xb', 'B', 5) - await preferencesController.removeToken('0xa') + preferencesController.setAddresses(['0x7e57e2']); + await preferencesController.setSelectedAddress('0x7e57e2'); + await preferencesController.addToken('0xa', 'A', 4); + await preferencesController.addToken('0xb', 'B', 5); + await preferencesController.removeToken('0xa'); - const tokens = preferencesController.getTokens() - assert.equal(tokens.length, 1, 'one token removed') + const tokens = preferencesController.getTokens(); + assert.equal(tokens.length, 1, 'one token removed'); - const [token1] = tokens - assert.deepEqual(token1, { address: '0xb', symbol: 'B', decimals: 5 }) - }) + const [token1] = tokens; + assert.deepEqual(token1, { address: '0xb', symbol: 'B', decimals: 5 }); + }); it('should remove a token from its state on corresponding address', async function () { - preferencesController.setAddresses(['0x7e57e2', '0x7e57e3']) - await preferencesController.setSelectedAddress('0x7e57e2') - await preferencesController.addToken('0xa', 'A', 4) - await preferencesController.addToken('0xb', 'B', 5) - await preferencesController.setSelectedAddress('0x7e57e3') - await preferencesController.addToken('0xa', 'A', 4) - await preferencesController.addToken('0xb', 'B', 5) - const initialTokensSecond = preferencesController.getTokens() - await preferencesController.setSelectedAddress('0x7e57e2') - await preferencesController.removeToken('0xa') + preferencesController.setAddresses(['0x7e57e2', '0x7e57e3']); + await preferencesController.setSelectedAddress('0x7e57e2'); + await preferencesController.addToken('0xa', 'A', 4); + await preferencesController.addToken('0xb', 'B', 5); + await preferencesController.setSelectedAddress('0x7e57e3'); + await preferencesController.addToken('0xa', 'A', 4); + await preferencesController.addToken('0xb', 'B', 5); + const initialTokensSecond = preferencesController.getTokens(); + await preferencesController.setSelectedAddress('0x7e57e2'); + await preferencesController.removeToken('0xa'); - const tokensFirst = preferencesController.getTokens() - assert.equal(tokensFirst.length, 1, 'one token removed in account') + const tokensFirst = preferencesController.getTokens(); + assert.equal(tokensFirst.length, 1, 'one token removed in account'); - const [token1] = tokensFirst - assert.deepEqual(token1, { address: '0xb', symbol: 'B', decimals: 5 }) + const [token1] = tokensFirst; + assert.deepEqual(token1, { address: '0xb', symbol: 'B', decimals: 5 }); - await preferencesController.setSelectedAddress('0x7e57e3') - const tokensSecond = preferencesController.getTokens() + await preferencesController.setSelectedAddress('0x7e57e3'); + const tokensSecond = preferencesController.getTokens(); assert.deepEqual( tokensSecond, initialTokensSecond, 'token deleted for account', - ) - }) + ); + }); it('should remove a token from its state on corresponding network', async function () { - network.providerStore.updateState({ type: 'mainnet' }) - await preferencesController.addToken('0xa', 'A', 4) - await preferencesController.addToken('0xb', 'B', 5) - network.providerStore.updateState({ type: 'rinkeby' }) - await preferencesController.addToken('0xa', 'A', 4) - await preferencesController.addToken('0xb', 'B', 5) - const initialTokensSecond = preferencesController.getTokens() - network.providerStore.updateState({ type: 'mainnet' }) - await preferencesController.removeToken('0xa') + network.providerStore.updateState({ type: 'mainnet' }); + await preferencesController.addToken('0xa', 'A', 4); + await preferencesController.addToken('0xb', 'B', 5); + network.providerStore.updateState({ type: 'rinkeby' }); + await preferencesController.addToken('0xa', 'A', 4); + await preferencesController.addToken('0xb', 'B', 5); + const initialTokensSecond = preferencesController.getTokens(); + network.providerStore.updateState({ type: 'mainnet' }); + await preferencesController.removeToken('0xa'); - const tokensFirst = preferencesController.getTokens() - assert.equal(tokensFirst.length, 1, 'one token removed in network') + const tokensFirst = preferencesController.getTokens(); + assert.equal(tokensFirst.length, 1, 'one token removed in network'); - const [token1] = tokensFirst - assert.deepEqual(token1, { address: '0xb', symbol: 'B', decimals: 5 }) + const [token1] = tokensFirst; + assert.deepEqual(token1, { address: '0xb', symbol: 'B', decimals: 5 }); - network.providerStore.updateState({ type: 'rinkeby' }) - const tokensSecond = preferencesController.getTokens() + network.providerStore.updateState({ type: 'rinkeby' }); + const tokensSecond = preferencesController.getTokens(); assert.deepEqual( tokensSecond, initialTokensSecond, 'token deleted for network', - ) - }) - }) + ); + }); + }); describe('on setSelectedAddress', function () { it('should update tokens from its state on corresponding address', async function () { - preferencesController.setAddresses(['0x7e57e2', '0x7e57e3']) - await preferencesController.setSelectedAddress('0x7e57e2') - await preferencesController.addToken('0xa', 'A', 4) - await preferencesController.addToken('0xb', 'B', 5) - await preferencesController.setSelectedAddress('0x7e57e3') - await preferencesController.addToken('0xa', 'C', 4) - await preferencesController.addToken('0xb', 'D', 5) + preferencesController.setAddresses(['0x7e57e2', '0x7e57e3']); + await preferencesController.setSelectedAddress('0x7e57e2'); + await preferencesController.addToken('0xa', 'A', 4); + await preferencesController.addToken('0xb', 'B', 5); + await preferencesController.setSelectedAddress('0x7e57e3'); + await preferencesController.addToken('0xa', 'C', 4); + await preferencesController.addToken('0xb', 'D', 5); - await preferencesController.setSelectedAddress('0x7e57e2') - const initialTokensFirst = preferencesController.getTokens() - await preferencesController.setSelectedAddress('0x7e57e3') - const initialTokensSecond = preferencesController.getTokens() + await preferencesController.setSelectedAddress('0x7e57e2'); + const initialTokensFirst = preferencesController.getTokens(); + await preferencesController.setSelectedAddress('0x7e57e3'); + const initialTokensSecond = preferencesController.getTokens(); assert.notDeepEqual( initialTokensFirst, initialTokensSecond, 'tokens not equal for different accounts and tokens', - ) + ); - await preferencesController.setSelectedAddress('0x7e57e2') - const tokensFirst = preferencesController.getTokens() - await preferencesController.setSelectedAddress('0x7e57e3') - const tokensSecond = preferencesController.getTokens() + await preferencesController.setSelectedAddress('0x7e57e2'); + const tokensFirst = preferencesController.getTokens(); + await preferencesController.setSelectedAddress('0x7e57e3'); + const tokensSecond = preferencesController.getTokens(); assert.deepEqual( tokensFirst, initialTokensFirst, 'tokens equal for same account', - ) + ); assert.deepEqual( tokensSecond, initialTokensSecond, 'tokens equal for same account', - ) - }) - }) + ); + }); + }); describe('on updateStateNetworkType', function () { it('should remove a token from its state on corresponding network', async function () { - network.providerStore.updateState({ type: 'mainnet' }) - await preferencesController.addToken('0xa', 'A', 4) - await preferencesController.addToken('0xb', 'B', 5) - const initialTokensFirst = preferencesController.getTokens() - network.providerStore.updateState({ type: 'rinkeby' }) - await preferencesController.addToken('0xa', 'C', 4) - await preferencesController.addToken('0xb', 'D', 5) - const initialTokensSecond = preferencesController.getTokens() + network.providerStore.updateState({ type: 'mainnet' }); + await preferencesController.addToken('0xa', 'A', 4); + await preferencesController.addToken('0xb', 'B', 5); + const initialTokensFirst = preferencesController.getTokens(); + network.providerStore.updateState({ type: 'rinkeby' }); + await preferencesController.addToken('0xa', 'C', 4); + await preferencesController.addToken('0xb', 'D', 5); + const initialTokensSecond = preferencesController.getTokens(); assert.notDeepEqual( initialTokensFirst, initialTokensSecond, 'tokens not equal for different networks and tokens', - ) + ); - network.providerStore.updateState({ type: 'mainnet' }) - const tokensFirst = preferencesController.getTokens() - network.providerStore.updateState({ type: 'rinkeby' }) - const tokensSecond = preferencesController.getTokens() + network.providerStore.updateState({ type: 'mainnet' }); + const tokensFirst = preferencesController.getTokens(); + network.providerStore.updateState({ type: 'rinkeby' }); + const tokensSecond = preferencesController.getTokens(); assert.deepEqual( tokensFirst, initialTokensFirst, 'tokens equal for same network', - ) + ); assert.deepEqual( tokensSecond, initialTokensSecond, 'tokens equal for same network', - ) - }) - }) + ); + }); + }); describe('on watchAsset', function () { - let req, stubHandleWatchAssetERC20 - const sandbox = sinon.createSandbox() + let req, stubHandleWatchAssetERC20; + const sandbox = sinon.createSandbox(); beforeEach(function () { - req = { method: 'wallet_watchAsset', params: {} } + req = { method: 'wallet_watchAsset', params: {} }; stubHandleWatchAssetERC20 = sandbox.stub( preferencesController, '_handleWatchAssetERC20', - ) - }) + ); + }); after(function () { - sandbox.restore() - }) + sandbox.restore(); + }); it('should error if passed no type', async function () { await assert.rejects( () => preferencesController.requestWatchAsset(req), { message: 'Asset of type "undefined" not supported.' }, 'should have errored', - ) - }) + ); + }); it('should error if method is not supported', async function () { - req.params.type = 'someasset' + req.params.type = 'someasset'; await assert.rejects( () => preferencesController.requestWatchAsset(req), { message: 'Asset of type "someasset" not supported.' }, 'should have errored', - ) - }) + ); + }); it('should handle ERC20 type', async function () { - req.params.type = 'ERC20' - await preferencesController.requestWatchAsset(req) - sandbox.assert.called(stubHandleWatchAssetERC20) - }) - }) + req.params.type = 'ERC20'; + await preferencesController.requestWatchAsset(req); + sandbox.assert.called(stubHandleWatchAssetERC20); + }); + }); describe('on watchAsset of type ERC20', function () { - let req + let req; - const sandbox = sinon.createSandbox() + const sandbox = sinon.createSandbox(); beforeEach(function () { - req = { params: { type: 'ERC20' } } - }) + req = { params: { type: 'ERC20' } }; + }); after(function () { - sandbox.restore() - }) + sandbox.restore(); + }); it('should add suggested token', async function () { - const address = '0xabcdef1234567' - const symbol = 'ABBR' - const decimals = 5 - const image = 'someimage' - req.params.options = { address, symbol, decimals, image } + const address = '0xabcdef1234567'; + const symbol = 'ABBR'; + const decimals = 5; + const image = 'someimage'; + req.params.options = { address, symbol, decimals, image }; sandbox .stub(preferencesController, '_validateERC20AssetParams') - .returns(true) - preferencesController.openPopup = async () => undefined + .returns(true); + preferencesController.openPopup = async () => undefined; - await preferencesController._handleWatchAssetERC20(req.params.options) - const suggested = preferencesController.getSuggestedTokens() + await preferencesController._handleWatchAssetERC20(req.params.options); + const suggested = preferencesController.getSuggestedTokens(); assert.equal( Object.keys(suggested).length, 1, `one token added ${Object.keys(suggested)}`, - ) + ); - assert.equal(suggested[address].address, address, 'set address correctly') - assert.equal(suggested[address].symbol, symbol, 'set symbol correctly') + assert.equal( + suggested[address].address, + address, + 'set address correctly', + ); + assert.equal(suggested[address].symbol, symbol, 'set symbol correctly'); assert.equal( suggested[address].decimals, decimals, 'set decimals correctly', - ) - assert.equal(suggested[address].image, image, 'set image correctly') - }) + ); + assert.equal(suggested[address].image, image, 'set image correctly'); + }); it('should add token correctly if user confirms', async function () { - const address = '0xabcdef1234567' - const symbol = 'ABBR' - const decimals = 5 - const image = 'someimage' - req.params.options = { address, symbol, decimals, image } + const address = '0xabcdef1234567'; + const symbol = 'ABBR'; + const decimals = 5; + const image = 'someimage'; + req.params.options = { address, symbol, decimals, image }; sandbox .stub(preferencesController, '_validateERC20AssetParams') - .returns(true) + .returns(true); preferencesController.openPopup = async () => { - await preferencesController.addToken(address, symbol, decimals, image) - } + await preferencesController.addToken(address, symbol, decimals, image); + }; - await preferencesController._handleWatchAssetERC20(req.params.options) - const tokens = preferencesController.getTokens() - assert.equal(tokens.length, 1, `one token added`) - const added = tokens[0] - assert.equal(added.address, address, 'set address correctly') - assert.equal(added.symbol, symbol, 'set symbol correctly') - assert.equal(added.decimals, decimals, 'set decimals correctly') + await preferencesController._handleWatchAssetERC20(req.params.options); + const tokens = preferencesController.getTokens(); + assert.equal(tokens.length, 1, `one token added`); + const added = tokens[0]; + assert.equal(added.address, address, 'set address correctly'); + assert.equal(added.symbol, symbol, 'set symbol correctly'); + assert.equal(added.decimals, decimals, 'set decimals correctly'); - const assetImages = preferencesController.getAssetImages() - assert.ok(assetImages[address], `set image correctly`) - }) + const assetImages = preferencesController.getAssetImages(); + assert.ok(assetImages[address], `set image correctly`); + }); it('should validate ERC20 asset correctly', async function () { - const validate = preferencesController._validateERC20AssetParams + const validate = preferencesController._validateERC20AssetParams; assert.doesNotThrow(() => validate({ @@ -518,11 +522,11 @@ describe('preferences controller', function () { symbol: 'ABC', decimals: 0, }), - ) + ); assert.throws( () => validate({ symbol: 'ABC', decimals: 0 }), 'missing address should fail', - ) + ); assert.throws( () => validate({ @@ -530,7 +534,7 @@ describe('preferences controller', function () { decimals: 0, }), 'missing symbol should fail', - ) + ); assert.throws( () => validate({ @@ -538,7 +542,7 @@ describe('preferences controller', function () { symbol: 'ABC', }), 'missing decimals should fail', - ) + ); assert.throws( () => validate({ @@ -547,7 +551,7 @@ describe('preferences controller', function () { decimals: 0, }), 'invalid symbol should fail', - ) + ); assert.throws( () => validate({ @@ -556,7 +560,7 @@ describe('preferences controller', function () { decimals: -1, }), 'decimals < 0 should fail', - ) + ); assert.throws( () => validate({ @@ -565,69 +569,69 @@ describe('preferences controller', function () { decimals: 38, }), 'decimals > 36 should fail', - ) + ); assert.throws( () => validate({ address: '0x123', symbol: 'ABC', decimals: 0 }), 'invalid address should fail', - ) - }) - }) + ); + }); + }); describe('setPasswordForgotten', function () { it('should default to false', function () { - const state = preferencesController.store.getState() - assert.equal(state.forgottenPassword, false) - }) + const state = preferencesController.store.getState(); + assert.equal(state.forgottenPassword, false); + }); it('should set the forgottenPassword property in state', function () { assert.equal( preferencesController.store.getState().forgottenPassword, false, - ) + ); - preferencesController.setPasswordForgotten(true) + preferencesController.setPasswordForgotten(true); assert.equal( preferencesController.store.getState().forgottenPassword, true, - ) - }) - }) + ); + }); + }); describe('#updateRpc', function () { it('should update the rpcDetails properly', async function () { preferencesController.store.updateState({ frequentRpcListDetail: [{}, { rpcUrl: 'test', chainId: '0x1' }, {}], - }) - await preferencesController.updateRpc({ rpcUrl: 'test', chainId: '0x1' }) + }); + await preferencesController.updateRpc({ rpcUrl: 'test', chainId: '0x1' }); await preferencesController.updateRpc({ rpcUrl: 'test/1', chainId: '0x1', - }) + }); await preferencesController.updateRpc({ rpcUrl: 'test/2', chainId: '0x1', - }) + }); await preferencesController.updateRpc({ rpcUrl: 'test/3', chainId: '0x1', - }) - const list = preferencesController.getFrequentRpcListDetail() - assert.deepEqual(list[1], { rpcUrl: 'test', chainId: '0x1' }) - }) + }); + const list = preferencesController.getFrequentRpcListDetail(); + assert.deepEqual(list[1], { rpcUrl: 'test', chainId: '0x1' }); + }); it('should migrate address book entries if chainId changes', async function () { preferencesController.store.updateState({ frequentRpcListDetail: [{}, { rpcUrl: 'test', chainId: '1' }, {}], - }) - await preferencesController.updateRpc({ rpcUrl: 'test', chainId: '0x1' }) - assert(migrateAddressBookState.calledWith('1', '0x1')) - }) - }) + }); + await preferencesController.updateRpc({ rpcUrl: 'test', chainId: '0x1' }); + assert(migrateAddressBookState.calledWith('1', '0x1')); + }); + }); describe('adding and removing from frequentRpcListDetail', function () { it('should add custom RPC url to state', function () { - preferencesController.addToFrequentRpcList('rpc_url', '0x1') + preferencesController.addToFrequentRpcList('rpc_url', '0x1'); assert.deepEqual( preferencesController.store.getState().frequentRpcListDetail, [ @@ -639,8 +643,8 @@ describe('preferences controller', function () { rpcPrefs: {}, }, ], - ) - preferencesController.addToFrequentRpcList('rpc_url', '0x1') + ); + preferencesController.addToFrequentRpcList('rpc_url', '0x1'); assert.deepEqual( preferencesController.store.getState().frequentRpcListDetail, [ @@ -652,17 +656,17 @@ describe('preferences controller', function () { rpcPrefs: {}, }, ], - ) - }) + ); + }); it('should throw if chainId is invalid', function () { assert.throws(() => { - preferencesController.addToFrequentRpcList('rpc_url', '1') - }, 'should throw on invalid chainId') - }) + preferencesController.addToFrequentRpcList('rpc_url', '1'); + }, 'should throw on invalid chainId'); + }); it('should remove custom RPC url from state', function () { - preferencesController.addToFrequentRpcList('rpc_url', '0x1') + preferencesController.addToFrequentRpcList('rpc_url', '0x1'); assert.deepEqual( preferencesController.store.getState().frequentRpcListDetail, [ @@ -674,27 +678,30 @@ describe('preferences controller', function () { rpcPrefs: {}, }, ], - ) - preferencesController.removeFromFrequentRpcList('other_rpc_url') - preferencesController.removeFromFrequentRpcList('http://localhost:8545') - preferencesController.removeFromFrequentRpcList('rpc_url') + ); + preferencesController.removeFromFrequentRpcList('other_rpc_url'); + preferencesController.removeFromFrequentRpcList('http://localhost:8545'); + preferencesController.removeFromFrequentRpcList('rpc_url'); assert.deepEqual( preferencesController.store.getState().frequentRpcListDetail, [], - ) - }) - }) + ); + }); + }); describe('setUsePhishDetect', function () { it('should default to true', function () { - const state = preferencesController.store.getState() - assert.equal(state.usePhishDetect, true) - }) + const state = preferencesController.store.getState(); + assert.equal(state.usePhishDetect, true); + }); it('should set the usePhishDetect property in state', function () { - assert.equal(preferencesController.store.getState().usePhishDetect, true) - preferencesController.setUsePhishDetect(false) - assert.equal(preferencesController.store.getState().usePhishDetect, false) - }) - }) -}) + assert.equal(preferencesController.store.getState().usePhishDetect, true); + preferencesController.setUsePhishDetect(false); + assert.equal( + preferencesController.store.getState().usePhishDetect, + false, + ); + }); + }); +}); diff --git a/test/unit/app/controllers/swaps-test.js b/test/unit/app/controllers/swaps-test.js index 2622d04eb..5bd1c8529 100644 --- a/test/unit/app/controllers/swaps-test.js +++ b/test/unit/app/controllers/swaps-test.js @@ -1,19 +1,19 @@ -import assert from 'assert' -import sinon from 'sinon' +import assert from 'assert'; +import sinon from 'sinon'; -import { ethers } from 'ethers' -import { mapValues } from 'lodash' -import BigNumber from 'bignumber.js' -import { ObservableStore } from '@metamask/obs-store' +import { ethers } from 'ethers'; +import { mapValues } from 'lodash'; +import BigNumber from 'bignumber.js'; +import { ObservableStore } from '@metamask/obs-store'; import { ROPSTEN_NETWORK_ID, MAINNET_NETWORK_ID, -} from '../../../../shared/constants/network' -import { ETH_SWAPS_TOKEN_ADDRESS } from '../../../../ui/app/helpers/constants/swaps' -import { createTestProviderTools } from '../../../stub/provider' +} from '../../../../shared/constants/network'; +import { ETH_SWAPS_TOKEN_ADDRESS } from '../../../../ui/app/helpers/constants/swaps'; +import { createTestProviderTools } from '../../../stub/provider'; import SwapsController, { utils, -} from '../../../../app/scripts/controllers/swaps' +} from '../../../../app/scripts/controllers/swaps'; const MOCK_FETCH_PARAMS = { slippage: 3, @@ -23,16 +23,16 @@ const MOCK_FETCH_PARAMS = { value: '1000000000000000000', fromAddress: '0x7F18BB4Dd92CF2404C54CBa1A9BE4A1153bdb078', exchangeList: 'zeroExV1', -} +}; -const TEST_AGG_ID_1 = 'TEST_AGG_1' -const TEST_AGG_ID_2 = 'TEST_AGG_2' -const TEST_AGG_ID_3 = 'TEST_AGG_3' -const TEST_AGG_ID_4 = 'TEST_AGG_4' -const TEST_AGG_ID_5 = 'TEST_AGG_5' -const TEST_AGG_ID_6 = 'TEST_AGG_6' -const TEST_AGG_ID_BEST = 'TEST_AGG_BEST' -const TEST_AGG_ID_APPROVAL = 'TEST_AGG_APPROVAL' +const TEST_AGG_ID_1 = 'TEST_AGG_1'; +const TEST_AGG_ID_2 = 'TEST_AGG_2'; +const TEST_AGG_ID_3 = 'TEST_AGG_3'; +const TEST_AGG_ID_4 = 'TEST_AGG_4'; +const TEST_AGG_ID_5 = 'TEST_AGG_5'; +const TEST_AGG_ID_6 = 'TEST_AGG_6'; +const TEST_AGG_ID_BEST = 'TEST_AGG_BEST'; +const TEST_AGG_ID_APPROVAL = 'TEST_AGG_APPROVAL'; const MOCK_APPROVAL_NEEDED = { data: @@ -42,7 +42,7 @@ const MOCK_APPROVAL_NEEDED = { from: '0x2369267687A84ac7B494daE2f1542C40E37f4455', gas: '12', gasPrice: '34', -} +}; const MOCK_QUOTES_APPROVAL_REQUIRED = { [TEST_AGG_ID_APPROVAL]: { @@ -69,28 +69,28 @@ const MOCK_QUOTES_APPROVAL_REQUIRED = { approvalNeeded: MOCK_APPROVAL_NEEDED, fee: 1, }, -} +}; const MOCK_FETCH_METADATA = { destinationTokenInfo: { symbol: 'FOO', decimals: 18, }, -} +}; const MOCK_TOKEN_RATES_STORE = new ObservableStore({ contractExchangeRates: { '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48': 2, '0x1111111111111111111111111111111111111111': 0.1, }, -}) +}); -const MOCK_GET_PROVIDER_CONFIG = () => ({ type: 'FAKE_NETWORK' }) +const MOCK_GET_PROVIDER_CONFIG = () => ({ type: 'FAKE_NETWORK' }); const MOCK_GET_BUFFERED_GAS_LIMIT = async () => ({ gasLimit: 2000000, simulationFails: undefined, -}) +}); function getMockNetworkController() { return { @@ -98,11 +98,11 @@ function getMockNetworkController() { getState: () => { return { network: ROPSTEN_NETWORK_ID, - } + }; }, }, on: sinon.stub().withArgs('networkDidChange').callsArgAsync(1), - } + }; } const EMPTY_INIT_STATE = { @@ -123,15 +123,15 @@ const EMPTY_INIT_STATE = { swapsFeatureIsLive: false, swapsQuoteRefreshTime: 60000, }, -} +}; -const sandbox = sinon.createSandbox() -const fetchTradesInfoStub = sandbox.stub() -const fetchSwapsFeatureLivenessStub = sandbox.stub() -const fetchSwapsQuoteRefreshTimeStub = sandbox.stub() +const sandbox = sinon.createSandbox(); +const fetchTradesInfoStub = sandbox.stub(); +const fetchSwapsFeatureLivenessStub = sandbox.stub(); +const fetchSwapsQuoteRefreshTimeStub = sandbox.stub(); describe('SwapsController', function () { - let provider + let provider; const getSwapsController = () => { return new SwapsController({ @@ -143,8 +143,8 @@ describe('SwapsController', function () { fetchTradesInfo: fetchTradesInfoStub, fetchSwapsFeatureLiveness: fetchSwapsFeatureLivenessStub, fetchSwapsQuoteRefreshTime: fetchSwapsQuoteRefreshTimeStub, - }) - } + }); + }; before(function () { const providerResultStub = { @@ -152,35 +152,38 @@ describe('SwapsController', function () { eth_gasPrice: '0x0de0b6b3a7640000', // by default, all accounts are external accounts (not contracts) eth_getCode: '0x', - } + }; provider = createTestProviderTools({ scaffold: providerResultStub, networkId: 1, chainId: 1, - }).provider - }) + }).provider; + }); afterEach(function () { - sandbox.restore() - }) + sandbox.restore(); + }); describe('constructor', function () { it('should setup correctly', function () { - const swapsController = getSwapsController() - assert.deepStrictEqual(swapsController.store.getState(), EMPTY_INIT_STATE) + const swapsController = getSwapsController(); + assert.deepStrictEqual( + swapsController.store.getState(), + EMPTY_INIT_STATE, + ); assert.deepStrictEqual( swapsController.getBufferedGasLimit, MOCK_GET_BUFFERED_GAS_LIMIT, - ) - assert.strictEqual(swapsController.pollCount, 0) + ); + assert.strictEqual(swapsController.pollCount, 0); assert.deepStrictEqual( swapsController.getProviderConfig, MOCK_GET_PROVIDER_CONFIG, - ) - }) + ); + }); it('should replace ethers instance when network changes', function () { - const networkController = getMockNetworkController() + const networkController = getMockNetworkController(); const swapsController = new SwapsController({ getBufferedGasLimit: MOCK_GET_BUFFERED_GAS_LIMIT, networkController, @@ -189,22 +192,22 @@ describe('SwapsController', function () { tokenRatesStore: MOCK_TOKEN_RATES_STORE, fetchTradesInfo: fetchTradesInfoStub, fetchSwapsFeatureLiveness: fetchSwapsFeatureLivenessStub, - }) - const currentEthersInstance = swapsController.ethersProvider - const onNetworkDidChange = networkController.on.getCall(0).args[1] + }); + const currentEthersInstance = swapsController.ethersProvider; + const onNetworkDidChange = networkController.on.getCall(0).args[1]; - onNetworkDidChange(MAINNET_NETWORK_ID) + onNetworkDidChange(MAINNET_NETWORK_ID); - const newEthersInstance = swapsController.ethersProvider + const newEthersInstance = swapsController.ethersProvider; assert.notStrictEqual( currentEthersInstance, newEthersInstance, 'Ethers provider should be replaced', - ) - }) + ); + }); it('should not replace ethers instance when network changes to loading', function () { - const networkController = getMockNetworkController() + const networkController = getMockNetworkController(); const swapsController = new SwapsController({ getBufferedGasLimit: MOCK_GET_BUFFERED_GAS_LIMIT, networkController, @@ -213,22 +216,22 @@ describe('SwapsController', function () { tokenRatesStore: MOCK_TOKEN_RATES_STORE, fetchTradesInfo: fetchTradesInfoStub, fetchSwapsFeatureLiveness: fetchSwapsFeatureLivenessStub, - }) - const currentEthersInstance = swapsController.ethersProvider - const onNetworkDidChange = networkController.on.getCall(0).args[1] + }); + const currentEthersInstance = swapsController.ethersProvider; + const onNetworkDidChange = networkController.on.getCall(0).args[1]; - onNetworkDidChange('loading') + onNetworkDidChange('loading'); - const newEthersInstance = swapsController.ethersProvider + const newEthersInstance = swapsController.ethersProvider; assert.strictEqual( currentEthersInstance, newEthersInstance, 'Ethers provider should not be replaced', - ) - }) + ); + }); it('should not replace ethers instance when network changes to the same network', function () { - const networkController = getMockNetworkController() + const networkController = getMockNetworkController(); const swapsController = new SwapsController({ getBufferedGasLimit: MOCK_GET_BUFFERED_GAS_LIMIT, networkController, @@ -237,149 +240,149 @@ describe('SwapsController', function () { tokenRatesStore: MOCK_TOKEN_RATES_STORE, fetchTradesInfo: fetchTradesInfoStub, fetchSwapsFeatureLiveness: fetchSwapsFeatureLivenessStub, - }) - const currentEthersInstance = swapsController.ethersProvider - const onNetworkDidChange = networkController.on.getCall(0).args[1] + }); + const currentEthersInstance = swapsController.ethersProvider; + const onNetworkDidChange = networkController.on.getCall(0).args[1]; - onNetworkDidChange(ROPSTEN_NETWORK_ID) + onNetworkDidChange(ROPSTEN_NETWORK_ID); - const newEthersInstance = swapsController.ethersProvider + const newEthersInstance = swapsController.ethersProvider; assert.strictEqual( currentEthersInstance, newEthersInstance, 'Ethers provider should not be replaced', - ) - }) - }) + ); + }); + }); describe('API', function () { - let swapsController + let swapsController; beforeEach(function () { - swapsController = getSwapsController() - }) + swapsController = getSwapsController(); + }); describe('setters', function () { it('should set selected quote agg id', function () { - const selectedAggId = 'test' - swapsController.setSelectedQuoteAggId(selectedAggId) + const selectedAggId = 'test'; + swapsController.setSelectedQuoteAggId(selectedAggId); assert.deepStrictEqual( swapsController.store.getState().swapsState.selectedAggId, selectedAggId, - ) - }) + ); + }); it('should set swaps tokens', function () { - const tokens = [] - swapsController.setSwapsTokens(tokens) + const tokens = []; + swapsController.setSwapsTokens(tokens); assert.deepStrictEqual( swapsController.store.getState().swapsState.tokens, tokens, - ) - }) + ); + }); it('should set trade tx id', function () { - const tradeTxId = 'test' - swapsController.setTradeTxId(tradeTxId) + const tradeTxId = 'test'; + swapsController.setTradeTxId(tradeTxId); assert.strictEqual( swapsController.store.getState().swapsState.tradeTxId, tradeTxId, - ) - }) + ); + }); it('should set swaps tx gas price', function () { - const gasPrice = 1 - swapsController.setSwapsTxGasPrice(gasPrice) + const gasPrice = 1; + swapsController.setSwapsTxGasPrice(gasPrice); assert.deepStrictEqual( swapsController.store.getState().swapsState.customGasPrice, gasPrice, - ) - }) + ); + }); it('should set swaps tx gas limit', function () { - const gasLimit = '1' - swapsController.setSwapsTxGasLimit(gasLimit) + const gasLimit = '1'; + swapsController.setSwapsTxGasLimit(gasLimit); assert.deepStrictEqual( swapsController.store.getState().swapsState.customMaxGas, gasLimit, - ) - }) + ); + }); it('should set background swap route state', function () { - const routeState = 'test' - swapsController.setBackgroundSwapRouteState(routeState) + const routeState = 'test'; + swapsController.setBackgroundSwapRouteState(routeState); assert.deepStrictEqual( swapsController.store.getState().swapsState.routeState, routeState, - ) - }) + ); + }); it('should set swaps error key', function () { - const errorKey = 'test' - swapsController.setSwapsErrorKey(errorKey) + const errorKey = 'test'; + swapsController.setSwapsErrorKey(errorKey); assert.deepStrictEqual( swapsController.store.getState().swapsState.errorKey, errorKey, - ) - }) + ); + }); it('should set initial gas estimate', async function () { - const initialAggId = TEST_AGG_ID_1 - const baseGasEstimate = 10 - const { maxGas, estimatedRefund } = getMockQuotes()[TEST_AGG_ID_1] + const initialAggId = TEST_AGG_ID_1; + const baseGasEstimate = 10; + const { maxGas, estimatedRefund } = getMockQuotes()[TEST_AGG_ID_1]; - const { swapsState } = swapsController.store.getState() + const { swapsState } = swapsController.store.getState(); // Set mock quotes in order to have data for the test agg swapsController.store.updateState({ swapsState: { ...swapsState, quotes: getMockQuotes() }, - }) + }); await swapsController.setInitialGasEstimate( initialAggId, baseGasEstimate, - ) + ); const { gasLimit: bufferedGasLimit, - } = await swapsController.getBufferedGasLimit() + } = await swapsController.getBufferedGasLimit(); const { gasEstimate, gasEstimateWithRefund, - } = swapsController.store.getState().swapsState.quotes[initialAggId] - assert.strictEqual(gasEstimate, bufferedGasLimit) + } = swapsController.store.getState().swapsState.quotes[initialAggId]; + assert.strictEqual(gasEstimate, bufferedGasLimit); assert.strictEqual( gasEstimateWithRefund, new BigNumber(maxGas, 10).minus(estimatedRefund, 10).toString(16), - ) - }) + ); + }); it('should set custom approve tx data', function () { - const data = 'test' - swapsController.setCustomApproveTxData(data) + const data = 'test'; + swapsController.setCustomApproveTxData(data); assert.deepStrictEqual( swapsController.store.getState().swapsState.customApproveTxData, data, - ) - }) - }) + ); + }); + }); describe('_findTopQuoteAndCalculateSavings', function () { beforeEach(function () { - const { swapsState } = swapsController.store.getState() + const { swapsState } = swapsController.store.getState(); swapsController.store.updateState({ swapsState: { ...swapsState, customGasPrice: '0x174876e800' }, - }) - }) + }); + }); it('returns empty object if passed undefined or empty object', async function () { assert.deepStrictEqual( await swapsController._findTopQuoteAndCalculateSavings(), {}, - ) + ); assert.deepStrictEqual( await swapsController._findTopQuoteAndCalculateSavings({}), {}, - ) - }) + ); + }); it('returns the top aggId and quotes with savings and fee values if passed necessary data and an even number of quotes', async function () { const [ @@ -387,34 +390,34 @@ describe('SwapsController', function () { resultQuotes, ] = await swapsController._findTopQuoteAndCalculateSavings( getTopQuoteAndSavingsMockQuotes(), - ) - assert.equal(topAggId, TEST_AGG_ID_1) + ); + assert.equal(topAggId, TEST_AGG_ID_1); assert.deepStrictEqual( resultQuotes, getTopQuoteAndSavingsBaseExpectedResults(), - ) - }) + ); + }); it('returns the top aggId and quotes with savings and fee values if passed necessary data and an odd number of quotes', async function () { - const testInput = getTopQuoteAndSavingsMockQuotes() - delete testInput[TEST_AGG_ID_6] - const expectedResultQuotes = getTopQuoteAndSavingsBaseExpectedResults() - delete expectedResultQuotes[TEST_AGG_ID_6] + const testInput = getTopQuoteAndSavingsMockQuotes(); + delete testInput[TEST_AGG_ID_6]; + const expectedResultQuotes = getTopQuoteAndSavingsBaseExpectedResults(); + delete expectedResultQuotes[TEST_AGG_ID_6]; expectedResultQuotes[TEST_AGG_ID_1].savings = { total: '0.0292', performance: '0.0297', fee: '0.02', metaMaskFee: '0.0205', medianMetaMaskFee: '0.0202', - } + }; const [ topAggId, resultQuotes, - ] = await swapsController._findTopQuoteAndCalculateSavings(testInput) - assert.equal(topAggId, TEST_AGG_ID_1) - assert.deepStrictEqual(resultQuotes, expectedResultQuotes) - }) + ] = await swapsController._findTopQuoteAndCalculateSavings(testInput); + assert.equal(topAggId, TEST_AGG_ID_1); + assert.deepStrictEqual(resultQuotes, expectedResultQuotes); + }); it('returns the top aggId, without best quote flagged, and quotes with fee values if passed necessary data but no custom convert rate exists', async function () { const testInput = mapValues( @@ -423,7 +426,7 @@ describe('SwapsController', function () { ...quote, destinationToken: '0xnoConversionRateExists', }), - ) + ); const expectedResultQuotes = { [TEST_AGG_ID_1]: { ...testInput[TEST_AGG_ID_1], @@ -449,15 +452,15 @@ describe('SwapsController', function () { ...testInput[TEST_AGG_ID_6], ethFee: '0.06', }, - } + }; const [ topAggId, resultQuotes, - ] = await swapsController._findTopQuoteAndCalculateSavings(testInput) - assert.equal(topAggId, TEST_AGG_ID_1) - assert.deepStrictEqual(resultQuotes, expectedResultQuotes) - }) + ] = await swapsController._findTopQuoteAndCalculateSavings(testInput); + assert.equal(topAggId, TEST_AGG_ID_1); + assert.deepStrictEqual(resultQuotes, expectedResultQuotes); + }); it('returns the top aggId and quotes with savings and fee values if passed necessary data and the source token is ETH', async function () { const testInput = mapValues( @@ -468,8 +471,8 @@ describe('SwapsController', function () { destinationToken: '0x1111111111111111111111111111111111111111', trade: { value: '0x8ac7230489e80000' }, }), - ) - const baseExpectedResultQuotes = getTopQuoteAndSavingsBaseExpectedResults() + ); + const baseExpectedResultQuotes = getTopQuoteAndSavingsBaseExpectedResults(); const expectedResultQuotes = { [TEST_AGG_ID_1]: { ...baseExpectedResultQuotes[TEST_AGG_ID_1], @@ -513,15 +516,15 @@ describe('SwapsController', function () { trade: { value: '0x8ac7230489e80000' }, overallValueOfQuote: '1.8705', }, - } + }; const [ topAggId, resultQuotes, - ] = await swapsController._findTopQuoteAndCalculateSavings(testInput) - assert.equal(topAggId, TEST_AGG_ID_1) - assert.deepStrictEqual(resultQuotes, expectedResultQuotes) - }) + ] = await swapsController._findTopQuoteAndCalculateSavings(testInput); + assert.equal(topAggId, TEST_AGG_ID_1); + assert.deepStrictEqual(resultQuotes, expectedResultQuotes); + }); it('returns the top aggId and quotes with savings and fee values if passed necessary data and the source token is ETH and an ETH fee is included in the trade value of what would be the best quote', async function () { const testInput = mapValues( @@ -532,10 +535,10 @@ describe('SwapsController', function () { destinationToken: '0x1111111111111111111111111111111111111111', trade: { value: '0x8ac7230489e80000' }, }), - ) + ); // 0.04 ETH fee included in trade value - testInput[TEST_AGG_ID_1].trade.value = '0x8b553ece48ec0000' - const baseExpectedResultQuotes = getTopQuoteAndSavingsBaseExpectedResults() + testInput[TEST_AGG_ID_1].trade.value = '0x8b553ece48ec0000'; + const baseExpectedResultQuotes = getTopQuoteAndSavingsBaseExpectedResults(); const expectedResultQuotes = { [TEST_AGG_ID_1]: { ...baseExpectedResultQuotes[TEST_AGG_ID_1], @@ -588,23 +591,23 @@ describe('SwapsController', function () { trade: { value: '0x8ac7230489e80000' }, overallValueOfQuote: '1.8705', }, - } - delete expectedResultQuotes[TEST_AGG_ID_1].isBestQuote - delete expectedResultQuotes[TEST_AGG_ID_1].savings + }; + delete expectedResultQuotes[TEST_AGG_ID_1].isBestQuote; + delete expectedResultQuotes[TEST_AGG_ID_1].savings; const [ topAggId, resultQuotes, - ] = await swapsController._findTopQuoteAndCalculateSavings(testInput) - assert.equal(topAggId, TEST_AGG_ID_2) - assert.deepStrictEqual(resultQuotes, expectedResultQuotes) - }) + ] = await swapsController._findTopQuoteAndCalculateSavings(testInput); + assert.equal(topAggId, TEST_AGG_ID_2); + assert.deepStrictEqual(resultQuotes, expectedResultQuotes); + }); it('returns the top aggId and quotes with savings and fee values if passed necessary data and the source token is not ETH and an ETH fee is included in the trade value of what would be the best quote', async function () { - const testInput = getTopQuoteAndSavingsMockQuotes() + const testInput = getTopQuoteAndSavingsMockQuotes(); // 0.04 ETH fee included in trade value - testInput[TEST_AGG_ID_1].trade.value = '0x8e1bc9bf040000' - const baseExpectedResultQuotes = getTopQuoteAndSavingsBaseExpectedResults() + testInput[TEST_AGG_ID_1].trade.value = '0x8e1bc9bf040000'; + const baseExpectedResultQuotes = getTopQuoteAndSavingsBaseExpectedResults(); const expectedResultQuotes = { ...baseExpectedResultQuotes, [TEST_AGG_ID_1]: { @@ -624,37 +627,37 @@ describe('SwapsController', function () { medianMetaMaskFee: '0.0201', }, }, - } - delete expectedResultQuotes[TEST_AGG_ID_1].isBestQuote - delete expectedResultQuotes[TEST_AGG_ID_1].savings + }; + delete expectedResultQuotes[TEST_AGG_ID_1].isBestQuote; + delete expectedResultQuotes[TEST_AGG_ID_1].savings; const [ topAggId, resultQuotes, - ] = await swapsController._findTopQuoteAndCalculateSavings(testInput) - assert.equal(topAggId, [TEST_AGG_ID_2]) - assert.deepStrictEqual(resultQuotes, expectedResultQuotes) - }) - }) + ] = await swapsController._findTopQuoteAndCalculateSavings(testInput); + assert.equal(topAggId, [TEST_AGG_ID_2]); + assert.deepStrictEqual(resultQuotes, expectedResultQuotes); + }); + }); describe('fetchAndSetQuotes', function () { it('returns null if fetchParams is not provided', async function () { - const quotes = await swapsController.fetchAndSetQuotes(undefined) - assert.strictEqual(quotes, null) - }) + const quotes = await swapsController.fetchAndSetQuotes(undefined); + assert.strictEqual(quotes, null); + }); it('calls fetchTradesInfo with the given fetchParams and returns the correct quotes', async function () { - fetchTradesInfoStub.resolves(getMockQuotes()) - fetchSwapsQuoteRefreshTimeStub.resolves(getMockQuoteRefreshTime()) + fetchTradesInfoStub.resolves(getMockQuotes()); + fetchSwapsQuoteRefreshTimeStub.resolves(getMockQuoteRefreshTime()); // Make it so approval is not required sandbox .stub(swapsController, '_getERC20Allowance') - .resolves(ethers.BigNumber.from(1)) + .resolves(ethers.BigNumber.from(1)); const [newQuotes] = await swapsController.fetchAndSetQuotes( MOCK_FETCH_PARAMS, MOCK_FETCH_METADATA, - ) + ); assert.deepStrictEqual(newQuotes[TEST_AGG_ID_BEST], { ...getMockQuotes()[TEST_AGG_ID_BEST], @@ -678,26 +681,26 @@ describe('SwapsController', function () { overallValueOfQuote: '-33554382', metaMaskFeeInEth: '0.5050505050505050505', ethValueOfTokens: '50', - }) + }); assert.strictEqual( fetchTradesInfoStub.calledOnceWithExactly(MOCK_FETCH_PARAMS), true, - ) - }) + ); + }); it('performs the allowance check', async function () { - fetchTradesInfoStub.resolves(getMockQuotes()) - fetchSwapsQuoteRefreshTimeStub.resolves(getMockQuoteRefreshTime()) + fetchTradesInfoStub.resolves(getMockQuotes()); + fetchSwapsQuoteRefreshTimeStub.resolves(getMockQuoteRefreshTime()); // Make it so approval is not required const allowanceStub = sandbox .stub(swapsController, '_getERC20Allowance') - .resolves(ethers.BigNumber.from(1)) + .resolves(ethers.BigNumber.from(1)); await swapsController.fetchAndSetQuotes( MOCK_FETCH_PARAMS, MOCK_FETCH_METADATA, - ) + ); assert.strictEqual( allowanceStub.calledOnceWithExactly( @@ -705,55 +708,55 @@ describe('SwapsController', function () { MOCK_FETCH_PARAMS.fromAddress, ), true, - ) - }) + ); + }); it('gets the gas limit if approval is required', async function () { - fetchTradesInfoStub.resolves(MOCK_QUOTES_APPROVAL_REQUIRED) - fetchSwapsQuoteRefreshTimeStub.resolves(getMockQuoteRefreshTime()) + fetchTradesInfoStub.resolves(MOCK_QUOTES_APPROVAL_REQUIRED); + fetchSwapsQuoteRefreshTimeStub.resolves(getMockQuoteRefreshTime()); // Ensure approval is required sandbox .stub(swapsController, '_getERC20Allowance') - .resolves(ethers.BigNumber.from(0)) + .resolves(ethers.BigNumber.from(0)); - const timedoutGasReturnResult = { gasLimit: 1000000 } + const timedoutGasReturnResult = { gasLimit: 1000000 }; const timedoutGasReturnStub = sandbox .stub(swapsController, 'timedoutGasReturn') - .resolves(timedoutGasReturnResult) + .resolves(timedoutGasReturnResult); await swapsController.fetchAndSetQuotes( MOCK_FETCH_PARAMS, MOCK_FETCH_METADATA, - ) + ); // Mocked quotes approvalNeeded is null, so it will only be called with the gas assert.strictEqual( timedoutGasReturnStub.calledOnceWithExactly(MOCK_APPROVAL_NEEDED), true, - ) - }) + ); + }); it('marks the best quote', async function () { - fetchTradesInfoStub.resolves(getMockQuotes()) - fetchSwapsQuoteRefreshTimeStub.resolves(getMockQuoteRefreshTime()) + fetchTradesInfoStub.resolves(getMockQuotes()); + fetchSwapsQuoteRefreshTimeStub.resolves(getMockQuoteRefreshTime()); // Make it so approval is not required sandbox .stub(swapsController, '_getERC20Allowance') - .resolves(ethers.BigNumber.from(1)) + .resolves(ethers.BigNumber.from(1)); const [newQuotes, topAggId] = await swapsController.fetchAndSetQuotes( MOCK_FETCH_PARAMS, MOCK_FETCH_METADATA, - ) + ); - assert.strictEqual(topAggId, TEST_AGG_ID_BEST) - assert.strictEqual(newQuotes[topAggId].isBestQuote, true) - }) + assert.strictEqual(topAggId, TEST_AGG_ID_BEST); + assert.strictEqual(newQuotes[topAggId].isBestQuote, true); + }); it('selects the best quote', async function () { - const bestAggId = 'bestAggId' + const bestAggId = 'bestAggId'; // Clone the existing mock quote and increase destination amount const bestQuote = { @@ -764,101 +767,101 @@ describe('SwapsController', function () { ) .add((100e18).toString()) .toString(), - } - const quotes = { ...getMockQuotes(), [bestAggId]: bestQuote } - fetchTradesInfoStub.resolves(quotes) - fetchSwapsQuoteRefreshTimeStub.resolves(getMockQuoteRefreshTime()) + }; + const quotes = { ...getMockQuotes(), [bestAggId]: bestQuote }; + fetchTradesInfoStub.resolves(quotes); + fetchSwapsQuoteRefreshTimeStub.resolves(getMockQuoteRefreshTime()); // Make it so approval is not required sandbox .stub(swapsController, '_getERC20Allowance') - .resolves(ethers.BigNumber.from(1)) + .resolves(ethers.BigNumber.from(1)); const [newQuotes, topAggId] = await swapsController.fetchAndSetQuotes( MOCK_FETCH_PARAMS, MOCK_FETCH_METADATA, - ) + ); - assert.strictEqual(topAggId, bestAggId) - assert.strictEqual(newQuotes[topAggId].isBestQuote, true) - }) + assert.strictEqual(topAggId, bestAggId); + assert.strictEqual(newQuotes[topAggId].isBestQuote, true); + }); it('does not mark as best quote if no conversion rate exists for destination token', async function () { - fetchTradesInfoStub.resolves(getMockQuotes()) - fetchSwapsQuoteRefreshTimeStub.resolves(getMockQuoteRefreshTime()) + fetchTradesInfoStub.resolves(getMockQuotes()); + fetchSwapsQuoteRefreshTimeStub.resolves(getMockQuoteRefreshTime()); // Make it so approval is not required sandbox .stub(swapsController, '_getERC20Allowance') - .resolves(ethers.BigNumber.from(1)) + .resolves(ethers.BigNumber.from(1)); swapsController.tokenRatesStore.updateState({ contractExchangeRates: {}, - }) + }); const [newQuotes, topAggId] = await swapsController.fetchAndSetQuotes( MOCK_FETCH_PARAMS, MOCK_FETCH_METADATA, - ) + ); - assert.strictEqual(newQuotes[topAggId].isBestQuote, undefined) - }) - }) + assert.strictEqual(newQuotes[topAggId].isBestQuote, undefined); + }); + }); describe('resetSwapsState', function () { it('resets the swaps state correctly', function () { - const { swapsState: old } = swapsController.store.getState() - swapsController.resetSwapsState() - const { swapsState } = swapsController.store.getState() + const { swapsState: old } = swapsController.store.getState(); + swapsController.resetSwapsState(); + const { swapsState } = swapsController.store.getState(); assert.deepStrictEqual(swapsState, { ...EMPTY_INIT_STATE.swapsState, tokens: old.tokens, swapsQuoteRefreshTime: old.swapsQuoteRefreshTime, - }) - }) + }); + }); it('clears polling timeout', function () { swapsController.pollingTimeout = setTimeout( () => assert.fail(), 1000000, - ) - swapsController.resetSwapsState() - assert.strictEqual(swapsController.pollingTimeout._idleTimeout, -1) - }) - }) + ); + swapsController.resetSwapsState(); + assert.strictEqual(swapsController.pollingTimeout._idleTimeout, -1); + }); + }); describe('stopPollingForQuotes', function () { it('clears polling timeout', function () { swapsController.pollingTimeout = setTimeout( () => assert.fail(), 1000000, - ) - swapsController.stopPollingForQuotes() - assert.strictEqual(swapsController.pollingTimeout._idleTimeout, -1) - }) + ); + swapsController.stopPollingForQuotes(); + assert.strictEqual(swapsController.pollingTimeout._idleTimeout, -1); + }); it('resets quotes state correctly', function () { - swapsController.stopPollingForQuotes() - const { swapsState } = swapsController.store.getState() - assert.deepStrictEqual(swapsState.quotes, {}) - assert.strictEqual(swapsState.quotesLastFetched, null) - }) - }) + swapsController.stopPollingForQuotes(); + const { swapsState } = swapsController.store.getState(); + assert.deepStrictEqual(swapsState.quotes, {}); + assert.strictEqual(swapsState.quotesLastFetched, null); + }); + }); describe('resetPostFetchState', function () { it('clears polling timeout', function () { swapsController.pollingTimeout = setTimeout( () => assert.fail(), 1000000, - ) - swapsController.resetPostFetchState() - assert.strictEqual(swapsController.pollingTimeout._idleTimeout, -1) - }) + ); + swapsController.resetPostFetchState(); + assert.strictEqual(swapsController.pollingTimeout._idleTimeout, -1); + }); it('updates state correctly', function () { - const tokens = 'test' - const fetchParams = 'test' - const swapsFeatureIsLive = false - const swapsQuoteRefreshTime = 0 + const tokens = 'test'; + const fetchParams = 'test'; + const swapsFeatureIsLive = false; + const swapsQuoteRefreshTime = 0; swapsController.store.updateState({ swapsState: { tokens, @@ -866,28 +869,28 @@ describe('SwapsController', function () { swapsFeatureIsLive, swapsQuoteRefreshTime, }, - }) + }); - swapsController.resetPostFetchState() + swapsController.resetPostFetchState(); - const { swapsState } = swapsController.store.getState() + const { swapsState } = swapsController.store.getState(); assert.deepStrictEqual(swapsState, { ...EMPTY_INIT_STATE.swapsState, tokens, fetchParams, swapsFeatureIsLive, swapsQuoteRefreshTime, - }) - }) - }) + }); + }); + }); describe('_setupSwapsLivenessFetching ', function () { - let clock - const EXPECTED_TIME = 600000 + let clock; + const EXPECTED_TIME = 600000; const getLivenessState = () => { - return swapsController.store.getState().swapsState.swapsFeatureIsLive - } + return swapsController.store.getState().swapsState.swapsFeatureIsLive; + }; // We have to do this to overwrite window.navigator.onLine const stubWindow = () => { @@ -896,104 +899,104 @@ describe('SwapsController', function () { navigator: { onLine: true }, dispatchEvent: window.dispatchEvent, Event: window.Event, - }) - } + }); + }; beforeEach(function () { - stubWindow() - clock = sandbox.useFakeTimers() - sandbox.spy(clock, 'setInterval') + stubWindow(); + clock = sandbox.useFakeTimers(); + sandbox.spy(clock, 'setInterval'); sandbox .stub(SwapsController.prototype, '_fetchAndSetSwapsLiveness') - .resolves(undefined) + .resolves(undefined); - sandbox.spy(SwapsController.prototype, '_setupSwapsLivenessFetching') + sandbox.spy(SwapsController.prototype, '_setupSwapsLivenessFetching'); - sandbox.spy(window, 'addEventListener') - }) + sandbox.spy(window, 'addEventListener'); + }); afterEach(function () { - sandbox.restore() - }) + sandbox.restore(); + }); it('calls _setupSwapsLivenessFetching in constructor', function () { - swapsController = getSwapsController() + swapsController = getSwapsController(); assert.ok( swapsController._setupSwapsLivenessFetching.calledOnce, 'should have called _setupSwapsLivenessFetching once', - ) - assert.ok(window.addEventListener.calledWith('online')) - assert.ok(window.addEventListener.calledWith('offline')) + ); + assert.ok(window.addEventListener.calledWith('online')); + assert.ok(window.addEventListener.calledWith('offline')); assert.ok( clock.setInterval.calledOnceWithExactly( sinon.match.func, EXPECTED_TIME, ), 'should have set an interval', - ) - }) + ); + }); it('handles browser being offline on boot, then coming online', async function () { - window.navigator.onLine = false + window.navigator.onLine = false; - swapsController = getSwapsController() + swapsController = getSwapsController(); assert.ok( swapsController._setupSwapsLivenessFetching.calledOnce, 'should have called _setupSwapsLivenessFetching once', - ) + ); assert.ok( swapsController._fetchAndSetSwapsLiveness.notCalled, 'should not have called _fetchAndSetSwapsLiveness', - ) + ); assert.ok( clock.setInterval.notCalled, 'should not have set an interval', - ) + ); assert.strictEqual( getLivenessState(), false, 'swaps feature should be disabled', - ) + ); const fetchPromise = new Promise((resolve) => { - const originalFunction = swapsController._fetchAndSetSwapsLiveness + const originalFunction = swapsController._fetchAndSetSwapsLiveness; swapsController._fetchAndSetSwapsLiveness = () => { - originalFunction() - resolve() - swapsController._fetchAndSetSwapsLiveness = originalFunction - } - }) + originalFunction(); + resolve(); + swapsController._fetchAndSetSwapsLiveness = originalFunction; + }; + }); // browser comes online - window.navigator.onLine = true - window.dispatchEvent(new window.Event('online')) - await fetchPromise + window.navigator.onLine = true; + window.dispatchEvent(new window.Event('online')); + await fetchPromise; assert.ok( swapsController._fetchAndSetSwapsLiveness.calledOnce, 'should have called _fetchAndSetSwapsLiveness once', - ) + ); assert.ok( clock.setInterval.calledOnceWithExactly( sinon.match.func, EXPECTED_TIME, ), 'should have set an interval', - ) - }) + ); + }); it('clears interval if browser goes offline', async function () { - swapsController = getSwapsController() + swapsController = getSwapsController(); // set feature to live - const { swapsState } = swapsController.store.getState() + const { swapsState } = swapsController.store.getState(); swapsController.store.updateState({ swapsState: { ...swapsState, swapsFeatureIsLive: true }, - }) + }); - sandbox.spy(swapsController.store, 'updateState') + sandbox.spy(swapsController.store, 'updateState'); assert.ok( clock.setInterval.calledOnceWithExactly( @@ -1001,172 +1004,172 @@ describe('SwapsController', function () { EXPECTED_TIME, ), 'should have set an interval', - ) + ); const clearIntervalPromise = new Promise((resolve) => { - const originalFunction = clock.clearInterval + const originalFunction = clock.clearInterval; clock.clearInterval = (intervalId) => { - originalFunction(intervalId) - clock.clearInterval = originalFunction - resolve() - } - }) + originalFunction(intervalId); + clock.clearInterval = originalFunction; + resolve(); + }; + }); // browser goes offline - window.navigator.onLine = false - window.dispatchEvent(new window.Event('offline')) + window.navigator.onLine = false; + window.dispatchEvent(new window.Event('offline')); // if this resolves, clearInterval was called - await clearIntervalPromise + await clearIntervalPromise; assert.ok( swapsController._fetchAndSetSwapsLiveness.calledOnce, 'should have called _fetchAndSetSwapsLiveness once', - ) + ); assert.ok( swapsController.store.updateState.calledOnce, 'should have called updateState once', - ) + ); assert.strictEqual( getLivenessState(), false, 'swaps feature should be disabled', - ) - }) - }) + ); + }); + }); describe('_fetchAndSetSwapsLiveness', function () { const getLivenessState = () => { - return swapsController.store.getState().swapsState.swapsFeatureIsLive - } + return swapsController.store.getState().swapsState.swapsFeatureIsLive; + }; beforeEach(function () { - fetchSwapsFeatureLivenessStub.reset() - sandbox.stub(SwapsController.prototype, '_setupSwapsLivenessFetching') - swapsController = getSwapsController() - }) + fetchSwapsFeatureLivenessStub.reset(); + sandbox.stub(SwapsController.prototype, '_setupSwapsLivenessFetching'); + swapsController = getSwapsController(); + }); afterEach(function () { - sandbox.restore() - }) + sandbox.restore(); + }); it('fetches feature liveness as expected when API is live', async function () { - fetchSwapsFeatureLivenessStub.resolves(true) + fetchSwapsFeatureLivenessStub.resolves(true); assert.strictEqual( getLivenessState(), false, 'liveness should be false on boot', - ) + ); - await swapsController._fetchAndSetSwapsLiveness() + await swapsController._fetchAndSetSwapsLiveness(); assert.ok( fetchSwapsFeatureLivenessStub.calledOnce, 'should have called fetch function once', - ) + ); assert.strictEqual( getLivenessState(), true, 'liveness should be true after call', - ) - }) + ); + }); it('does not update state if fetched value is same as state value', async function () { - fetchSwapsFeatureLivenessStub.resolves(false) - sandbox.spy(swapsController.store, 'updateState') + fetchSwapsFeatureLivenessStub.resolves(false); + sandbox.spy(swapsController.store, 'updateState'); assert.strictEqual( getLivenessState(), false, 'liveness should be false on boot', - ) + ); - await swapsController._fetchAndSetSwapsLiveness() + await swapsController._fetchAndSetSwapsLiveness(); assert.ok( fetchSwapsFeatureLivenessStub.calledOnce, 'should have called fetch function once', - ) + ); assert.ok( swapsController.store.updateState.notCalled, 'should not have called store.updateState', - ) + ); assert.strictEqual( getLivenessState(), false, 'liveness should remain false after call', - ) - }) + ); + }); it('tries three times before giving up if fetching fails', async function () { - const clock = sandbox.useFakeTimers() - fetchSwapsFeatureLivenessStub.rejects(new Error('foo')) - sandbox.spy(swapsController.store, 'updateState') + const clock = sandbox.useFakeTimers(); + fetchSwapsFeatureLivenessStub.rejects(new Error('foo')); + sandbox.spy(swapsController.store, 'updateState'); assert.strictEqual( getLivenessState(), false, 'liveness should be false on boot', - ) + ); - swapsController._fetchAndSetSwapsLiveness() - await clock.runAllAsync() + swapsController._fetchAndSetSwapsLiveness(); + await clock.runAllAsync(); assert.ok( fetchSwapsFeatureLivenessStub.calledThrice, 'should have called fetch function three times', - ) + ); assert.ok( swapsController.store.updateState.notCalled, 'should not have called store.updateState', - ) + ); assert.strictEqual( getLivenessState(), false, 'liveness should remain false after call', - ) - }) + ); + }); it('sets state after fetching on successful retry', async function () { - const clock = sandbox.useFakeTimers() - fetchSwapsFeatureLivenessStub.onCall(0).rejects(new Error('foo')) - fetchSwapsFeatureLivenessStub.onCall(1).rejects(new Error('foo')) - fetchSwapsFeatureLivenessStub.onCall(2).resolves(true) + const clock = sandbox.useFakeTimers(); + fetchSwapsFeatureLivenessStub.onCall(0).rejects(new Error('foo')); + fetchSwapsFeatureLivenessStub.onCall(1).rejects(new Error('foo')); + fetchSwapsFeatureLivenessStub.onCall(2).resolves(true); assert.strictEqual( getLivenessState(), false, 'liveness should be false on boot', - ) + ); - swapsController._fetchAndSetSwapsLiveness() - await clock.runAllAsync() + swapsController._fetchAndSetSwapsLiveness(); + await clock.runAllAsync(); assert.strictEqual( fetchSwapsFeatureLivenessStub.callCount, 3, 'should have called fetch function three times', - ) + ); assert.strictEqual( getLivenessState(), true, 'liveness should be true after call', - ) - }) - }) - }) + ); + }); + }); + }); describe('utils', function () { describe('getMedianEthValueQuote', function () { - const { getMedianEthValueQuote } = utils + const { getMedianEthValueQuote } = utils; it('calculates median correctly with uneven sample', function () { const expectedResult = { ethFee: '10', metaMaskFeeInEth: '5', ethValueOfTokens: '0.3', - } + }; const values = [ { overallValueOfQuote: '3', @@ -1186,23 +1189,23 @@ describe('SwapsController', function () { metaMaskFeeInEth: '6', ethValueOfTokens: '0.6', }, - ] + ]; - const median = getMedianEthValueQuote(values) + const median = getMedianEthValueQuote(values); assert.deepEqual( median, expectedResult, 'should have returned correct median quote object', - ) - }) + ); + }); it('calculates median correctly with even sample', function () { const expectedResult = { ethFee: '20', metaMaskFeeInEth: '6.5', ethValueOfTokens: '0.25', - } + }; const values = [ { overallValueOfQuote: '3', @@ -1228,22 +1231,22 @@ describe('SwapsController', function () { metaMaskFeeInEth: '6', ethValueOfTokens: '0.6', }, - ] - const median = getMedianEthValueQuote(values) + ]; + const median = getMedianEthValueQuote(values); assert.deepEqual( median, expectedResult, 'should have returned correct median quote object', - ) - }) + ); + }); it('calculates median correctly with an uneven sample where multiple quotes have the median overall value', function () { const expectedResult = { ethFee: '2', metaMaskFeeInEth: '0.5', ethValueOfTokens: '5', - } + }; const values = [ { @@ -1288,22 +1291,22 @@ describe('SwapsController', function () { ethFee: '2', metaMaskFeeInEth: '0.8', }, - ] - const median = getMedianEthValueQuote(values) + ]; + const median = getMedianEthValueQuote(values); assert.deepEqual( median, expectedResult, 'should have returned correct median quote object', - ) - }) + ); + }); it('calculates median correctly with an even sample where multiple quotes have the same overall value as either of the two middle values', function () { const expectedResult = { ethFee: '2', metaMaskFeeInEth: '0.55', ethValueOfTokens: '5.5', - } + }; const values = [ { @@ -1342,35 +1345,35 @@ describe('SwapsController', function () { ethFee: '2', metaMaskFeeInEth: '0.8', }, - ] - const median = getMedianEthValueQuote(values) + ]; + const median = getMedianEthValueQuote(values); assert.deepEqual( median, expectedResult, 'should have returned correct median quote object', - ) - }) + ); + }); it('throws on empty or non-array sample', function () { assert.throws( () => getMedianEthValueQuote([]), 'should throw on empty array', - ) + ); assert.throws( () => getMedianEthValueQuote(), 'should throw on non-array param', - ) + ); assert.throws( () => getMedianEthValueQuote({}), 'should throw on non-array param', - ) - }) - }) - }) -}) + ); + }); + }); + }); +}); function getMockQuotes() { return { @@ -1475,7 +1478,7 @@ function getMockQuotes() { }, fee: 1, }, - } + }; } function getTopQuoteAndSavingsMockQuotes() { @@ -1572,11 +1575,11 @@ function getTopQuoteAndSavingsMockQuotes() { }, fee: 1, }, - } + }; } function getTopQuoteAndSavingsBaseExpectedResults() { - const baseTestInput = getTopQuoteAndSavingsMockQuotes() + const baseTestInput = getTopQuoteAndSavingsMockQuotes(); return { [TEST_AGG_ID_1]: { ...baseTestInput[TEST_AGG_ID_1], @@ -1628,9 +1631,9 @@ function getTopQuoteAndSavingsBaseExpectedResults() { metaMaskFeeInEth: '0.0195', ethValueOfTokens: '1.9305', }, - } + }; } function getMockQuoteRefreshTime() { - return 45000 + return 45000; } diff --git a/test/unit/app/controllers/token-rates-controller.js b/test/unit/app/controllers/token-rates-controller.js index 58e0009a1..c1f69d54f 100644 --- a/test/unit/app/controllers/token-rates-controller.js +++ b/test/unit/app/controllers/token-rates-controller.js @@ -1,25 +1,25 @@ -import assert from 'assert' -import sinon from 'sinon' -import { ObservableStore } from '@metamask/obs-store' -import TokenRatesController from '../../../../app/scripts/controllers/token-rates' +import assert from 'assert'; +import sinon from 'sinon'; +import { ObservableStore } from '@metamask/obs-store'; +import TokenRatesController from '../../../../app/scripts/controllers/token-rates'; describe('TokenRatesController', function () { it('should listen for preferences store updates', function () { - const preferences = new ObservableStore({ tokens: [] }) - preferences.putState({ tokens: ['foo'] }) - const controller = new TokenRatesController({ preferences }) - assert.deepEqual(controller._tokens, ['foo']) - }) + const preferences = new ObservableStore({ tokens: [] }); + preferences.putState({ tokens: ['foo'] }); + const controller = new TokenRatesController({ preferences }); + assert.deepEqual(controller._tokens, ['foo']); + }); it('should poll on correct interval', async function () { - const stub = sinon.stub(global, 'setInterval') - const preferences = new ObservableStore({ tokens: [] }) - preferences.putState({ tokens: ['foo'] }) - const controller = new TokenRatesController({ preferences }) - controller.start(1337) + const stub = sinon.stub(global, 'setInterval'); + const preferences = new ObservableStore({ tokens: [] }); + preferences.putState({ tokens: ['foo'] }); + const controller = new TokenRatesController({ preferences }); + controller.start(1337); - assert.strictEqual(stub.getCall(0).args[1], 1337) - stub.restore() - controller.stop() - }) -}) + assert.strictEqual(stub.getCall(0).args[1], 1337); + stub.restore(); + controller.stop(); + }); +}); diff --git a/test/unit/app/controllers/transactions/pending-tx-tracker-test.js b/test/unit/app/controllers/transactions/pending-tx-tracker-test.js index 6252da35a..db0f4d1d3 100644 --- a/test/unit/app/controllers/transactions/pending-tx-tracker-test.js +++ b/test/unit/app/controllers/transactions/pending-tx-tracker-test.js @@ -1,13 +1,13 @@ -import { strict as assert } from 'assert' -import sinon from 'sinon' -import BN from 'bn.js' -import PendingTransactionTracker from '../../../../../app/scripts/controllers/transactions/pending-tx-tracker' -import { TRANSACTION_STATUSES } from '../../../../../shared/constants/transaction' +import { strict as assert } from 'assert'; +import sinon from 'sinon'; +import BN from 'bn.js'; +import PendingTransactionTracker from '../../../../../app/scripts/controllers/transactions/pending-tx-tracker'; +import { TRANSACTION_STATUSES } from '../../../../../shared/constants/transaction'; describe('PendingTransactionTracker', function () { describe('#resubmitPendingTxs', function () { it('should return early if there are no pending transactions', async function () { - const getPendingTransactions = sinon.stub().returns([]) + const getPendingTransactions = sinon.stub().returns([]); const pendingTxTracker = new PendingTransactionTracker({ query: { getTransactionReceipt: sinon.stub(), @@ -22,20 +22,20 @@ describe('PendingTransactionTracker', function () { approveTransaction: sinon.spy(), publishTransaction: sinon.spy(), confirmTransaction: sinon.spy(), - }) - const resubmitTx = sinon.stub(pendingTxTracker, '_resubmitTx').rejects() - const warningListener = sinon.spy() + }); + const resubmitTx = sinon.stub(pendingTxTracker, '_resubmitTx').rejects(); + const warningListener = sinon.spy(); - pendingTxTracker.on('tx:warning', warningListener) - await pendingTxTracker.resubmitPendingTxs('0x1') + pendingTxTracker.on('tx:warning', warningListener); + await pendingTxTracker.resubmitPendingTxs('0x1'); assert.ok( getPendingTransactions.calledOnceWithExactly(), 'should call getPendingTransaction', - ) - assert.ok(resubmitTx.notCalled, 'should NOT call _resubmitTx') - assert.ok(warningListener.notCalled, "should NOT emit 'tx:warning'") - }) + ); + assert.ok(resubmitTx.notCalled, 'should NOT call _resubmitTx'); + assert.ok(warningListener.notCalled, "should NOT emit 'tx:warning'"); + }); it('should resubmit each pending transaction', async function () { const getPendingTransactions = sinon.stub().returns([ @@ -45,7 +45,7 @@ describe('PendingTransactionTracker', function () { { id: 2, }, - ]) + ]); const pendingTxTracker = new PendingTransactionTracker({ query: { getTransactionReceipt: sinon.stub(), @@ -60,27 +60,27 @@ describe('PendingTransactionTracker', function () { approveTransaction: sinon.spy(), publishTransaction: sinon.spy(), confirmTransaction: sinon.spy(), - }) - const resubmitTx = sinon.stub(pendingTxTracker, '_resubmitTx').resolves() - const warningListener = sinon.spy() + }); + const resubmitTx = sinon.stub(pendingTxTracker, '_resubmitTx').resolves(); + const warningListener = sinon.spy(); - pendingTxTracker.on('tx:warning', warningListener) - await pendingTxTracker.resubmitPendingTxs('0x1') + pendingTxTracker.on('tx:warning', warningListener); + await pendingTxTracker.resubmitPendingTxs('0x1'); assert.ok( getPendingTransactions.calledOnceWithExactly(), 'should call getPendingTransaction', - ) - assert.ok(resubmitTx.calledTwice, 'should call _resubmitTx') - assert.ok(warningListener.notCalled, "should NOT emit 'tx:warning'") - }) + ); + assert.ok(resubmitTx.calledTwice, 'should call _resubmitTx'); + assert.ok(warningListener.notCalled, "should NOT emit 'tx:warning'"); + }); it("should NOT emit 'tx:warning' for known failed resubmission", async function () { const getPendingTransactions = sinon.stub().returns([ { id: 1, }, - ]) + ]); const pendingTxTracker = new PendingTransactionTracker({ query: { getTransactionReceipt: sinon.stub(), @@ -95,29 +95,29 @@ describe('PendingTransactionTracker', function () { approveTransaction: sinon.spy(), publishTransaction: sinon.spy(), confirmTransaction: sinon.spy(), - }) + }); const resubmitTx = sinon .stub(pendingTxTracker, '_resubmitTx') - .rejects({ message: 'known transaction' }) - const warningListener = sinon.spy() + .rejects({ message: 'known transaction' }); + const warningListener = sinon.spy(); - pendingTxTracker.on('tx:warning', warningListener) - await pendingTxTracker.resubmitPendingTxs('0x1') + pendingTxTracker.on('tx:warning', warningListener); + await pendingTxTracker.resubmitPendingTxs('0x1'); assert.ok( getPendingTransactions.calledOnceWithExactly(), 'should call getPendingTransaction', - ) - assert.ok(resubmitTx.calledOnce, 'should call _resubmitTx') - assert.ok(warningListener.notCalled, "should NOT emit 'tx:warning'") - }) + ); + assert.ok(resubmitTx.calledOnce, 'should call _resubmitTx'); + assert.ok(warningListener.notCalled, "should NOT emit 'tx:warning'"); + }); it("should emit 'tx:warning' for unknown failed resubmission", async function () { const getPendingTransactions = sinon.stub().returns([ { id: 1, }, - ]) + ]); const pendingTxTracker = new PendingTransactionTracker({ query: { getTransactionReceipt: sinon.stub(), @@ -132,23 +132,23 @@ describe('PendingTransactionTracker', function () { approveTransaction: sinon.spy(), publishTransaction: sinon.spy(), confirmTransaction: sinon.spy(), - }) + }); const resubmitTx = sinon .stub(pendingTxTracker, '_resubmitTx') - .rejects({ message: 'who dis' }) - const warningListener = sinon.spy() + .rejects({ message: 'who dis' }); + const warningListener = sinon.spy(); - pendingTxTracker.on('tx:warning', warningListener) - await pendingTxTracker.resubmitPendingTxs('0x1') + pendingTxTracker.on('tx:warning', warningListener); + await pendingTxTracker.resubmitPendingTxs('0x1'); assert.ok( getPendingTransactions.calledOnceWithExactly(), 'should call getPendingTransaction', - ) - assert.ok(resubmitTx.calledOnce, 'should call _resubmitTx') - assert.ok(warningListener.calledOnce, "should emit 'tx:warning'") - }) - }) + ); + assert.ok(resubmitTx.calledOnce, 'should call _resubmitTx'); + assert.ok(warningListener.calledOnce, "should emit 'tx:warning'"); + }); + }); describe('#updatePendingTxs', function () { it('should call _checkPendingTx for each pending transaction', async function () { @@ -165,48 +165,48 @@ describe('PendingTransactionTracker', function () { history: [{}], rawTx: '0xf86c808504a817c800827b0d940c62bb85faa3311a998d3aba8098c1235c564966880de0b6b3a7640000802aa08ff665feb887a25d4099e40e11f0fef93ee9608f404bd3f853dd9e84ed3317a6a02ec9d3d1d6e176d4d2593dd760e74ccac753e6a0ea0d00cc9789d0d7ff1f471d', - } - const txList = [1, 2, 3].map((id) => ({ ...txMeta, id })) + }; + const txList = [1, 2, 3].map((id) => ({ ...txMeta, id })); const pendingTxTracker = new PendingTransactionTracker({ query: { getTransactionReceipt: sinon.stub(), }, nonceTracker: { getGlobalLock: async () => { - return { releaseLock: () => undefined } + return { releaseLock: () => undefined }; }, }, getPendingTransactions: () => txList, getCompletedTransactions: () => { - return [] + return []; }, publishTransaction: () => undefined, confirmTransaction: () => undefined, - }) + }); const checkPendingTxStub = sinon .stub(pendingTxTracker, '_checkPendingTx') - .resolves() - await pendingTxTracker.updatePendingTxs() + .resolves(); + await pendingTxTracker.updatePendingTxs(); - assert.ok(checkPendingTxStub.calledThrice) + assert.ok(checkPendingTxStub.calledThrice); assert.ok( checkPendingTxStub.firstCall.calledWithExactly( sinon.match.has('id', 1), ), - ) + ); assert.ok( checkPendingTxStub.secondCall.calledWithExactly( sinon.match.has('id', 2), ), - ) + ); assert.ok( checkPendingTxStub.thirdCall.calledWithExactly( sinon.match.has('id', 3), ), - ) - }) - }) + ); + }); + }); describe('#_resubmitTx', function () { it('should publish a new transaction', async function () { @@ -223,9 +223,9 @@ describe('PendingTransactionTracker', function () { history: [{}], rawTx: '0xf86c808504a817c80086a02ec9d3d1d6e176d4d2593dd760e74ccac753e6a0ea0d00cc9789d0d7ff1f471d', - } - const approveTransaction = sinon.spy() - const publishTransaction = sinon.spy() + }; + const approveTransaction = sinon.spy(); + const publishTransaction = sinon.spy(); const pendingTxTracker = new PendingTransactionTracker({ query: { getTransactionReceipt: sinon.stub(), @@ -240,19 +240,19 @@ describe('PendingTransactionTracker', function () { approveTransaction, publishTransaction, confirmTransaction: sinon.spy(), - }) + }); - await pendingTxTracker._resubmitTx(txMeta) + await pendingTxTracker._resubmitTx(txMeta); assert.ok( publishTransaction.calledOnceWithExactly(txMeta.rawTx), 'should call publish transaction with the rawTx', - ) + ); assert.ok( approveTransaction.notCalled, 'should NOT try to approve transaction', - ) - }) + ); + }); it('should publish the given transaction if more than 2**retryCount blocks have passed', async function () { const txMeta = { @@ -270,9 +270,9 @@ describe('PendingTransactionTracker', function () { '0xf86c808504a817c800827b0d940c62bb85faa3311a996e176d4d2593dd760e74ccac753e6a0ea0d00cc9789d0d7ff1f471d', retryCount: 4, firstRetryBlockNumber: '0x1', - } - const approveTransaction = sinon.spy() - const publishTransaction = sinon.spy() + }; + const approveTransaction = sinon.spy(); + const publishTransaction = sinon.spy(); const pendingTxTracker = new PendingTransactionTracker({ query: { getTransactionReceipt: sinon.stub(), @@ -287,19 +287,19 @@ describe('PendingTransactionTracker', function () { publishTransaction, approveTransaction, confirmTransaction: sinon.spy(), - }) + }); - await pendingTxTracker._resubmitTx(txMeta, '0x11' /* 16 */) + await pendingTxTracker._resubmitTx(txMeta, '0x11' /* 16 */); assert.ok( publishTransaction.calledOnceWithExactly(txMeta.rawTx), 'should try to publish transaction', - ) + ); assert.ok( approveTransaction.notCalled, 'should NOT try to approve transaction', - ) - }) + ); + }); it('should NOT publish the given transaction if fewer than 2**retryCount blocks have passed', async function () { const txMeta = { @@ -317,9 +317,9 @@ describe('PendingTransactionTracker', function () { '0xf86c808504a817c800827b0d940c62bb85faa3311a996e176d4d2593dd760e74ccac753e6a0ea0d00cc9789d0d7ff1f471d', retryCount: 4, firstRetryBlockNumber: '0x1', - } - const approveTransaction = sinon.spy() - const publishTransaction = sinon.spy() + }; + const approveTransaction = sinon.spy(); + const publishTransaction = sinon.spy(); const pendingTxTracker = new PendingTransactionTracker({ query: { getTransactionReceipt: sinon.stub(), @@ -334,23 +334,23 @@ describe('PendingTransactionTracker', function () { publishTransaction, approveTransaction, confirmTransaction: sinon.spy(), - }) + }); - await pendingTxTracker._resubmitTx(txMeta, '0x5') + await pendingTxTracker._resubmitTx(txMeta, '0x5'); assert.ok( publishTransaction.notCalled, 'should NOT try to publish transaction', - ) + ); assert.ok( approveTransaction.notCalled, 'should NOT try to approve transaction', - ) - }) + ); + }); it('should call approveTransaction if the tx is not yet signed', async function () { - const approveTransaction = sinon.spy() - const publishTransaction = sinon.spy() + const approveTransaction = sinon.spy(); + const publishTransaction = sinon.spy(); const pendingTxTracker = new PendingTransactionTracker({ query: { getTransactionReceipt: sinon.stub(), @@ -365,24 +365,24 @@ describe('PendingTransactionTracker', function () { approveTransaction, publishTransaction, confirmTransaction: sinon.spy(), - }) + }); - await pendingTxTracker._resubmitTx({ id: 40 }) + await pendingTxTracker._resubmitTx({ id: 40 }); assert.ok( approveTransaction.calledOnceWithExactly(40), 'should call approveTransaction with the tx ID', - ) + ); assert.ok( publishTransaction.notCalled, 'should NOT try to publish transaction', - ) - }) - }) + ); + }); + }); describe('#_checkIfTxWasDropped', function () { it('should return true when the given nonce is lower than the network nonce', async function () { - const nonceBN = new BN(2) + const nonceBN = new BN(2); const pendingTxTracker = new PendingTransactionTracker({ query: { getTransactionReceipt: sinon.stub(), @@ -397,9 +397,9 @@ describe('PendingTransactionTracker', function () { getCompletedTransactions: sinon.stub().returns([]), publishTransaction: sinon.spy(), confirmTransaction: sinon.spy(), - }) + }); - pendingTxTracker.DROPPED_BUFFER_COUNT = 0 + pendingTxTracker.DROPPED_BUFFER_COUNT = 0; assert.ok( await pendingTxTracker._checkIfTxWasDropped({ @@ -414,11 +414,11 @@ describe('PendingTransactionTracker', function () { }, rawTx: '0xf86c808504a817c800827b0d940c62bba0ea0d00cc9789d0d7ff1f471d', }), - ) - }) + ); + }); it('should return false when the given nonce is the network nonce', async function () { - const nonceBN = new BN(1) + const nonceBN = new BN(1); const pendingTxTracker = new PendingTransactionTracker({ query: { getTransactionReceipt: sinon.stub(), @@ -433,7 +433,7 @@ describe('PendingTransactionTracker', function () { getCompletedTransactions: sinon.stub().returns([]), publishTransaction: sinon.spy(), confirmTransaction: sinon.spy(), - }) + }); const dropped = await pendingTxTracker._checkIfTxWasDropped({ id: 1, @@ -447,11 +447,11 @@ describe('PendingTransactionTracker', function () { }, rawTx: '0xf86c808504a89e84ed3317a6a02ec9d3d1d6e176d4d2593dd760e74ccac753e6a0ea0d00cc9789d0d7ff1f471d', - }) + }); - assert.ok(!dropped, 'should be false') - }) - }) + assert.ok(!dropped, 'should be false'); + }); + }); describe('#_checkIfNonceIsTaken', function () { it('should return false if the given nonce is not taken', async function () { @@ -482,8 +482,8 @@ describe('PendingTransactionTracker', function () { rawTx: '0xf86c808507a6a02ec9d3d1d6e176d4d2593dd760e74ccac753e6a0ea0d00cc9789d0d7ff1f471d', }, - ] - const getCompletedTransactions = sinon.stub().returns(confirmedTxList) + ]; + const getCompletedTransactions = sinon.stub().returns(confirmedTxList); const pendingTxTracker = new PendingTransactionTracker({ query: sinon.spy(), nonceTracker: { @@ -495,7 +495,7 @@ describe('PendingTransactionTracker', function () { getCompletedTransactions, publishTransaction: sinon.spy(), confirmTransaction: sinon.spy(), - }) + }); const taken = await pendingTxTracker._checkIfNonceIsTaken({ txParams: { @@ -503,15 +503,15 @@ describe('PendingTransactionTracker', function () { nonce: '0x3', value: '0xfffff', }, - }) + }); assert.ok( getCompletedTransactions.calledOnceWithExactly( '0x1678a085c290ebd122dc42cba69373b5953b831d', ), - ) - assert.ok(!taken) - }) + ); + assert.ok(!taken); + }); it('should return true if the nonce is taken', async function () { const confirmedTxList = [ @@ -541,8 +541,8 @@ describe('PendingTransactionTracker', function () { rawTx: '0xf86c808504a817c800827b0d940c62bb760e74ccac753e6a0ea0d00cc9789d0d7ff1f471d', }, - ] - const getCompletedTransactions = sinon.stub().returns(confirmedTxList) + ]; + const getCompletedTransactions = sinon.stub().returns(confirmedTxList); const pendingTxTracker = new PendingTransactionTracker({ query: sinon.spy(), nonceTracker: { @@ -554,7 +554,7 @@ describe('PendingTransactionTracker', function () { getCompletedTransactions, publishTransaction: sinon.spy(), confirmTransaction: sinon.spy(), - }) + }); const taken = await pendingTxTracker._checkIfNonceIsTaken({ txParams: { @@ -562,16 +562,16 @@ describe('PendingTransactionTracker', function () { nonce: '0x2', value: '0xfffff', }, - }) + }); assert.ok( getCompletedTransactions.calledOnceWithExactly( '0x1678a085c290ebd122dc42cba69373b5953b831d', ), - ) - assert.ok(taken) - }) - }) + ); + assert.ok(taken); + }); + }); describe('#_checkPendingTx', function () { it("should emit 'tx:warning' if getTransactionReceipt rejects", async function () { @@ -587,8 +587,8 @@ describe('PendingTransactionTracker', function () { }, history: [{}], rawTx: '0xf86c808504a817c80082471d', - } - const nonceBN = new BN(2) + }; + const nonceBN = new BN(2); const pendingTxTracker = new PendingTransactionTracker({ query: { getTransactionReceipt: sinon.stub().rejects(), @@ -603,25 +603,28 @@ describe('PendingTransactionTracker', function () { getCompletedTransactions: sinon.stub().returns([]), publishTransaction: sinon.spy(), confirmTransaction: sinon.spy(), - }) + }); const listeners = { confirmed: sinon.spy(), dropped: sinon.spy(), failed: sinon.spy(), warning: sinon.spy(), - } + }; - pendingTxTracker.once('tx:confirmed', listeners.confirmed) - pendingTxTracker.once('tx:dropped', listeners.dropped) - pendingTxTracker.once('tx:failed', listeners.failed) - pendingTxTracker.once('tx:warning', listeners.warning) - await pendingTxTracker._checkPendingTx(txMeta) + pendingTxTracker.once('tx:confirmed', listeners.confirmed); + pendingTxTracker.once('tx:dropped', listeners.dropped); + pendingTxTracker.once('tx:failed', listeners.failed); + pendingTxTracker.once('tx:warning', listeners.warning); + await pendingTxTracker._checkPendingTx(txMeta); - assert.ok(listeners.dropped.notCalled, "should not emit 'tx:dropped") - assert.ok(listeners.confirmed.notCalled, "should not emit 'tx:confirmed'") - assert.ok(listeners.failed.notCalled, "should not emit 'tx:failed'") - assert.ok(listeners.warning.calledOnce, "should emit 'tx:warning'") - }) + assert.ok(listeners.dropped.notCalled, "should not emit 'tx:dropped"); + assert.ok( + listeners.confirmed.notCalled, + "should not emit 'tx:confirmed'", + ); + assert.ok(listeners.failed.notCalled, "should not emit 'tx:failed'"); + assert.ok(listeners.warning.calledOnce, "should emit 'tx:warning'"); + }); it('should NOT emit anything if the tx is already not submitted', async function () { const pendingTxTracker = new PendingTransactionTracker({ @@ -635,18 +638,18 @@ describe('PendingTransactionTracker', function () { getCompletedTransactions: sinon.stub().returns([]), publishTransaction: sinon.spy(), confirmTransaction: sinon.spy(), - }) + }); const listeners = { confirmed: sinon.spy(), dropped: sinon.spy(), failed: sinon.spy(), warning: sinon.spy(), - } + }; - pendingTxTracker.once('tx:confirmed', listeners.confirmed) - pendingTxTracker.once('tx:dropped', listeners.dropped) - pendingTxTracker.once('tx:failed', listeners.failed) - pendingTxTracker.once('tx:warning', listeners.warning) + pendingTxTracker.once('tx:confirmed', listeners.confirmed); + pendingTxTracker.once('tx:dropped', listeners.dropped); + pendingTxTracker.once('tx:failed', listeners.failed); + pendingTxTracker.once('tx:warning', listeners.warning); await pendingTxTracker._checkPendingTx({ status: TRANSACTION_STATUSES.CONFIRMED, history: [{}], @@ -654,13 +657,16 @@ describe('PendingTransactionTracker', function () { id: '456', value: '0x01', hash: '0xbad', - }) + }); - assert.ok(listeners.failed.notCalled, "should not emit 'tx:failed'") - assert.ok(listeners.confirmed.notCalled, "should not emit 'tx:confirmed'") - assert.ok(listeners.dropped.notCalled, "should not emit 'tx:dropped'") - assert.ok(listeners.warning.notCalled, "should not emit 'tx:warning'") - }) + assert.ok(listeners.failed.notCalled, "should not emit 'tx:failed'"); + assert.ok( + listeners.confirmed.notCalled, + "should not emit 'tx:confirmed'", + ); + assert.ok(listeners.dropped.notCalled, "should not emit 'tx:dropped'"); + assert.ok(listeners.warning.notCalled, "should not emit 'tx:warning'"); + }); it("should emit 'tx:failed' if the txMeta does NOT have a hash", async function () { const pendingTxTracker = new PendingTransactionTracker({ @@ -674,24 +680,24 @@ describe('PendingTransactionTracker', function () { getCompletedTransactions: sinon.stub().returns([]), publishTransaction: sinon.spy(), confirmTransaction: sinon.spy(), - }) + }); const listeners = { confirmed: sinon.spy(), dropped: sinon.spy(), failed: sinon.spy(), warning: sinon.spy(), - } + }; - pendingTxTracker.once('tx:confirmed', listeners.confirmed) - pendingTxTracker.once('tx:dropped', listeners.dropped) - pendingTxTracker.once('tx:failed', listeners.failed) - pendingTxTracker.once('tx:warning', listeners.warning) + pendingTxTracker.once('tx:confirmed', listeners.confirmed); + pendingTxTracker.once('tx:dropped', listeners.dropped); + pendingTxTracker.once('tx:failed', listeners.failed); + pendingTxTracker.once('tx:warning', listeners.warning); await pendingTxTracker._checkPendingTx({ id: '2', history: [{}], status: TRANSACTION_STATUSES.SUBMITTED, txParams: { from: '0x1678a085c290ebd122dc42cba69373b5953b831d' }, - }) + }); assert.ok( listeners.failed.calledOnceWithExactly( @@ -699,11 +705,14 @@ describe('PendingTransactionTracker', function () { sinon.match.instanceOf(Error), ), "should pass txId to 'tx:failed' listener", - ) - assert.ok(listeners.confirmed.notCalled, "should not emit 'tx:confirmed'") - assert.ok(listeners.dropped.notCalled, "should not emit 'tx:dropped'") - assert.ok(listeners.warning.notCalled, "should not emit 'tx:warning'") - }) + ); + assert.ok( + listeners.confirmed.notCalled, + "should not emit 'tx:confirmed'", + ); + assert.ok(listeners.dropped.notCalled, "should not emit 'tx:dropped'"); + assert.ok(listeners.warning.notCalled, "should not emit 'tx:warning'"); + }); it("should emit 'tx:dropped' if another tx with the same nonce succeeds", async function () { const txs = [ @@ -724,7 +733,7 @@ describe('PendingTransactionTracker', function () { hash: '0x2a919d2512ec963f524bfd9730fb66b6d5a2e399d1dd957abb5e2b544a12644b', }, - ] + ]; const pendingTxTracker = new PendingTransactionTracker({ query: { getTransactionReceipt: sinon.stub().resolves(null), @@ -738,28 +747,31 @@ describe('PendingTransactionTracker', function () { getCompletedTransactions: sinon.stub().returns(txs), publishTransaction: sinon.spy(), confirmTransaction: sinon.spy(), - }) + }); const listeners = { confirmed: sinon.spy(), dropped: sinon.spy(), failed: sinon.spy(), warning: sinon.spy(), - } + }; - pendingTxTracker.once('tx:confirmed', listeners.confirmed) - pendingTxTracker.once('tx:dropped', listeners.dropped) - pendingTxTracker.once('tx:failed', listeners.failed) - pendingTxTracker.once('tx:warning', listeners.warning) - await pendingTxTracker._checkPendingTx(txs[1]) + pendingTxTracker.once('tx:confirmed', listeners.confirmed); + pendingTxTracker.once('tx:dropped', listeners.dropped); + pendingTxTracker.once('tx:failed', listeners.failed); + pendingTxTracker.once('tx:warning', listeners.warning); + await pendingTxTracker._checkPendingTx(txs[1]); - assert.ok(listeners.dropped.calledOnceWithExactly('123')) - assert.ok(listeners.confirmed.notCalled, "should not emit 'tx:confirmed'") - assert.ok(listeners.failed.notCalled, "should not emit 'tx:failed'") - assert.ok(listeners.warning.notCalled, "should not emit 'tx:warning'") - }) + assert.ok(listeners.dropped.calledOnceWithExactly('123')); + assert.ok( + listeners.confirmed.notCalled, + "should not emit 'tx:confirmed'", + ); + assert.ok(listeners.failed.notCalled, "should not emit 'tx:failed'"); + assert.ok(listeners.warning.notCalled, "should not emit 'tx:warning'"); + }); it("should emit 'tx:dropped' with the txMetas id only after the fourth call", async function () { - const nonceBN = new BN(2) + const nonceBN = new BN(2); const txMeta = { id: 1, hash: @@ -772,7 +784,7 @@ describe('PendingTransactionTracker', function () { }, history: [{}], rawTx: '0xf86c808504a817c80082471d', - } + }; const pendingTxTracker = new PendingTransactionTracker({ query: { getTransactionReceipt: sinon.stub().resolves(null), @@ -787,27 +799,30 @@ describe('PendingTransactionTracker', function () { getCompletedTransactions: sinon.stub().returns([]), publishTransaction: sinon.spy(), confirmTransaction: sinon.spy(), - }) + }); const listeners = { confirmed: sinon.spy(), dropped: sinon.spy(), failed: sinon.spy(), warning: sinon.spy(), - } + }; - pendingTxTracker.once('tx:confirmed', listeners.confirmed) - pendingTxTracker.once('tx:dropped', listeners.dropped) - pendingTxTracker.once('tx:failed', listeners.failed) - pendingTxTracker.once('tx:warning', listeners.warning) - await pendingTxTracker._checkPendingTx(txMeta) - await pendingTxTracker._checkPendingTx(txMeta) - await pendingTxTracker._checkPendingTx(txMeta) - await pendingTxTracker._checkPendingTx(txMeta) + pendingTxTracker.once('tx:confirmed', listeners.confirmed); + pendingTxTracker.once('tx:dropped', listeners.dropped); + pendingTxTracker.once('tx:failed', listeners.failed); + pendingTxTracker.once('tx:warning', listeners.warning); + await pendingTxTracker._checkPendingTx(txMeta); + await pendingTxTracker._checkPendingTx(txMeta); + await pendingTxTracker._checkPendingTx(txMeta); + await pendingTxTracker._checkPendingTx(txMeta); - assert.ok(listeners.dropped.calledOnceWithExactly(1)) - assert.ok(listeners.confirmed.notCalled, "should not emit 'tx:confirmed'") - assert.ok(listeners.failed.notCalled, "should not emit 'tx:failed'") - assert.ok(listeners.warning.notCalled, "should not emit 'tx:warning'") - }) - }) -}) + assert.ok(listeners.dropped.calledOnceWithExactly(1)); + assert.ok( + listeners.confirmed.notCalled, + "should not emit 'tx:confirmed'", + ); + assert.ok(listeners.failed.notCalled, "should not emit 'tx:failed'"); + assert.ok(listeners.warning.notCalled, "should not emit 'tx:warning'"); + }); + }); +}); diff --git a/test/unit/app/controllers/transactions/tx-controller-test.js b/test/unit/app/controllers/transactions/tx-controller-test.js index e37c44a47..ca7bfede6 100644 --- a/test/unit/app/controllers/transactions/tx-controller-test.js +++ b/test/unit/app/controllers/transactions/tx-controller-test.js @@ -1,27 +1,27 @@ -import { strict as assert } from 'assert' -import EventEmitter from 'events' -import ethUtil from 'ethereumjs-util' -import EthTx from 'ethereumjs-tx' -import { ObservableStore } from '@metamask/obs-store' -import sinon from 'sinon' -import TransactionController from '../../../../../app/scripts/controllers/transactions' +import { strict as assert } from 'assert'; +import EventEmitter from 'events'; +import ethUtil from 'ethereumjs-util'; +import EthTx from 'ethereumjs-tx'; +import { ObservableStore } from '@metamask/obs-store'; +import sinon from 'sinon'; +import TransactionController from '../../../../../app/scripts/controllers/transactions'; import { createTestProviderTools, getTestAccounts, -} from '../../../../stub/provider' +} from '../../../../stub/provider'; import { TRANSACTION_CATEGORIES, TRANSACTION_STATUSES, TRANSACTION_TYPES, -} from '../../../../../shared/constants/transaction' +} from '../../../../../shared/constants/transaction'; -const noop = () => true -const currentNetworkId = '42' -const currentChainId = '0x2a' +const noop = () => true; +const currentNetworkId = '42'; +const currentChainId = '0x2a'; describe('Transaction Controller', function () { - let txController, provider, providerResultStub, fromAccount + let txController, provider, providerResultStub, fromAccount; beforeEach(function () { providerResultStub = { @@ -29,55 +29,55 @@ describe('Transaction Controller', function () { eth_gasPrice: '0x0de0b6b3a7640000', // by default, all accounts are external accounts (not contracts) eth_getCode: '0x', - } + }; provider = createTestProviderTools({ scaffold: providerResultStub }) - .provider - fromAccount = getTestAccounts()[0] - const blockTrackerStub = new EventEmitter() - blockTrackerStub.getCurrentBlock = noop - blockTrackerStub.getLatestBlock = noop + .provider; + fromAccount = getTestAccounts()[0]; + const blockTrackerStub = new EventEmitter(); + blockTrackerStub.getCurrentBlock = noop; + blockTrackerStub.getLatestBlock = noop; txController = new TransactionController({ provider, getGasPrice() { - return '0xee6b2800' + return '0xee6b2800'; }, networkStore: new ObservableStore(currentNetworkId), txHistoryLimit: 10, blockTracker: blockTrackerStub, signTransaction: (ethTx) => new Promise((resolve) => { - ethTx.sign(fromAccount.key) - resolve() + ethTx.sign(fromAccount.key); + resolve(); }), getPermittedAccounts: () => undefined, getCurrentChainId: () => currentChainId, getParticipateInMetrics: () => false, - }) + }); txController.nonceTracker.getNonceLock = () => - Promise.resolve({ nextNonce: 0, releaseLock: noop }) - }) + Promise.resolve({ nextNonce: 0, releaseLock: noop }); + }); describe('#getState', function () { it('should return a state object with the right keys and data types', function () { - const exposedState = txController.getState() + const exposedState = txController.getState(); assert.ok( 'unapprovedTxs' in exposedState, 'state should have the key unapprovedTxs', - ) + ); assert.ok( 'currentNetworkTxList' in exposedState, 'state should have the key currentNetworkTxList', - ) + ); assert.ok( typeof exposedState?.unapprovedTxs === 'object', 'should be an object', - ) + ); assert.ok( Array.isArray(exposedState.currentNetworkTxList), 'should be an array', - ) - }) - }) + ); + }); + }); describe('#getUnapprovedTxCount', function () { it('should return the number of unapproved txs', function () { @@ -103,11 +103,11 @@ describe('Transaction Controller', function () { txParams: {}, history: [{}], }, - ]) - const unapprovedTxCount = txController.getUnapprovedTxCount() - assert.equal(unapprovedTxCount, 3, 'should be 3') - }) - }) + ]); + const unapprovedTxCount = txController.getUnapprovedTxCount(); + assert.equal(unapprovedTxCount, 3, 'should be 3'); + }); + }); describe('#getPendingTxCount', function () { it('should return the number of pending txs', function () { @@ -133,19 +133,19 @@ describe('Transaction Controller', function () { txParams: {}, history: [{}], }, - ]) - const pendingTxCount = txController.getPendingTxCount() - assert.equal(pendingTxCount, 3, 'should be 3') - }) - }) + ]); + const pendingTxCount = txController.getPendingTxCount(); + assert.equal(pendingTxCount, 3, 'should be 3'); + }); + }); describe('#getConfirmedTransactions', function () { it('should return the number of confirmed txs', function () { - const address = '0xc684832530fcbddae4b4230a47e991ddcec2831d' + const address = '0xc684832530fcbddae4b4230a47e991ddcec2831d'; const txParams = { from: address, to: '0xc684832530fcbddae4b4230a47e991ddcec2831d', - } + }; txController.txStateManager._saveTxList([ { id: 0, @@ -210,136 +210,136 @@ describe('Transaction Controller', function () { txParams, history: [{}], }, - ]) + ]); assert.equal( txController.nonceTracker.getConfirmedTransactions(address).length, 3, - ) - }) - }) + ); + }); + }); describe('#newUnapprovedTransaction', function () { - let stub, txMeta, txParams + let stub, txMeta, txParams; beforeEach(function () { txParams = { from: '0xc684832530fcbddae4b4230a47e991ddcec2831d', to: '0xc684832530fcbddae4b4230a47e991ddcec2831d', - } + }; txMeta = { status: TRANSACTION_STATUSES.UNAPPROVED, id: 1, metamaskNetworkId: currentNetworkId, txParams, history: [{}], - } - txController.txStateManager._saveTxList([txMeta]) + }; + txController.txStateManager._saveTxList([txMeta]); stub = sinon .stub(txController, 'addUnapprovedTransaction') .callsFake(() => { - txController.emit('newUnapprovedTx', txMeta) - return Promise.resolve(txController.txStateManager.addTx(txMeta)) - }) - }) + txController.emit('newUnapprovedTx', txMeta); + return Promise.resolve(txController.txStateManager.addTx(txMeta)); + }); + }); afterEach(function () { - txController.txStateManager._saveTxList([]) - stub.restore() - }) + txController.txStateManager._saveTxList([]); + stub.restore(); + }); it('should resolve when finished and status is submitted and resolve with the hash', async function () { txController.once('newUnapprovedTx', (txMetaFromEmit) => { setTimeout(() => { - txController.setTxHash(txMetaFromEmit.id, '0x0') - txController.txStateManager.setTxStatusSubmitted(txMetaFromEmit.id) - }) - }) + txController.setTxHash(txMetaFromEmit.id, '0x0'); + txController.txStateManager.setTxStatusSubmitted(txMetaFromEmit.id); + }); + }); - const hash = await txController.newUnapprovedTransaction(txParams) - assert.ok(hash, 'newUnapprovedTransaction needs to return the hash') - }) + const hash = await txController.newUnapprovedTransaction(txParams); + assert.ok(hash, 'newUnapprovedTransaction needs to return the hash'); + }); it('should reject when finished and status is rejected', async function () { txController.once('newUnapprovedTx', (txMetaFromEmit) => { setTimeout(() => { - txController.txStateManager.setTxStatusRejected(txMetaFromEmit.id) - }) - }) + txController.txStateManager.setTxStatusRejected(txMetaFromEmit.id); + }); + }); await assert.rejects( () => txController.newUnapprovedTransaction(txParams), { message: 'MetaMask Tx Signature: User denied transaction signature.', }, - ) - }) - }) + ); + }); + }); describe('#addUnapprovedTransaction', function () { - const selectedAddress = '0x1678a085c290ebd122dc42cba69373b5953b831d' - const recipientAddress = '0xc42edfcc21ed14dda456aa0756c153f7985d8813' + const selectedAddress = '0x1678a085c290ebd122dc42cba69373b5953b831d'; + const recipientAddress = '0xc42edfcc21ed14dda456aa0756c153f7985d8813'; - let getSelectedAddress, getPermittedAccounts + let getSelectedAddress, getPermittedAccounts; beforeEach(function () { getSelectedAddress = sinon .stub(txController, 'getSelectedAddress') - .returns(selectedAddress) + .returns(selectedAddress); getPermittedAccounts = sinon .stub(txController, 'getPermittedAccounts') - .returns([selectedAddress]) - }) + .returns([selectedAddress]); + }); afterEach(function () { - getSelectedAddress.restore() - getPermittedAccounts.restore() - }) + getSelectedAddress.restore(); + getPermittedAccounts.restore(); + }); it('should add an unapproved transaction and return a valid txMeta', async function () { const txMeta = await txController.addUnapprovedTransaction({ from: selectedAddress, to: recipientAddress, - }) - assert.ok('id' in txMeta, 'should have a id') - assert.ok('time' in txMeta, 'should have a time stamp') + }); + assert.ok('id' in txMeta, 'should have a id'); + assert.ok('time' in txMeta, 'should have a time stamp'); assert.ok( 'metamaskNetworkId' in txMeta, 'should have a metamaskNetworkId', - ) - assert.ok('txParams' in txMeta, 'should have a txParams') - assert.ok('history' in txMeta, 'should have a history') + ); + assert.ok('txParams' in txMeta, 'should have a txParams'); + assert.ok('history' in txMeta, 'should have a history'); assert.equal( txMeta.txParams.value, '0x0', 'should have added 0x0 as the value', - ) + ); - const memTxMeta = txController.txStateManager.getTx(txMeta.id) - assert.deepEqual(txMeta, memTxMeta) - }) + const memTxMeta = txController.txStateManager.getTx(txMeta.id); + assert.deepEqual(txMeta, memTxMeta); + }); it('should emit newUnapprovedTx event and pass txMeta as the first argument', function (done) { - providerResultStub.eth_gasPrice = '4a817c800' + providerResultStub.eth_gasPrice = '4a817c800'; txController.once('newUnapprovedTx', (txMetaFromEmit) => { - assert.ok(txMetaFromEmit, 'txMeta is falsy') - done() - }) + assert.ok(txMetaFromEmit, 'txMeta is falsy'); + done(); + }); txController .addUnapprovedTransaction({ from: selectedAddress, to: recipientAddress, }) - .catch(done) - }) + .catch(done); + }); it("should fail if the from address isn't the selected address", async function () { await assert.rejects(() => txController.addUnapprovedTransaction({ from: '0x0d1d4e623D10F9FBA5Db95830F7d3839406C6AF2', }), - ) - }) + ); + }); it('should fail if netId is loading', async function () { - txController.networkStore = new ObservableStore('loading') + txController.networkStore = new ObservableStore('loading'); await assert.rejects( () => txController.addUnapprovedTransaction({ @@ -347,9 +347,9 @@ describe('Transaction Controller', function () { to: '0x0d1d4e623D10F9FBA5Db95830F7d3839406C6AF2', }), { message: 'MetaMask is having trouble connecting to the network' }, - ) - }) - }) + ); + }); + }); describe('#addTxGasDefaults', function () { it('should add the tx defaults if their are none', async function () { @@ -361,7 +361,7 @@ describe('Transaction Controller', function () { txParams: {}, history: [{}], }, - ]) + ]); const txMeta = { id: 1, txParams: { @@ -369,22 +369,22 @@ describe('Transaction Controller', function () { to: '0xc684832530fcbddae4b4230a47e991ddcec2831d', }, history: [{}], - } - providerResultStub.eth_gasPrice = '4a817c800' - providerResultStub.eth_getBlockByNumber = { gasLimit: '47b784' } - providerResultStub.eth_estimateGas = '5209' + }; + providerResultStub.eth_gasPrice = '4a817c800'; + providerResultStub.eth_getBlockByNumber = { gasLimit: '47b784' }; + providerResultStub.eth_estimateGas = '5209'; - const txMetaWithDefaults = await txController.addTxGasDefaults(txMeta) + const txMetaWithDefaults = await txController.addTxGasDefaults(txMeta); assert.ok( txMetaWithDefaults.txParams.gasPrice, 'should have added the gas price', - ) + ); assert.ok( txMetaWithDefaults.txParams.gas, 'should have added the gas field', - ) - }) - }) + ); + }); + }); describe('#addTx', function () { it('should emit updates', function (done) { @@ -393,36 +393,36 @@ describe('Transaction Controller', function () { status: TRANSACTION_STATUSES.UNAPPROVED, metamaskNetworkId: currentNetworkId, txParams: {}, - } + }; - const eventNames = ['update:badge', '1:unapproved'] - const listeners = [] + const eventNames = ['update:badge', '1:unapproved']; + const listeners = []; eventNames.forEach((eventName) => { listeners.push( new Promise((resolve) => { txController.once(eventName, (arg) => { - resolve(arg) - }) + resolve(arg); + }); }), - ) - }) + ); + }); Promise.all(listeners) .then((returnValues) => { assert.deepEqual( returnValues.pop(), txMeta, 'last event 1:unapproved should return txMeta', - ) - done() + ); + done(); }) - .catch(done) - txController.addTx(txMeta) - }) - }) + .catch(done); + txController.addTx(txMeta); + }); + }); describe('#approveTransaction', function () { it('does not overwrite set values', async function () { - const originalValue = '0x01' + const originalValue = '0x01'; const txMeta = { id: '1', status: TRANSACTION_STATUSES.UNAPPROVED, @@ -432,41 +432,41 @@ describe('Transaction Controller', function () { gas: originalValue, gasPrice: originalValue, }, - } - this.timeout(15000) - const wrongValue = '0x05' + }; + this.timeout(15000); + const wrongValue = '0x05'; - txController.addTx(txMeta) - providerResultStub.eth_gasPrice = wrongValue - providerResultStub.eth_estimateGas = '0x5209' + txController.addTx(txMeta); + providerResultStub.eth_gasPrice = wrongValue; + providerResultStub.eth_estimateGas = '0x5209'; const signStub = sinon .stub(txController, 'signTransaction') - .callsFake(() => Promise.resolve()) + .callsFake(() => Promise.resolve()); const pubStub = sinon .stub(txController, 'publishTransaction') .callsFake(() => { - txController.setTxHash('1', originalValue) - txController.txStateManager.setTxStatusSubmitted('1') - }) + txController.setTxHash('1', originalValue); + txController.txStateManager.setTxStatusSubmitted('1'); + }); - await txController.approveTransaction(txMeta.id) - const result = txController.txStateManager.getTx(txMeta.id) - const params = result.txParams + await txController.approveTransaction(txMeta.id); + const result = txController.txStateManager.getTx(txMeta.id); + const params = result.txParams; - assert.equal(params.gas, originalValue, 'gas unmodified') - assert.equal(params.gasPrice, originalValue, 'gas price unmodified') - assert.equal(result.hash, originalValue) + assert.equal(params.gas, originalValue, 'gas unmodified'); + assert.equal(params.gasPrice, originalValue, 'gas price unmodified'); + assert.equal(result.hash, originalValue); assert.equal( result.status, TRANSACTION_STATUSES.SUBMITTED, 'should have reached the submitted status.', - ) - signStub.restore() - pubStub.restore() - }) - }) + ); + signStub.restore(); + pubStub.restore(); + }); + }); describe('#sign replay-protected tx', function () { it('prepares a tx with the chainId set', async function () { @@ -478,12 +478,12 @@ describe('Transaction Controller', function () { txParams: {}, }, noop, - ) - const rawTx = await txController.signTransaction('1') - const ethTx = new EthTx(ethUtil.toBuffer(rawTx)) - assert.equal(ethTx.getChainId(), 42) - }) - }) + ); + const rawTx = await txController.signTransaction('1'); + const ethTx = new EthTx(ethUtil.toBuffer(rawTx)); + assert.equal(ethTx.getChainId(), 42); + }); + }); describe('#updateAndApproveTransaction', function () { it('should update and approve transactions', async function () { @@ -498,21 +498,21 @@ describe('Transaction Controller', function () { nonce: '0x4b', }, metamaskNetworkId: currentNetworkId, - } - txController.txStateManager.addTx(txMeta) - const approvalPromise = txController.updateAndApproveTransaction(txMeta) - const tx = txController.txStateManager.getTx(1) - assert.equal(tx.status, TRANSACTION_STATUSES.APPROVED) - await approvalPromise - }) - }) + }; + txController.txStateManager.addTx(txMeta); + const approvalPromise = txController.updateAndApproveTransaction(txMeta); + const tx = txController.txStateManager.getTx(1); + assert.equal(tx.status, TRANSACTION_STATUSES.APPROVED); + await approvalPromise; + }); + }); describe('#getChainId', function () { it('returns 0 when the chainId is NaN', function () { - txController.networkStore = new ObservableStore('loading') - assert.equal(txController.getChainId(), 0) - }) - }) + txController.networkStore = new ObservableStore('loading'); + assert.equal(txController.getChainId(), 0); + }); + }); describe('#cancelTransaction', function () { it('should emit a status change to rejected', function (done) { @@ -566,7 +566,7 @@ describe('Transaction Controller', function () { metamaskNetworkId: currentNetworkId, history: [{}], }, - ]) + ]); txController.once('tx:status-update', (txId, status) => { try { @@ -574,27 +574,27 @@ describe('Transaction Controller', function () { status, TRANSACTION_STATUSES.REJECTED, 'status should be rejected', - ) - assert.equal(txId, 0, 'id should e 0') - done() + ); + assert.equal(txId, 0, 'id should e 0'); + done(); } catch (e) { - done(e) + done(e); } - }) + }); - txController.cancelTransaction(0) - }) - }) + txController.cancelTransaction(0); + }); + }); describe('#createSpeedUpTransaction', function () { - let addTxSpy - let approveTransactionSpy - let txParams - let expectedTxParams + let addTxSpy; + let approveTransactionSpy; + let txParams; + let expectedTxParams; beforeEach(function () { - addTxSpy = sinon.spy(txController, 'addTx') - approveTransactionSpy = sinon.spy(txController, 'approveTransaction') + addTxSpy = sinon.spy(txController, 'addTx'); + approveTransactionSpy = sinon.spy(txController, 'approveTransaction'); txParams = { nonce: '0x00', @@ -602,7 +602,7 @@ describe('Transaction Controller', function () { to: '0xB09d8505E1F4EF1CeA089D47094f5DD3464083d4', gas: '0x5209', gasPrice: '0xa', - } + }; txController.txStateManager._saveTxList([ { id: 1, @@ -611,97 +611,97 @@ describe('Transaction Controller', function () { txParams, history: [{}], }, - ]) + ]); - expectedTxParams = { ...txParams, gasPrice: '0xb' } - }) + expectedTxParams = { ...txParams, gasPrice: '0xb' }; + }); afterEach(function () { - addTxSpy.restore() - approveTransactionSpy.restore() - }) + addTxSpy.restore(); + approveTransactionSpy.restore(); + }); it('should call this.addTx and this.approveTransaction with the expected args', async function () { - await txController.createSpeedUpTransaction(1) - assert.equal(addTxSpy.callCount, 1) + await txController.createSpeedUpTransaction(1); + assert.equal(addTxSpy.callCount, 1); - const addTxArgs = addTxSpy.getCall(0).args[0] - assert.deepEqual(addTxArgs.txParams, expectedTxParams) + const addTxArgs = addTxSpy.getCall(0).args[0]; + assert.deepEqual(addTxArgs.txParams, expectedTxParams); - const { lastGasPrice, type } = addTxArgs + const { lastGasPrice, type } = addTxArgs; assert.deepEqual( { lastGasPrice, type }, { lastGasPrice: '0xa', type: TRANSACTION_TYPES.RETRY, }, - ) - }) + ); + }); it('should call this.approveTransaction with the id of the returned tx', async function () { - const result = await txController.createSpeedUpTransaction(1) - assert.equal(approveTransactionSpy.callCount, 1) + const result = await txController.createSpeedUpTransaction(1); + assert.equal(approveTransactionSpy.callCount, 1); - const approveTransactionArg = approveTransactionSpy.getCall(0).args[0] - assert.equal(result.id, approveTransactionArg) - }) + const approveTransactionArg = approveTransactionSpy.getCall(0).args[0]; + assert.equal(result.id, approveTransactionArg); + }); it('should return the expected txMeta', async function () { - const result = await txController.createSpeedUpTransaction(1) + const result = await txController.createSpeedUpTransaction(1); - assert.deepEqual(result.txParams, expectedTxParams) + assert.deepEqual(result.txParams, expectedTxParams); - const { lastGasPrice, type } = result + const { lastGasPrice, type } = result; assert.deepEqual( { lastGasPrice, type }, { lastGasPrice: '0xa', type: TRANSACTION_TYPES.RETRY, }, - ) - }) - }) + ); + }); + }); describe('#publishTransaction', function () { - let hash, txMeta + let hash, txMeta; beforeEach(function () { hash = - '0x2a5523c6fa98b47b7d9b6c8320179785150b42a16bcff36b398c5062b65657e8' + '0x2a5523c6fa98b47b7d9b6c8320179785150b42a16bcff36b398c5062b65657e8'; txMeta = { id: 1, status: TRANSACTION_STATUSES.UNAPPROVED, txParams: {}, metamaskNetworkId: currentNetworkId, - } - providerResultStub.eth_sendRawTransaction = hash - }) + }; + providerResultStub.eth_sendRawTransaction = hash; + }); it('should publish a tx, updates the rawTx when provided a one', async function () { const rawTx = - '0x477b2e6553c917af0db0388ae3da62965ff1a184558f61b749d1266b2e6d024c' - txController.txStateManager.addTx(txMeta) - await txController.publishTransaction(txMeta.id, rawTx) - const publishedTx = txController.txStateManager.getTx(1) - assert.equal(publishedTx.hash, hash) - assert.equal(publishedTx.status, TRANSACTION_STATUSES.SUBMITTED) - }) + '0x477b2e6553c917af0db0388ae3da62965ff1a184558f61b749d1266b2e6d024c'; + txController.txStateManager.addTx(txMeta); + await txController.publishTransaction(txMeta.id, rawTx); + const publishedTx = txController.txStateManager.getTx(1); + assert.equal(publishedTx.hash, hash); + assert.equal(publishedTx.status, TRANSACTION_STATUSES.SUBMITTED); + }); it('should ignore the error "Transaction Failed: known transaction" and be as usual', async function () { providerResultStub.eth_sendRawTransaction = async (_, __, ___, end) => { - end('Transaction Failed: known transaction') - } + end('Transaction Failed: known transaction'); + }; const rawTx = - '0xf86204831e848082520894f231d46dd78806e1dd93442cf33c7671f853874880802ca05f973e540f2d3c2f06d3725a626b75247593cb36477187ae07ecfe0a4db3cf57a00259b52ee8c58baaa385fb05c3f96116e58de89bcc165cb3bfdfc708672fed8a' - txController.txStateManager.addTx(txMeta) - await txController.publishTransaction(txMeta.id, rawTx) - const publishedTx = txController.txStateManager.getTx(1) + '0xf86204831e848082520894f231d46dd78806e1dd93442cf33c7671f853874880802ca05f973e540f2d3c2f06d3725a626b75247593cb36477187ae07ecfe0a4db3cf57a00259b52ee8c58baaa385fb05c3f96116e58de89bcc165cb3bfdfc708672fed8a'; + txController.txStateManager.addTx(txMeta); + await txController.publishTransaction(txMeta.id, rawTx); + const publishedTx = txController.txStateManager.getTx(1); assert.equal( publishedTx.hash, '0x2cc5a25744486f7383edebbf32003e5a66e18135799593d6b5cdd2bb43674f09', - ) - assert.equal(publishedTx.status, TRANSACTION_STATUSES.SUBMITTED) - }) - }) + ); + assert.equal(publishedTx.status, TRANSACTION_STATUSES.SUBMITTED); + }); + }); describe('#_markNonceDuplicatesDropped', function () { it('should mark all nonce duplicates as dropped without marking the confirmed transaction as dropped', function () { @@ -755,90 +755,90 @@ describe('Transaction Controller', function () { history: [{}], txParams: { nonce: '0x01' }, }, - ]) - txController._markNonceDuplicatesDropped(1) - const confirmedTx = txController.txStateManager.getTx(1) + ]); + txController._markNonceDuplicatesDropped(1); + const confirmedTx = txController.txStateManager.getTx(1); const droppedTxs = txController.txStateManager.getFilteredTxList({ nonce: '0x01', status: TRANSACTION_STATUSES.DROPPED, - }) + }); assert.equal( confirmedTx.status, TRANSACTION_STATUSES.CONFIRMED, 'the confirmedTx should remain confirmed', - ) - assert.equal(droppedTxs.length, 6, 'their should be 6 dropped txs') - }) - }) + ); + assert.equal(droppedTxs.length, 6, 'their should be 6 dropped txs'); + }); + }); describe('#_determineTransactionCategory', function () { it('should return a simple send transactionCategory when to is truthy but data is falsy', async function () { const result = await txController._determineTransactionCategory({ to: '0xabc', data: '', - }) + }); assert.deepEqual(result, { transactionCategory: TRANSACTION_CATEGORIES.SENT_ETHER, getCodeResponse: null, - }) - }) + }); + }); it('should return a token transfer transactionCategory when data is for the respective method call', async function () { const result = await txController._determineTransactionCategory({ to: '0xabc', data: '0xa9059cbb0000000000000000000000002f318C334780961FB129D2a6c30D0763d9a5C970000000000000000000000000000000000000000000000000000000000000000a', - }) + }); assert.deepEqual(result, { transactionCategory: TRANSACTION_CATEGORIES.TOKEN_METHOD_TRANSFER, getCodeResponse: undefined, - }) - }) + }); + }); it('should return a token approve transactionCategory when data is for the respective method call', async function () { const result = await txController._determineTransactionCategory({ to: '0xabc', data: '0x095ea7b30000000000000000000000002f318C334780961FB129D2a6c30D0763d9a5C9700000000000000000000000000000000000000000000000000000000000000005', - }) + }); assert.deepEqual(result, { transactionCategory: TRANSACTION_CATEGORIES.TOKEN_METHOD_APPROVE, getCodeResponse: undefined, - }) - }) + }); + }); it('should return a contract deployment transactionCategory when to is falsy and there is data', async function () { const result = await txController._determineTransactionCategory({ to: '', data: '0xabd', - }) + }); assert.deepEqual(result, { transactionCategory: TRANSACTION_CATEGORIES.DEPLOY_CONTRACT, getCodeResponse: undefined, - }) - }) + }); + }); it('should return a simple send transactionCategory with a 0x getCodeResponse when there is data and but the to address is not a contract address', async function () { const result = await txController._determineTransactionCategory({ to: '0x9e673399f795D01116e9A8B2dD2F156705131ee9', data: '0xabd', - }) + }); assert.deepEqual(result, { transactionCategory: TRANSACTION_CATEGORIES.SENT_ETHER, getCodeResponse: '0x', - }) - }) + }); + }); it('should return a simple send transactionCategory with a null getCodeResponse when to is truthy and there is data and but getCode returns an error', async function () { const result = await txController._determineTransactionCategory({ to: '0xabc', data: '0xabd', - }) + }); assert.deepEqual(result, { transactionCategory: TRANSACTION_CATEGORIES.SENT_ETHER, getCodeResponse: null, - }) - }) + }); + }); it('should return a contract interaction transactionCategory with the correct getCodeResponse when to is truthy and there is data and it is not a token transaction', async function () { const _providerResultStub = { @@ -846,38 +846,38 @@ describe('Transaction Controller', function () { eth_gasPrice: '0x0de0b6b3a7640000', // by default, all accounts are external accounts (not contracts) eth_getCode: '0xa', - } + }; const _provider = createTestProviderTools({ scaffold: _providerResultStub, - }).provider - const _fromAccount = getTestAccounts()[0] - const _blockTrackerStub = new EventEmitter() - _blockTrackerStub.getCurrentBlock = noop - _blockTrackerStub.getLatestBlock = noop + }).provider; + const _fromAccount = getTestAccounts()[0]; + const _blockTrackerStub = new EventEmitter(); + _blockTrackerStub.getCurrentBlock = noop; + _blockTrackerStub.getLatestBlock = noop; const _txController = new TransactionController({ provider: _provider, getGasPrice() { - return '0xee6b2800' + return '0xee6b2800'; }, networkStore: new ObservableStore(currentNetworkId), txHistoryLimit: 10, blockTracker: _blockTrackerStub, signTransaction: (ethTx) => new Promise((resolve) => { - ethTx.sign(_fromAccount.key) - resolve() + ethTx.sign(_fromAccount.key); + resolve(); }), getParticipateInMetrics: () => false, - }) + }); const result = await _txController._determineTransactionCategory({ to: '0x9e673399f795D01116e9A8B2dD2F156705131ee9', data: 'abd', - }) + }); assert.deepEqual(result, { transactionCategory: TRANSACTION_CATEGORIES.CONTRACT_INTERACTION, getCodeResponse: '0x0a', - }) - }) + }); + }); it('should return a contract interaction transactionCategory with the correct getCodeResponse when to is a contract address and data is falsy', async function () { const _providerResultStub = { @@ -885,39 +885,39 @@ describe('Transaction Controller', function () { eth_gasPrice: '0x0de0b6b3a7640000', // by default, all accounts are external accounts (not contracts) eth_getCode: '0xa', - } + }; const _provider = createTestProviderTools({ scaffold: _providerResultStub, - }).provider - const _fromAccount = getTestAccounts()[0] - const _blockTrackerStub = new EventEmitter() - _blockTrackerStub.getCurrentBlock = noop - _blockTrackerStub.getLatestBlock = noop + }).provider; + const _fromAccount = getTestAccounts()[0]; + const _blockTrackerStub = new EventEmitter(); + _blockTrackerStub.getCurrentBlock = noop; + _blockTrackerStub.getLatestBlock = noop; const _txController = new TransactionController({ provider: _provider, getGasPrice() { - return '0xee6b2800' + return '0xee6b2800'; }, networkStore: new ObservableStore(currentNetworkId), txHistoryLimit: 10, blockTracker: _blockTrackerStub, signTransaction: (ethTx) => new Promise((resolve) => { - ethTx.sign(_fromAccount.key) - resolve() + ethTx.sign(_fromAccount.key); + resolve(); }), getParticipateInMetrics: () => false, - }) + }); const result = await _txController._determineTransactionCategory({ to: '0x9e673399f795D01116e9A8B2dD2F156705131ee9', data: '', - }) + }); assert.deepEqual(result, { transactionCategory: TRANSACTION_CATEGORIES.CONTRACT_INTERACTION, getCodeResponse: '0x0a', - }) - }) - }) + }); + }); + }); describe('#getPendingTransactions', function () { it('should show only submitted and approved transactions as pending transaction', function () { @@ -970,23 +970,23 @@ describe('Transaction Controller', function () { txParams: {}, history: [{}], }, - ]) + ]); assert.equal( txController.pendingTxTracker.getPendingTransactions().length, 2, - ) + ); const states = txController.pendingTxTracker .getPendingTransactions() - .map((tx) => tx.status) + .map((tx) => tx.status); assert.ok( states.includes(TRANSACTION_STATUSES.APPROVED), 'includes approved', - ) + ); assert.ok( states.includes(TRANSACTION_STATUSES.SUBMITTED), 'includes submitted', - ) - }) - }) -}) + ); + }); + }); +}); diff --git a/test/unit/app/controllers/transactions/tx-gas-util-test.js b/test/unit/app/controllers/transactions/tx-gas-util-test.js index c08b70520..d3e9cfddf 100644 --- a/test/unit/app/controllers/transactions/tx-gas-util-test.js +++ b/test/unit/app/controllers/transactions/tx-gas-util-test.js @@ -1,10 +1,10 @@ -import { strict as assert } from 'assert' -import Transaction from 'ethereumjs-tx' -import { hexToBn, bnToHex } from '../../../../../app/scripts/lib/util' -import TxUtils from '../../../../../app/scripts/controllers/transactions/tx-gas-utils' +import { strict as assert } from 'assert'; +import Transaction from 'ethereumjs-tx'; +import { hexToBn, bnToHex } from '../../../../../app/scripts/lib/util'; +import TxUtils from '../../../../../app/scripts/controllers/transactions/tx-gas-utils'; describe('txUtils', function () { - let txUtils + let txUtils; before(function () { txUtils = new TxUtils( @@ -12,12 +12,12 @@ describe('txUtils', function () { {}, { get: () => { - return () => undefined + return () => undefined; }, }, ), - ) - }) + ); + }); describe('chain Id', function () { it('prepares a transaction with the provided chainId', function () { @@ -30,56 +30,56 @@ describe('txUtils', function () { data: '0x', nonce: '0x3', chainId: 42, - } - const ethTx = new Transaction(txParams) - assert.equal(ethTx.getChainId(), 42, 'chainId is set from tx params') - }) - }) + }; + const ethTx = new Transaction(txParams); + assert.equal(ethTx.getChainId(), 42, 'chainId is set from tx params'); + }); + }); describe('addGasBuffer', function () { it('multiplies by 1.5, when within block gas limit', function () { // naive estimatedGas: 0x16e360 (1.5 mil) - const inputHex = '0x16e360' + const inputHex = '0x16e360'; // dummy gas limit: 0x3d4c52 (4 mil) - const blockGasLimitHex = '0x3d4c52' - const output = txUtils.addGasBuffer(inputHex, blockGasLimitHex) - const inputBn = hexToBn(inputHex) - const outputBn = hexToBn(output) - const expectedBn = inputBn.muln(1.5) - assert.ok(outputBn.eq(expectedBn), 'returns 1.5 the input value') - }) + const blockGasLimitHex = '0x3d4c52'; + const output = txUtils.addGasBuffer(inputHex, blockGasLimitHex); + const inputBn = hexToBn(inputHex); + const outputBn = hexToBn(output); + const expectedBn = inputBn.muln(1.5); + assert.ok(outputBn.eq(expectedBn), 'returns 1.5 the input value'); + }); it('uses original estimatedGas, when above block gas limit', function () { // naive estimatedGas: 0x16e360 (1.5 mil) - const inputHex = '0x16e360' + const inputHex = '0x16e360'; // dummy gas limit: 0x0f4240 (1 mil) - const blockGasLimitHex = '0x0f4240' - const output = txUtils.addGasBuffer(inputHex, blockGasLimitHex) + const blockGasLimitHex = '0x0f4240'; + const output = txUtils.addGasBuffer(inputHex, blockGasLimitHex); // const inputBn = hexToBn(inputHex) - const outputBn = hexToBn(output) - const expectedBn = hexToBn(inputHex) + const outputBn = hexToBn(output); + const expectedBn = hexToBn(inputHex); assert.ok( outputBn.eq(expectedBn), 'returns the original estimatedGas value', - ) - }) + ); + }); it('buffers up to recommend gas limit recommended ceiling', function () { // naive estimatedGas: 0x16e360 (1.5 mil) - const inputHex = '0x16e360' + const inputHex = '0x16e360'; // dummy gas limit: 0x1e8480 (2 mil) - const blockGasLimitHex = '0x1e8480' - const blockGasLimitBn = hexToBn(blockGasLimitHex) - const ceilGasLimitBn = blockGasLimitBn.muln(0.9) - const output = txUtils.addGasBuffer(inputHex, blockGasLimitHex) + const blockGasLimitHex = '0x1e8480'; + const blockGasLimitBn = hexToBn(blockGasLimitHex); + const ceilGasLimitBn = blockGasLimitBn.muln(0.9); + const output = txUtils.addGasBuffer(inputHex, blockGasLimitHex); // const inputBn = hexToBn(inputHex) // const outputBn = hexToBn(output) - const expectedHex = bnToHex(ceilGasLimitBn) + const expectedHex = bnToHex(ceilGasLimitBn); assert.equal( output, expectedHex, 'returns the gas limit recommended ceiling value', - ) - }) - }) -}) + ); + }); + }); +}); diff --git a/test/unit/app/controllers/transactions/tx-helper-test.js b/test/unit/app/controllers/transactions/tx-helper-test.js index 0330e7724..c2b13af4c 100644 --- a/test/unit/app/controllers/transactions/tx-helper-test.js +++ b/test/unit/app/controllers/transactions/tx-helper-test.js @@ -1,17 +1,17 @@ -import { strict as assert } from 'assert' -import txHelper from '../../../../../ui/lib/tx-helper' +import { strict as assert } from 'assert'; +import txHelper from '../../../../../ui/lib/tx-helper'; describe('txHelper', function () { it('always shows the oldest tx first', function () { - const metamaskNetworkId = '1' + const metamaskNetworkId = '1'; const txs = { a: { metamaskNetworkId, time: 3 }, b: { metamaskNetworkId, time: 1 }, c: { metamaskNetworkId, time: 2 }, - } + }; - const sorted = txHelper(txs, null, null, metamaskNetworkId) - assert.equal(sorted[0].time, 1, 'oldest tx first') - assert.equal(sorted[2].time, 3, 'newest tx last') - }) -}) + const sorted = txHelper(txs, null, null, metamaskNetworkId); + assert.equal(sorted[0].time, 1, 'oldest tx first'); + assert.equal(sorted[2].time, 3, 'newest tx last'); + }); +}); diff --git a/test/unit/app/controllers/transactions/tx-state-history-helpers-test.js b/test/unit/app/controllers/transactions/tx-state-history-helpers-test.js index c11cb17e0..6ff852bae 100644 --- a/test/unit/app/controllers/transactions/tx-state-history-helpers-test.js +++ b/test/unit/app/controllers/transactions/tx-state-history-helpers-test.js @@ -1,11 +1,11 @@ -import { strict as assert } from 'assert' +import { strict as assert } from 'assert'; import { snapshotFromTxMeta, migrateFromSnapshotsToDiffs, replayHistory, generateHistoryEntry, -} from '../../../../../app/scripts/controllers/transactions/lib/tx-state-history-helpers' -import testData from '../../../../data/mock-tx-history.json' +} from '../../../../../app/scripts/controllers/transactions/lib/tx-state-history-helpers'; +import testData from '../../../../data/mock-tx-history.json'; describe('Transaction state history helper', function () { describe('#snapshotFromTxMeta', function () { @@ -16,86 +16,86 @@ describe('Transaction state history helper', function () { bam: 'baz', }, }, - } - const output = snapshotFromTxMeta(input) - assert.ok('foo' in output, 'has a foo key') - assert.ok('bar' in output.foo, 'has a bar key') - assert.ok('bam' in output.foo.bar, 'has a bar key') - assert.equal(output.foo.bar.bam, 'baz', 'has a baz value') - }) + }; + const output = snapshotFromTxMeta(input); + assert.ok('foo' in output, 'has a foo key'); + assert.ok('bar' in output.foo, 'has a bar key'); + assert.ok('bam' in output.foo.bar, 'has a bar key'); + assert.equal(output.foo.bar.bam, 'baz', 'has a baz value'); + }); it('should remove the history key', function () { - const input = { foo: 'bar', history: 'remembered' } - const output = snapshotFromTxMeta(input) - assert.equal(typeof output.history, 'undefined', 'should remove history') - }) - }) + const input = { foo: 'bar', history: 'remembered' }; + const output = snapshotFromTxMeta(input); + assert.equal(typeof output.history, 'undefined', 'should remove history'); + }); + }); describe('#migrateFromSnapshotsToDiffs', function () { it('migrates history to diffs and can recover original values', function () { testData.TransactionsController.transactions.forEach((tx) => { - const newHistory = migrateFromSnapshotsToDiffs(tx.history) + const newHistory = migrateFromSnapshotsToDiffs(tx.history); newHistory.forEach((newEntry, index) => { if (index === 0) { assert.equal( Array.isArray(newEntry), false, 'initial history item IS NOT a json patch obj', - ) + ); } else { assert.equal( Array.isArray(newEntry), true, 'non-initial history entry IS a json patch obj', - ) + ); } - const oldEntry = tx.history[index] - const historySubset = newHistory.slice(0, index + 1) - const reconstructedValue = replayHistory(historySubset) + const oldEntry = tx.history[index]; + const historySubset = newHistory.slice(0, index + 1); + const reconstructedValue = replayHistory(historySubset); assert.deepEqual( oldEntry, reconstructedValue, 'was able to reconstruct old entry from diffs', - ) - }) - }) - }) - }) + ); + }); + }); + }); + }); describe('#replayHistory', function () { it('replaying history does not mutate the original object', function () { - const initialState = { test: true, message: 'hello', value: 1 } + const initialState = { test: true, message: 'hello', value: 1 }; const diff1 = [ { op: 'replace', path: '/message', value: 'haay', }, - ] + ]; const diff2 = [ { op: 'replace', path: '/value', value: 2, }, - ] - const history = [initialState, diff1, diff2] + ]; + const history = [initialState, diff1, diff2]; - const beforeStateSnapshot = JSON.stringify(initialState) - const latestState = replayHistory(history) - const afterStateSnapshot = JSON.stringify(initialState) + const beforeStateSnapshot = JSON.stringify(initialState); + const latestState = replayHistory(history); + const afterStateSnapshot = JSON.stringify(initialState); assert.notEqual( initialState, latestState, 'initial state is not the same obj as the latest state', - ) + ); assert.equal( beforeStateSnapshot, afterStateSnapshot, 'initial state is not modified during run', - ) - }) - }) + ); + }); + }); describe('#generateHistoryEntry', function () { function generateHistoryEntryTest(note) { @@ -106,7 +106,7 @@ describe('Transaction state history helper', function () { bam: 'baz', }, }, - } + }; const nextState = { newPropRoot: 'new property - root', @@ -117,46 +117,46 @@ describe('Transaction state history helper', function () { bam: 'baz', }, }, - } + }; - const before = new Date().getTime() - const result = generateHistoryEntry(prevState, nextState, note) - const after = new Date().getTime() - assert.ok(Array.isArray(result)) - assert.equal(result.length, 3) + const before = new Date().getTime(); + const result = generateHistoryEntry(prevState, nextState, note); + const after = new Date().getTime(); + assert.ok(Array.isArray(result)); + assert.equal(result.length, 3); const expectedEntry1 = { op: 'add', path: '/foo/newPropFirstLevel', value: 'new property - first level', - } - assert.equal(result[0].op, expectedEntry1.op) - assert.equal(result[0].path, expectedEntry1.path) - assert.equal(result[0].value, expectedEntry1.value) - assert.equal(result[0].note, note) - assert.ok(result[0].timestamp >= before && result[0].timestamp <= after) + }; + assert.equal(result[0].op, expectedEntry1.op); + assert.equal(result[0].path, expectedEntry1.path); + assert.equal(result[0].value, expectedEntry1.value); + assert.equal(result[0].note, note); + assert.ok(result[0].timestamp >= before && result[0].timestamp <= after); const expectedEntry2 = { op: 'replace', path: '/someValue', value: 'value 2', - } - assert.deepEqual(result[1], expectedEntry2) + }; + assert.deepEqual(result[1], expectedEntry2); const expectedEntry3 = { op: 'add', path: '/newPropRoot', value: 'new property - root', - } - assert.deepEqual(result[2], expectedEntry3) + }; + assert.deepEqual(result[2], expectedEntry3); } it('should generate history entries', function () { - generateHistoryEntryTest() - }) + generateHistoryEntryTest(); + }); it('should add note to first entry', function () { - generateHistoryEntryTest('custom note') - }) - }) -}) + generateHistoryEntryTest('custom note'); + }); + }); +}); diff --git a/test/unit/app/controllers/transactions/tx-state-manager-test.js b/test/unit/app/controllers/transactions/tx-state-manager-test.js index 0b32e7e6f..6efafb693 100644 --- a/test/unit/app/controllers/transactions/tx-state-manager-test.js +++ b/test/unit/app/controllers/transactions/tx-state-manager-test.js @@ -1,15 +1,15 @@ -import { strict as assert } from 'assert' -import sinon from 'sinon' -import TxStateManager from '../../../../../app/scripts/controllers/transactions/tx-state-manager' -import { snapshotFromTxMeta } from '../../../../../app/scripts/controllers/transactions/lib/tx-state-history-helpers' -import { TRANSACTION_STATUSES } from '../../../../../shared/constants/transaction' +import { strict as assert } from 'assert'; +import sinon from 'sinon'; +import TxStateManager from '../../../../../app/scripts/controllers/transactions/tx-state-manager'; +import { snapshotFromTxMeta } from '../../../../../app/scripts/controllers/transactions/lib/tx-state-history-helpers'; +import { TRANSACTION_STATUSES } from '../../../../../shared/constants/transaction'; -const noop = () => true +const noop = () => true; describe('TransactionStateManager', function () { - let txStateManager - const currentNetworkId = '42' - const otherNetworkId = '2' + let txStateManager; + const currentNetworkId = '42'; + const otherNetworkId = '2'; beforeEach(function () { txStateManager = new TxStateManager({ @@ -18,8 +18,8 @@ describe('TransactionStateManager', function () { }, txHistoryLimit: 10, getNetwork: () => currentNetworkId, - }) - }) + }); + }); describe('#setTxStatusSigned', function () { it('sets the tx status to signed', function () { @@ -28,14 +28,14 @@ describe('TransactionStateManager', function () { status: TRANSACTION_STATUSES.UNAPPROVED, metamaskNetworkId: currentNetworkId, txParams: {}, - } - txStateManager.addTx(tx, noop) - txStateManager.setTxStatusSigned(1) - const result = txStateManager.getTxList() - assert.ok(Array.isArray(result)) - assert.equal(result.length, 1) - assert.equal(result[0].status, TRANSACTION_STATUSES.SIGNED) - }) + }; + txStateManager.addTx(tx, noop); + txStateManager.setTxStatusSigned(1); + const result = txStateManager.getTxList(); + assert.ok(Array.isArray(result)); + assert.equal(result.length, 1); + assert.equal(result[0].status, TRANSACTION_STATUSES.SIGNED); + }); it('should emit a signed event to signal the execution of callback', function () { const tx = { @@ -43,19 +43,19 @@ describe('TransactionStateManager', function () { status: TRANSACTION_STATUSES.UNAPPROVED, metamaskNetworkId: currentNetworkId, txParams: {}, - } - const clock = sinon.useFakeTimers() - const onSigned = sinon.spy() + }; + const clock = sinon.useFakeTimers(); + const onSigned = sinon.spy(); - txStateManager.addTx(tx) - txStateManager.on('1:signed', onSigned) - txStateManager.setTxStatusSigned(1) - clock.runAll() - clock.restore() + txStateManager.addTx(tx); + txStateManager.on('1:signed', onSigned); + txStateManager.setTxStatusSigned(1); + clock.runAll(); + clock.restore(); - assert.ok(onSigned.calledOnce) - }) - }) + assert.ok(onSigned.calledOnce); + }); + }); describe('#setTxStatusRejected', function () { it('sets the tx status to rejected and removes it from history', function () { @@ -64,13 +64,13 @@ describe('TransactionStateManager', function () { status: TRANSACTION_STATUSES.UNAPPROVED, metamaskNetworkId: currentNetworkId, txParams: {}, - } - txStateManager.addTx(tx) - txStateManager.setTxStatusRejected(1) - const result = txStateManager.getTxList() - assert.ok(Array.isArray(result)) - assert.equal(result.length, 0) - }) + }; + txStateManager.addTx(tx); + txStateManager.setTxStatusRejected(1); + const result = txStateManager.getTxList(); + assert.ok(Array.isArray(result)); + assert.equal(result.length, 0); + }); it('should emit a rejected event to signal the execution of callback', function () { const tx = { @@ -78,34 +78,34 @@ describe('TransactionStateManager', function () { status: TRANSACTION_STATUSES.UNAPPROVED, metamaskNetworkId: currentNetworkId, txParams: {}, - } - const clock = sinon.useFakeTimers() - const onSigned = sinon.spy() + }; + const clock = sinon.useFakeTimers(); + const onSigned = sinon.spy(); - txStateManager.addTx(tx) - txStateManager.on('1:rejected', onSigned) - txStateManager.setTxStatusRejected(1) - clock.runAll() - clock.restore() + txStateManager.addTx(tx); + txStateManager.on('1:rejected', onSigned); + txStateManager.setTxStatusRejected(1); + clock.runAll(); + clock.restore(); - assert.ok(onSigned.calledOnce) - }) - }) + assert.ok(onSigned.calledOnce); + }); + }); describe('#getFullTxList', function () { it('when new should return empty array', function () { - const result = txStateManager.getTxList() - assert.ok(Array.isArray(result)) - assert.equal(result.length, 0) - }) - }) + const result = txStateManager.getTxList(); + assert.ok(Array.isArray(result)); + assert.equal(result.length, 0); + }); + }); describe('#getTxList', function () { it('when new should return empty array', function () { - const result = txStateManager.getTxList() - assert.ok(Array.isArray(result)) - assert.equal(result.length, 0) - }) + const result = txStateManager.getTxList(); + assert.ok(Array.isArray(result)); + assert.equal(result.length, 0); + }); it('should return a full list of transactions', function () { const submittedTx = { @@ -118,7 +118,7 @@ describe('TransactionStateManager', function () { nonce: '0x0', }, status: TRANSACTION_STATUSES.SUBMITTED, - } + }; const confirmedTx = { id: 3, @@ -130,17 +130,17 @@ describe('TransactionStateManager', function () { nonce: '0x3', }, status: TRANSACTION_STATUSES.CONFIRMED, - } + }; const txm = new TxStateManager({ initState: { transactions: [submittedTx, confirmedTx], }, getNetwork: () => currentNetworkId, - }) + }); - assert.deepEqual(txm.getTxList(), [submittedTx, confirmedTx]) - }) + assert.deepEqual(txm.getTxList(), [submittedTx, confirmedTx]); + }); it('should return a list of transactions, limited by N unique nonces when there are NO duplicates', function () { const submittedTx0 = { @@ -153,7 +153,7 @@ describe('TransactionStateManager', function () { nonce: '0x0', }, status: TRANSACTION_STATUSES.SUBMITTED, - } + }; const unapprovedTx1 = { id: 1, @@ -165,7 +165,7 @@ describe('TransactionStateManager', function () { nonce: '0x1', }, status: TRANSACTION_STATUSES.UNAPPROVED, - } + }; const approvedTx2 = { id: 2, @@ -177,7 +177,7 @@ describe('TransactionStateManager', function () { nonce: '0x2', }, status: TRANSACTION_STATUSES.APPROVED, - } + }; const confirmedTx3 = { id: 3, @@ -189,7 +189,7 @@ describe('TransactionStateManager', function () { nonce: '0x3', }, status: TRANSACTION_STATUSES.CONFIRMED, - } + }; const txm = new TxStateManager({ initState: { @@ -201,10 +201,10 @@ describe('TransactionStateManager', function () { ], }, getNetwork: () => currentNetworkId, - }) + }); - assert.deepEqual(txm.getTxList(2), [approvedTx2, confirmedTx3]) - }) + assert.deepEqual(txm.getTxList(2), [approvedTx2, confirmedTx3]); + }); it('should return a list of transactions, limited by N unique nonces when there ARE duplicates', function () { const submittedTx0s = [ @@ -230,7 +230,7 @@ describe('TransactionStateManager', function () { }, status: TRANSACTION_STATUSES.SUBMITTED, }, - ] + ]; const unapprovedTx1 = { id: 1, @@ -242,7 +242,7 @@ describe('TransactionStateManager', function () { nonce: '0x1', }, status: TRANSACTION_STATUSES.UNAPPROVED, - } + }; const approvedTx2s = [ { @@ -267,7 +267,7 @@ describe('TransactionStateManager', function () { }, status: TRANSACTION_STATUSES.APPROVED, }, - ] + ]; const failedTx3s = [ { @@ -292,7 +292,7 @@ describe('TransactionStateManager', function () { }, status: TRANSACTION_STATUSES.FAILED, }, - ] + ]; const txm = new TxStateManager({ initState: { @@ -304,11 +304,11 @@ describe('TransactionStateManager', function () { ], }, getNetwork: () => currentNetworkId, - }) + }); - assert.deepEqual(txm.getTxList(2), [...approvedTx2s, ...failedTx3s]) - }) - }) + assert.deepEqual(txm.getTxList(2), [...approvedTx2s, ...failedTx3s]); + }); + }); describe('#addTx', function () { it('adds a tx returned in getTxList', function () { @@ -317,13 +317,13 @@ describe('TransactionStateManager', function () { status: TRANSACTION_STATUSES.CONFIRMED, metamaskNetworkId: currentNetworkId, txParams: {}, - } - txStateManager.addTx(tx, noop) - const result = txStateManager.getTxList() - assert.ok(Array.isArray(result)) - assert.equal(result.length, 1) - assert.equal(result[0].id, 1) - }) + }; + txStateManager.addTx(tx, noop); + const result = txStateManager.getTxList(); + assert.ok(Array.isArray(result)); + assert.equal(result.length, 1); + assert.equal(result[0].id, 1); + }); it('throws error and does not add tx if txParams are invalid', function () { const validTxParams = { @@ -334,8 +334,8 @@ describe('TransactionStateManager', function () { gasPrice: '0x77359400', value: '0x0', data: '0x0', - } - const invalidValues = [1, true, {}, Symbol('1')] + }; + const invalidValues = [1, true, {}, Symbol('1')]; Object.keys(validTxParams).forEach((key) => { for (const value of invalidValues) { @@ -347,17 +347,17 @@ describe('TransactionStateManager', function () { ...validTxParams, [key]: value, }, - } + }; assert.throws( txStateManager.addTx.bind(txStateManager, tx), 'addTx should throw error', - ) - const result = txStateManager.getTxList() - assert.ok(Array.isArray(result), 'txList should be an array') - assert.equal(result.length, 0, 'txList should be empty') + ); + const result = txStateManager.getTxList(); + assert.ok(Array.isArray(result), 'txList should be an array'); + assert.equal(result.length, 0, 'txList should be empty'); } - }) - }) + }); + }); it('does not override txs from other networks', function () { const tx = { @@ -365,23 +365,23 @@ describe('TransactionStateManager', function () { status: TRANSACTION_STATUSES.CONFIRMED, metamaskNetworkId: currentNetworkId, txParams: {}, - } + }; const tx2 = { id: 2, status: TRANSACTION_STATUSES.CONFIRMED, metamaskNetworkId: otherNetworkId, txParams: {}, - } - txStateManager.addTx(tx, noop) - txStateManager.addTx(tx2, noop) - const result = txStateManager.getFullTxList() - const result2 = txStateManager.getTxList() - assert.equal(result.length, 2, 'txs were deleted') - assert.equal(result2.length, 1, 'incorrect number of txs on network.') - }) + }; + txStateManager.addTx(tx, noop); + txStateManager.addTx(tx2, noop); + const result = txStateManager.getFullTxList(); + const result2 = txStateManager.getTxList(); + assert.equal(result.length, 2, 'txs were deleted'); + assert.equal(result2.length, 1, 'incorrect number of txs on network.'); + }); it('cuts off early txs beyond a limit', function () { - const limit = txStateManager.txHistoryLimit + const limit = txStateManager.txHistoryLimit; for (let i = 0; i < limit + 1; i++) { const tx = { id: i, @@ -389,16 +389,16 @@ describe('TransactionStateManager', function () { status: TRANSACTION_STATUSES.CONFIRMED, metamaskNetworkId: currentNetworkId, txParams: {}, - } - txStateManager.addTx(tx, noop) + }; + txStateManager.addTx(tx, noop); } - const result = txStateManager.getTxList() - assert.equal(result.length, limit, `limit of ${limit} txs enforced`) - assert.equal(result[0].id, 1, 'early txs truncated') - }) + const result = txStateManager.getTxList(); + assert.equal(result.length, limit, `limit of ${limit} txs enforced`); + assert.equal(result[0].id, 1, 'early txs truncated'); + }); it('cuts off early txs beyond a limit whether or not it is confirmed or rejected', function () { - const limit = txStateManager.txHistoryLimit + const limit = txStateManager.txHistoryLimit; for (let i = 0; i < limit + 1; i++) { const tx = { id: i, @@ -406,13 +406,13 @@ describe('TransactionStateManager', function () { status: TRANSACTION_STATUSES.REJECTED, metamaskNetworkId: currentNetworkId, txParams: {}, - } - txStateManager.addTx(tx, noop) + }; + txStateManager.addTx(tx, noop); } - const result = txStateManager.getTxList() - assert.equal(result.length, limit, `limit of ${limit} txs enforced`) - assert.equal(result[0].id, 1, 'early txs truncated') - }) + const result = txStateManager.getTxList(); + assert.equal(result.length, limit, `limit of ${limit} txs enforced`); + assert.equal(result[0].id, 1, 'early txs truncated'); + }); it('cuts off early txs beyond a limit but does not cut unapproved txs', function () { const unconfirmedTx = { @@ -421,9 +421,9 @@ describe('TransactionStateManager', function () { status: TRANSACTION_STATUSES.UNAPPROVED, metamaskNetworkId: currentNetworkId, txParams: {}, - } - txStateManager.addTx(unconfirmedTx, noop) - const limit = txStateManager.txHistoryLimit + }; + txStateManager.addTx(unconfirmedTx, noop); + const limit = txStateManager.txHistoryLimit; for (let i = 1; i < limit + 1; i++) { const tx = { id: i, @@ -431,20 +431,20 @@ describe('TransactionStateManager', function () { status: TRANSACTION_STATUSES.CONFIRMED, metamaskNetworkId: currentNetworkId, txParams: {}, - } - txStateManager.addTx(tx, noop) + }; + txStateManager.addTx(tx, noop); } - const result = txStateManager.getTxList() - assert.equal(result.length, limit, `limit of ${limit} txs enforced`) - assert.equal(result[0].id, 0, 'first tx should still be there') + const result = txStateManager.getTxList(); + assert.equal(result.length, limit, `limit of ${limit} txs enforced`); + assert.equal(result[0].id, 0, 'first tx should still be there'); assert.equal( result[0].status, TRANSACTION_STATUSES.UNAPPROVED, 'first tx should be unapproved', - ) - assert.equal(result[1].id, 2, 'early txs truncated') - }) - }) + ); + assert.equal(result[1].id, 2, 'early txs truncated'); + }); + }); describe('#updateTx', function () { it('replaces the tx with the same id', function () { @@ -456,7 +456,7 @@ describe('TransactionStateManager', function () { txParams: {}, }, noop, - ) + ); txStateManager.addTx( { id: '2', @@ -465,13 +465,13 @@ describe('TransactionStateManager', function () { txParams: {}, }, noop, - ) - const txMeta = txStateManager.getTx('1') - txMeta.hash = 'foo' - txStateManager.updateTx(txMeta) - const result = txStateManager.getTx('1') - assert.equal(result.hash, 'foo') - }) + ); + const txMeta = txStateManager.getTx('1'); + txMeta.hash = 'foo'; + txStateManager.updateTx(txMeta); + const result = txStateManager.getTx('1'); + assert.equal(result.hash, 'foo'); + }); it('throws error and does not update tx if txParams are invalid', function () { const validTxParams = { @@ -482,39 +482,39 @@ describe('TransactionStateManager', function () { gasPrice: '0x77359400', value: '0x0', data: '0x0', - } - const invalidValues = [1, true, {}, Symbol('1')] + }; + const invalidValues = [1, true, {}, Symbol('1')]; txStateManager.addTx({ id: 1, status: TRANSACTION_STATUSES.UNAPPROVED, metamaskNetworkId: currentNetworkId, txParams: validTxParams, - }) + }); Object.keys(validTxParams).forEach((key) => { for (const value of invalidValues) { - const originalTx = txStateManager.getTx(1) + const originalTx = txStateManager.getTx(1); const newTx = { ...originalTx, txParams: { ...originalTx.txParams, [key]: value, }, - } + }; assert.throws( txStateManager.updateTx.bind(txStateManager, newTx), 'updateTx should throw an error', - ) - const result = txStateManager.getTx(1) - assert.deepEqual(result, originalTx, 'tx should not be updated') + ); + const result = txStateManager.getTx(1); + assert.deepEqual(result, originalTx, 'tx should not be updated'); } - }) - }) + }); + }); it('updates gas price and adds history items', function () { - const originalGasPrice = '0x01' - const desiredGasPrice = '0x02' + const originalGasPrice = '0x01'; + const desiredGasPrice = '0x02'; const txMeta = { id: '1', @@ -523,71 +523,71 @@ describe('TransactionStateManager', function () { txParams: { gasPrice: originalGasPrice, }, - } + }; - txStateManager.addTx(txMeta) - const updatedTx = txStateManager.getTx('1') + txStateManager.addTx(txMeta); + const updatedTx = txStateManager.getTx('1'); // verify tx was initialized correctly - assert.equal(updatedTx.history.length, 1, 'one history item (initial)') + assert.equal(updatedTx.history.length, 1, 'one history item (initial)'); assert.equal( Array.isArray(updatedTx.history[0]), false, 'first history item is initial state', - ) + ); assert.deepEqual( updatedTx.history[0], snapshotFromTxMeta(updatedTx), 'first history item is initial state', - ) + ); // modify value and updateTx - updatedTx.txParams.gasPrice = desiredGasPrice - const before = new Date().getTime() - txStateManager.updateTx(updatedTx) - const after = new Date().getTime() + updatedTx.txParams.gasPrice = desiredGasPrice; + const before = new Date().getTime(); + txStateManager.updateTx(updatedTx); + const after = new Date().getTime(); // check updated value - const result = txStateManager.getTx('1') + const result = txStateManager.getTx('1'); assert.equal( result.txParams.gasPrice, desiredGasPrice, 'gas price updated', - ) + ); // validate history was updated assert.equal( result.history.length, 2, 'two history items (initial + diff)', - ) + ); assert.equal( result.history[1].length, 1, 'two history state items (initial + diff)', - ) + ); const expectedEntry = { op: 'replace', path: '/txParams/gasPrice', value: desiredGasPrice, - } + }; assert.deepEqual( result.history[1][0].op, expectedEntry.op, 'two history items (initial + diff) operation', - ) + ); assert.deepEqual( result.history[1][0].path, expectedEntry.path, 'two history items (initial + diff) path', - ) + ); assert.deepEqual( result.history[1][0].value, expectedEntry.value, 'two history items (initial + diff) value', - ) + ); assert.ok( result.history[1][0].timestamp >= before && result.history[1][0].timestamp <= after, - ) - }) + ); + }); it('does NOT add empty history items', function () { const txMeta = { @@ -597,15 +597,15 @@ describe('TransactionStateManager', function () { txParams: { gasPrice: '0x01', }, - } + }; - txStateManager.addTx(txMeta) - txStateManager.updateTx(txMeta) + txStateManager.addTx(txMeta); + txStateManager.updateTx(txMeta); - const { history } = txStateManager.getTx('1') - assert.equal(history.length, 1, 'two history items (initial + diff)') - }) - }) + const { history } = txStateManager.getTx('1'); + assert.equal(history.length, 1, 'two history items (initial + diff)'); + }); + }); describe('#getUnapprovedTxList', function () { it('returns unapproved txs in a hash', function () { @@ -617,7 +617,7 @@ describe('TransactionStateManager', function () { txParams: {}, }, noop, - ) + ); txStateManager.addTx( { id: '2', @@ -626,13 +626,13 @@ describe('TransactionStateManager', function () { txParams: {}, }, noop, - ) - const result = txStateManager.getUnapprovedTxList() - assert.equal(typeof result, 'object') - assert.equal(result['1'].status, TRANSACTION_STATUSES.UNAPPROVED) - assert.equal(result['2'], undefined) - }) - }) + ); + const result = txStateManager.getUnapprovedTxList(); + assert.equal(typeof result, 'object'); + assert.equal(result['1'].status, TRANSACTION_STATUSES.UNAPPROVED); + assert.equal(result['2'], undefined); + }); + }); describe('#getTx', function () { it('returns a tx with the requested id', function () { @@ -644,7 +644,7 @@ describe('TransactionStateManager', function () { txParams: {}, }, noop, - ) + ); txStateManager.addTx( { id: '2', @@ -653,17 +653,17 @@ describe('TransactionStateManager', function () { txParams: {}, }, noop, - ) + ); assert.equal( txStateManager.getTx('1').status, TRANSACTION_STATUSES.UNAPPROVED, - ) + ); assert.equal( txStateManager.getTx('2').status, TRANSACTION_STATUSES.CONFIRMED, - ) - }) - }) + ); + }); + }); describe('#getFilteredTxList', function () { it('returns a tx with the requested data', function () { @@ -728,60 +728,60 @@ describe('TransactionStateManager', function () { txParams: { from: '0xbb', to: '0xaa' }, metamaskNetworkId: currentNetworkId, }, - ] - txMetas.forEach((txMeta) => txStateManager.addTx(txMeta, noop)) - let filterParams + ]; + txMetas.forEach((txMeta) => txStateManager.addTx(txMeta, noop)); + let filterParams; - filterParams = { status: TRANSACTION_STATUSES.UNAPPROVED, from: '0xaa' } + filterParams = { status: TRANSACTION_STATUSES.UNAPPROVED, from: '0xaa' }; assert.equal( txStateManager.getFilteredTxList(filterParams).length, 3, `getFilteredTxList - ${JSON.stringify(filterParams)}`, - ) - filterParams = { status: TRANSACTION_STATUSES.UNAPPROVED, to: '0xaa' } + ); + filterParams = { status: TRANSACTION_STATUSES.UNAPPROVED, to: '0xaa' }; assert.equal( txStateManager.getFilteredTxList(filterParams).length, 2, `getFilteredTxList - ${JSON.stringify(filterParams)}`, - ) - filterParams = { status: TRANSACTION_STATUSES.CONFIRMED, from: '0xbb' } + ); + filterParams = { status: TRANSACTION_STATUSES.CONFIRMED, from: '0xbb' }; assert.equal( txStateManager.getFilteredTxList(filterParams).length, 3, `getFilteredTxList - ${JSON.stringify(filterParams)}`, - ) - filterParams = { status: TRANSACTION_STATUSES.CONFIRMED } + ); + filterParams = { status: TRANSACTION_STATUSES.CONFIRMED }; assert.equal( txStateManager.getFilteredTxList(filterParams).length, 5, `getFilteredTxList - ${JSON.stringify(filterParams)}`, - ) - filterParams = { from: '0xaa' } + ); + filterParams = { from: '0xaa' }; assert.equal( txStateManager.getFilteredTxList(filterParams).length, 5, `getFilteredTxList - ${JSON.stringify(filterParams)}`, - ) - filterParams = { to: '0xaa' } + ); + filterParams = { to: '0xaa' }; assert.equal( txStateManager.getFilteredTxList(filterParams).length, 5, `getFilteredTxList - ${JSON.stringify(filterParams)}`, - ) + ); filterParams = { status: (status) => status !== TRANSACTION_STATUSES.CONFIRMED, - } + }; assert.equal( txStateManager.getFilteredTxList(filterParams).length, 5, `getFilteredTxList - ${JSON.stringify(filterParams)}`, - ) - }) - }) + ); + }); + }); describe('#wipeTransactions', function () { - const specificAddress = '0xaa' - const otherAddress = '0xbb' + const specificAddress = '0xaa'; + const otherAddress = '0xbb'; it('should remove only the transactions from a specific address', function () { const txMetas = [ @@ -803,21 +803,21 @@ describe('TransactionStateManager', function () { txParams: { from: otherAddress, to: specificAddress }, metamaskNetworkId: currentNetworkId, }, - ] - txMetas.forEach((txMeta) => txStateManager.addTx(txMeta, noop)) + ]; + txMetas.forEach((txMeta) => txStateManager.addTx(txMeta, noop)); - txStateManager.wipeTransactions(specificAddress) + txStateManager.wipeTransactions(specificAddress); const transactionsFromCurrentAddress = txStateManager .getTxList() - .filter((txMeta) => txMeta.txParams.from === specificAddress) + .filter((txMeta) => txMeta.txParams.from === specificAddress); const transactionsFromOtherAddresses = txStateManager .getTxList() - .filter((txMeta) => txMeta.txParams.from !== specificAddress) + .filter((txMeta) => txMeta.txParams.from !== specificAddress); - assert.equal(transactionsFromCurrentAddress.length, 0) - assert.equal(transactionsFromOtherAddresses.length, 2) - }) + assert.equal(transactionsFromCurrentAddress.length, 0); + assert.equal(transactionsFromOtherAddresses.length, 2); + }); it('should not remove the transactions from other networks', function () { const txMetas = [ @@ -839,44 +839,44 @@ describe('TransactionStateManager', function () { txParams: { from: specificAddress, to: otherAddress }, metamaskNetworkId: otherNetworkId, }, - ] + ]; - txMetas.forEach((txMeta) => txStateManager.addTx(txMeta, noop)) + txMetas.forEach((txMeta) => txStateManager.addTx(txMeta, noop)); - txStateManager.wipeTransactions(specificAddress) + txStateManager.wipeTransactions(specificAddress); const txsFromCurrentNetworkAndAddress = txStateManager .getTxList() - .filter((txMeta) => txMeta.txParams.from === specificAddress) + .filter((txMeta) => txMeta.txParams.from === specificAddress); const txFromOtherNetworks = txStateManager .getFullTxList() - .filter((txMeta) => txMeta.metamaskNetworkId === otherNetworkId) + .filter((txMeta) => txMeta.metamaskNetworkId === otherNetworkId); - assert.equal(txsFromCurrentNetworkAndAddress.length, 0) - assert.equal(txFromOtherNetworks.length, 2) - }) - }) + assert.equal(txsFromCurrentNetworkAndAddress.length, 0); + assert.equal(txFromOtherNetworks.length, 2); + }); + }); describe('#_removeTx', function () { it('should remove the transaction from the storage', function () { - txStateManager._saveTxList([{ id: 1 }]) - txStateManager._removeTx(1) + txStateManager._saveTxList([{ id: 1 }]); + txStateManager._removeTx(1); assert.ok( !txStateManager.getFullTxList().length, 'txList should be empty', - ) - }) + ); + }); it('should only remove the transaction with ID 1 from the storage', function () { - txStateManager._saveTxList([{ id: 1 }, { id: 2 }]) - txStateManager._removeTx(1) + txStateManager._saveTxList([{ id: 1 }, { id: 2 }]); + txStateManager._removeTx(1); assert.equal( txStateManager.getFullTxList()[0].id, 2, 'txList should have a id of 2', - ) - }) - }) + ); + }); + }); describe('#clearUnapprovedTxs', function () { it('removes unapproved transactions', function () { @@ -905,17 +905,17 @@ describe('TransactionStateManager', function () { txParams: { from: '0xaa', to: '0xbb' }, metamaskNetworkId: otherNetworkId, }, - ] + ]; - txMetas.forEach((txMeta) => txStateManager.addTx(txMeta, noop)) + txMetas.forEach((txMeta) => txStateManager.addTx(txMeta, noop)); - txStateManager.clearUnapprovedTxs() + txStateManager.clearUnapprovedTxs(); const unapprovedTxList = txStateManager .getFullTxList() - .filter((tx) => tx.status === TRANSACTION_STATUSES.UNAPPROVED) + .filter((tx) => tx.status === TRANSACTION_STATUSES.UNAPPROVED); - assert.equal(unapprovedTxList.length, 0) - }) - }) -}) + assert.equal(unapprovedTxList.length, 0); + }); + }); +}); diff --git a/test/unit/app/controllers/transactions/tx-utils-test.js b/test/unit/app/controllers/transactions/tx-utils-test.js index 77add3f62..a643d9dea 100644 --- a/test/unit/app/controllers/transactions/tx-utils-test.js +++ b/test/unit/app/controllers/transactions/tx-utils-test.js @@ -1,5 +1,5 @@ -import { strict as assert } from 'assert' -import * as txUtils from '../../../../../app/scripts/controllers/transactions/lib/util' +import { strict as assert } from 'assert'; +import * as txUtils from '../../../../../app/scripts/controllers/transactions/lib/util'; describe('txUtils', function () { describe('#validateTxParams', function () { @@ -8,47 +8,47 @@ describe('txUtils', function () { from: '0x1678a085c290ebd122dc42cba69373b5953b831d', to: '0xc42edfcc21ed14dda456aa0756c153f7985d8813', value: '0x01', - } - txUtils.validateTxParams(sample) - }) + }; + txUtils.validateTxParams(sample); + }); it('throws for invalid params value', function () { assert.throws(() => txUtils.validateTxParams(), { message: 'Invalid transaction params: must be an object.', - }) + }); assert.throws(() => txUtils.validateTxParams(null), { message: 'Invalid transaction params: must be an object.', - }) + }); assert.throws(() => txUtils.validateTxParams(true), { message: 'Invalid transaction params: must be an object.', - }) + }); assert.throws(() => txUtils.validateTxParams([]), { message: 'Invalid transaction params: must be an object.', - }) - }) + }); + }); it('throws for missing "to" and "data"', function () { const sample = { from: '0x1678a085c290ebd122dc42cba69373b5953b831d', value: '0x01', - } + }; assert.throws(() => txUtils.validateTxParams(sample), { message: 'Invalid transaction params: must specify "data" for contract deployments, or "to" (and optionally "data") for all other types of transactions.', - }) - }) + }); + }); it('throws for negative values', function () { const sample = { from: '0x1678a085c290ebd122dc42cba69373b5953b831d', to: '0xc42edfcc21ed14dda456aa0756c153f7985d8813', value: '-0x01', - } + }; assert.throws(() => txUtils.validateTxParams(sample), { message: 'Invalid transaction value "-0x01": not a positive number.', - }) - }) - }) + }); + }); + }); describe('#normalizeTxParams', function () { it('should normalize txParams', function () { @@ -58,36 +58,39 @@ describe('txUtils', function () { to: null, data: '68656c6c6f20776f726c64', random: 'hello world', - } + }; - let normalizedTxParams = txUtils.normalizeTxParams(txParams) + let normalizedTxParams = txUtils.normalizeTxParams(txParams); - assert.ok(!normalizedTxParams.chainId, 'there should be no chainId') - assert.ok(!normalizedTxParams.to, 'there should be no to address if null') + assert.ok(!normalizedTxParams.chainId, 'there should be no chainId'); + assert.ok( + !normalizedTxParams.to, + 'there should be no to address if null', + ); assert.equal( normalizedTxParams.from.slice(0, 2), '0x', 'from should be hex-prefixed', - ) + ); assert.equal( normalizedTxParams.data.slice(0, 2), '0x', 'data should be hex-prefixed', - ) + ); assert.ok( !('random' in normalizedTxParams), 'there should be no random key in normalizedTxParams', - ) + ); - txParams.to = 'a7df1beDBF813f57096dF77FCd515f0B3900e402' - normalizedTxParams = txUtils.normalizeTxParams(txParams) + txParams.to = 'a7df1beDBF813f57096dF77FCd515f0B3900e402'; + normalizedTxParams = txUtils.normalizeTxParams(txParams); assert.equal( normalizedTxParams.to.slice(0, 2), '0x', 'to should be hex-prefixed', - ) - }) - }) + ); + }); + }); describe('#validateRecipient', function () { it('removes recipient for txParams with 0x when contract data is provided', function () { @@ -95,10 +98,10 @@ describe('txUtils', function () { from: '0x1678a085c290ebd122dc42cba69373b5953b831d', to: '0x', data: 'bytecode', - } + }; const sanitizedTxParams = txUtils.validateRecipient( zeroRecipientDataTxParams, - ) + ); assert.deepEqual( sanitizedTxParams, { @@ -106,69 +109,69 @@ describe('txUtils', function () { data: 'bytecode', }, 'no recipient with 0x', - ) - }) + ); + }); it('should error when recipient is 0x', function () { const zeroRecipientTxParams = { from: '0x1678a085c290ebd122dc42cba69373b5953b831d', to: '0x', - } + }; assert.throws( () => { - txUtils.validateRecipient(zeroRecipientTxParams) + txUtils.validateRecipient(zeroRecipientTxParams); }, Error, 'Invalid recipient address', - ) - }) - }) + ); + }); + }); describe('#validateFrom', function () { it('should error when from is not a hex string', function () { // where from is undefined - const txParams = {} + const txParams = {}; assert.throws( () => { - txUtils.validateFrom(txParams) + txUtils.validateFrom(txParams); }, Error, `Invalid from address ${txParams.from} not a string`, - ) + ); // where from is array - txParams.from = [] + txParams.from = []; assert.throws( () => { - txUtils.validateFrom(txParams) + txUtils.validateFrom(txParams); }, Error, `Invalid from address ${txParams.from} not a string`, - ) + ); // where from is a object - txParams.from = {} + txParams.from = {}; assert.throws( () => { - txUtils.validateFrom(txParams) + txUtils.validateFrom(txParams); }, Error, `Invalid from address ${txParams.from} not a string`, - ) + ); // where from is a invalid address - txParams.from = 'im going to fail' + txParams.from = 'im going to fail'; assert.throws( () => { - txUtils.validateFrom(txParams) + txUtils.validateFrom(txParams); }, Error, `Invalid from address`, - ) + ); // should run - txParams.from = '0x1678a085c290ebd122dc42cba69373b5953b831d' - txUtils.validateFrom(txParams) - }) - }) -}) + txParams.from = '0x1678a085c290ebd122dc42cba69373b5953b831d'; + txUtils.validateFrom(txParams); + }); + }); +}); diff --git a/test/unit/app/fetch-with-timeout.test.js b/test/unit/app/fetch-with-timeout.test.js index dd91ff58b..9a8aae403 100644 --- a/test/unit/app/fetch-with-timeout.test.js +++ b/test/unit/app/fetch-with-timeout.test.js @@ -1,57 +1,61 @@ -import assert from 'assert' -import nock from 'nock' +import assert from 'assert'; +import nock from 'nock'; -import getFetchWithTimeout from '../../../shared/modules/fetch-with-timeout' +import getFetchWithTimeout from '../../../shared/modules/fetch-with-timeout'; describe('getFetchWithTimeout', function () { it('fetches a url', async function () { - nock('https://api.infura.io').get('/money').reply(200, '{"hodl": false}') + nock('https://api.infura.io').get('/money').reply(200, '{"hodl": false}'); - const fetchWithTimeout = getFetchWithTimeout(30000) + const fetchWithTimeout = getFetchWithTimeout(30000); const response = await ( await fetchWithTimeout('https://api.infura.io/money') - ).json() + ).json(); assert.deepEqual(response, { hodl: false, - }) - }) + }); + }); it('throws when the request hits a custom timeout', async function () { nock('https://api.infura.io') .get('/moon') .delay(2000) - .reply(200, '{"moon": "2012-12-21T11:11:11Z"}') + .reply(200, '{"moon": "2012-12-21T11:11:11Z"}'); - const fetchWithTimeout = getFetchWithTimeout(123) + const fetchWithTimeout = getFetchWithTimeout(123); try { - await fetchWithTimeout('https://api.infura.io/moon').then((r) => r.json()) - assert.fail('Request should throw') + await fetchWithTimeout('https://api.infura.io/moon').then((r) => + r.json(), + ); + assert.fail('Request should throw'); } catch (e) { - assert.ok(e) + assert.ok(e); } - }) + }); it('should abort the request when the custom timeout is hit', async function () { nock('https://api.infura.io') .get('/moon') .delay(2000) - .reply(200, '{"moon": "2012-12-21T11:11:11Z"}') + .reply(200, '{"moon": "2012-12-21T11:11:11Z"}'); - const fetchWithTimeout = getFetchWithTimeout(123) + const fetchWithTimeout = getFetchWithTimeout(123); try { - await fetchWithTimeout('https://api.infura.io/moon').then((r) => r.json()) - assert.fail('Request should be aborted') + await fetchWithTimeout('https://api.infura.io/moon').then((r) => + r.json(), + ); + assert.fail('Request should be aborted'); } catch (e) { - assert.deepEqual(e.message, 'Aborted') + assert.deepEqual(e.message, 'Aborted'); } - }) + }); it('throws on invalid timeout', async function () { - assert.throws(() => getFetchWithTimeout(), 'should throw') - assert.throws(() => getFetchWithTimeout(-1), 'should throw') - assert.throws(() => getFetchWithTimeout({}), 'should throw') - assert.throws(() => getFetchWithTimeout(true), 'should throw') - }) -}) + assert.throws(() => getFetchWithTimeout(), 'should throw'); + assert.throws(() => getFetchWithTimeout(-1), 'should throw'); + assert.throws(() => getFetchWithTimeout({}), 'should throw'); + assert.throws(() => getFetchWithTimeout(true), 'should throw'); + }); +}); diff --git a/test/unit/app/message-manager-test.js b/test/unit/app/message-manager-test.js index cd1769cda..2c0589e63 100644 --- a/test/unit/app/message-manager-test.js +++ b/test/unit/app/message-manager-test.js @@ -1,21 +1,21 @@ -import assert from 'assert' -import MessageManager from '../../../app/scripts/lib/message-manager' -import { TRANSACTION_STATUSES } from '../../../shared/constants/transaction' +import assert from 'assert'; +import MessageManager from '../../../app/scripts/lib/message-manager'; +import { TRANSACTION_STATUSES } from '../../../shared/constants/transaction'; describe('Message Manager', function () { - let messageManager + let messageManager; beforeEach(function () { - messageManager = new MessageManager() - }) + messageManager = new MessageManager(); + }); describe('#getMsgList', function () { it('when new should return empty array', function () { - const result = messageManager.messages - assert.ok(Array.isArray(result)) - assert.equal(result.length, 0) - }) - }) + const result = messageManager.messages; + assert.ok(Array.isArray(result)); + assert.equal(result.length, 0); + }); + }); describe('#addMsg', function () { it('adds a Msg returned in getMsgList', function () { @@ -23,14 +23,14 @@ describe('Message Manager', function () { id: 1, status: TRANSACTION_STATUSES.APPROVED, metamaskNetworkId: 'unit test', - } - messageManager.addMsg(Msg) - const result = messageManager.messages - assert.ok(Array.isArray(result)) - assert.equal(result.length, 1) - assert.equal(result[0].id, 1) - }) - }) + }; + messageManager.addMsg(Msg); + const result = messageManager.messages; + assert.ok(Array.isArray(result)); + assert.equal(result.length, 1); + assert.equal(result[0].id, 1); + }); + }); describe('#setMsgStatusApproved', function () { it('sets the Msg status to approved', function () { @@ -38,15 +38,15 @@ describe('Message Manager', function () { id: 1, status: 'unapproved', metamaskNetworkId: 'unit test', - } - messageManager.addMsg(Msg) - messageManager.setMsgStatusApproved(1) - const result = messageManager.messages - assert.ok(Array.isArray(result)) - assert.equal(result.length, 1) - assert.equal(result[0].status, TRANSACTION_STATUSES.APPROVED) - }) - }) + }; + messageManager.addMsg(Msg); + messageManager.setMsgStatusApproved(1); + const result = messageManager.messages; + assert.ok(Array.isArray(result)); + assert.equal(result.length, 1); + assert.equal(result[0].status, TRANSACTION_STATUSES.APPROVED); + }); + }); describe('#rejectMsg', function () { it('sets the Msg status to rejected', function () { @@ -54,15 +54,15 @@ describe('Message Manager', function () { id: 1, status: 'unapproved', metamaskNetworkId: 'unit test', - } - messageManager.addMsg(Msg) - messageManager.rejectMsg(1) - const result = messageManager.messages - assert.ok(Array.isArray(result)) - assert.equal(result.length, 1) - assert.equal(result[0].status, TRANSACTION_STATUSES.REJECTED) - }) - }) + }; + messageManager.addMsg(Msg); + messageManager.rejectMsg(1); + const result = messageManager.messages; + assert.ok(Array.isArray(result)); + assert.equal(result.length, 1); + assert.equal(result[0].status, TRANSACTION_STATUSES.REJECTED); + }); + }); describe('#_updateMsg', function () { it('replaces the Msg with the same id', function () { @@ -70,22 +70,22 @@ describe('Message Manager', function () { id: '1', status: 'unapproved', metamaskNetworkId: 'unit test', - }) + }); messageManager.addMsg({ id: '2', status: TRANSACTION_STATUSES.APPROVED, metamaskNetworkId: 'unit test', - }) + }); messageManager._updateMsg({ id: '1', status: 'blah', hash: 'foo', metamaskNetworkId: 'unit test', - }) - const result = messageManager.getMsg('1') - assert.equal(result.hash, 'foo') - }) - }) + }); + const result = messageManager.getMsg('1'); + assert.equal(result.hash, 'foo'); + }); + }); describe('#getUnapprovedMsgs', function () { it('returns unapproved Msgs in a hash', function () { @@ -93,18 +93,18 @@ describe('Message Manager', function () { id: '1', status: 'unapproved', metamaskNetworkId: 'unit test', - }) + }); messageManager.addMsg({ id: '2', status: TRANSACTION_STATUSES.APPROVED, metamaskNetworkId: 'unit test', - }) - const result = messageManager.getUnapprovedMsgs() - assert.equal(typeof result, 'object') - assert.equal(result['1'].status, 'unapproved') - assert.equal(result['2'], undefined) - }) - }) + }); + const result = messageManager.getUnapprovedMsgs(); + assert.equal(typeof result, 'object'); + assert.equal(result['1'].status, 'unapproved'); + assert.equal(result['2'], undefined); + }); + }); describe('#getMsg', function () { it('returns a Msg with the requested id', function () { @@ -112,17 +112,17 @@ describe('Message Manager', function () { id: '1', status: 'unapproved', metamaskNetworkId: 'unit test', - }) + }); messageManager.addMsg({ id: '2', status: TRANSACTION_STATUSES.APPROVED, metamaskNetworkId: 'unit test', - }) - assert.equal(messageManager.getMsg('1').status, 'unapproved') + }); + assert.equal(messageManager.getMsg('1').status, 'unapproved'); assert.equal( messageManager.getMsg('2').status, TRANSACTION_STATUSES.APPROVED, - ) - }) - }) -}) + ); + }); + }); +}); diff --git a/test/unit/app/nodeify-test.js b/test/unit/app/nodeify-test.js index 050553e61..2418f40bc 100644 --- a/test/unit/app/nodeify-test.js +++ b/test/unit/app/nodeify-test.js @@ -1,74 +1,74 @@ -import assert from 'assert' -import nodeify from '../../../app/scripts/lib/nodeify' +import assert from 'assert'; +import nodeify from '../../../app/scripts/lib/nodeify'; describe('nodeify', function () { const obj = { foo: 'bar', promiseFunc(a) { - const solution = this.foo + a - return Promise.resolve(solution) + const solution = this.foo + a; + return Promise.resolve(solution); }, - } + }; it('should retain original context', function (done) { - const nodified = nodeify(obj.promiseFunc, obj) + const nodified = nodeify(obj.promiseFunc, obj); nodified('baz', (err, res) => { if (!err) { - assert.equal(res, 'barbaz') - done() - return + assert.equal(res, 'barbaz'); + done(); + return; } - done(new Error(err.toString())) - }) - }) + done(new Error(err.toString())); + }); + }); it('no callback - should allow the last argument to not be a function', function (done) { - const nodified = nodeify(obj.promiseFunc, obj) + const nodified = nodeify(obj.promiseFunc, obj); try { - nodified('baz') - done() + nodified('baz'); + done(); } catch (err) { done( new Error( 'should not have thrown if the last argument is not a function', ), - ) + ); } - }) + }); it('sync functions - returns value', function (done) { - const nodified = nodeify(() => 42) + const nodified = nodeify(() => 42); try { nodified((err, result) => { if (err) { - done(new Error(`should not have thrown any error: ${err.message}`)) - return + done(new Error(`should not have thrown any error: ${err.message}`)); + return; } - assert.equal(42, result, 'got expected result') - }) - done() + assert.equal(42, result, 'got expected result'); + }); + done(); } catch (err) { - done(new Error(`should not have thrown any error: ${err.message}`)) + done(new Error(`should not have thrown any error: ${err.message}`)); } - }) + }); it('sync functions - handles errors', function (done) { const nodified = nodeify(() => { - throw new Error('boom!') - }) + throw new Error('boom!'); + }); try { nodified((err, result) => { if (result) { - done(new Error('should not have returned any result')) - return + done(new Error('should not have returned any result')); + return; } - assert.ok(err, 'got expected error') - assert.ok(err.message.includes('boom!'), 'got expected error message') - }) - done() + assert.ok(err, 'got expected error'); + assert.ok(err.message.includes('boom!'), 'got expected error message'); + }); + done(); } catch (err) { - done(new Error(`should not have thrown any error: ${err.message}`)) + done(new Error(`should not have thrown any error: ${err.message}`)); } - }) -}) + }); +}); diff --git a/test/unit/app/personal-message-manager-test.js b/test/unit/app/personal-message-manager-test.js index fd1aa9164..15035a111 100644 --- a/test/unit/app/personal-message-manager-test.js +++ b/test/unit/app/personal-message-manager-test.js @@ -1,21 +1,21 @@ -import assert from 'assert' -import PersonalMessageManager from '../../../app/scripts/lib/personal-message-manager' -import { TRANSACTION_STATUSES } from '../../../shared/constants/transaction' +import assert from 'assert'; +import PersonalMessageManager from '../../../app/scripts/lib/personal-message-manager'; +import { TRANSACTION_STATUSES } from '../../../shared/constants/transaction'; describe('Personal Message Manager', function () { - let messageManager + let messageManager; beforeEach(function () { - messageManager = new PersonalMessageManager() - }) + messageManager = new PersonalMessageManager(); + }); describe('#getMsgList', function () { it('when new should return empty array', function () { - const result = messageManager.messages - assert.ok(Array.isArray(result)) - assert.equal(result.length, 0) - }) - }) + const result = messageManager.messages; + assert.ok(Array.isArray(result)); + assert.equal(result.length, 0); + }); + }); describe('#addMsg', function () { it('adds a Msg returned in getMsgList', function () { @@ -23,14 +23,14 @@ describe('Personal Message Manager', function () { id: 1, status: TRANSACTION_STATUSES.APPROVED, metamaskNetworkId: 'unit test', - } - messageManager.addMsg(Msg) - const result = messageManager.messages - assert.ok(Array.isArray(result)) - assert.equal(result.length, 1) - assert.equal(result[0].id, 1) - }) - }) + }; + messageManager.addMsg(Msg); + const result = messageManager.messages; + assert.ok(Array.isArray(result)); + assert.equal(result.length, 1); + assert.equal(result[0].id, 1); + }); + }); describe('#setMsgStatusApproved', function () { it('sets the Msg status to approved', function () { @@ -38,15 +38,15 @@ describe('Personal Message Manager', function () { id: 1, status: TRANSACTION_STATUSES.UNAPPROVED, metamaskNetworkId: 'unit test', - } - messageManager.addMsg(Msg) - messageManager.setMsgStatusApproved(1) - const result = messageManager.messages - assert.ok(Array.isArray(result)) - assert.equal(result.length, 1) - assert.equal(result[0].status, TRANSACTION_STATUSES.APPROVED) - }) - }) + }; + messageManager.addMsg(Msg); + messageManager.setMsgStatusApproved(1); + const result = messageManager.messages; + assert.ok(Array.isArray(result)); + assert.equal(result.length, 1); + assert.equal(result[0].status, TRANSACTION_STATUSES.APPROVED); + }); + }); describe('#rejectMsg', function () { it('sets the Msg status to rejected', function () { @@ -54,15 +54,15 @@ describe('Personal Message Manager', function () { id: 1, status: TRANSACTION_STATUSES.UNAPPROVED, metamaskNetworkId: 'unit test', - } - messageManager.addMsg(Msg) - messageManager.rejectMsg(1) - const result = messageManager.messages - assert.ok(Array.isArray(result)) - assert.equal(result.length, 1) - assert.equal(result[0].status, TRANSACTION_STATUSES.REJECTED) - }) - }) + }; + messageManager.addMsg(Msg); + messageManager.rejectMsg(1); + const result = messageManager.messages; + assert.ok(Array.isArray(result)); + assert.equal(result.length, 1); + assert.equal(result[0].status, TRANSACTION_STATUSES.REJECTED); + }); + }); describe('#_updateMsg', function () { it('replaces the Msg with the same id', function () { @@ -70,22 +70,22 @@ describe('Personal Message Manager', function () { id: '1', status: TRANSACTION_STATUSES.UNAPPROVED, metamaskNetworkId: 'unit test', - }) + }); messageManager.addMsg({ id: '2', status: TRANSACTION_STATUSES.APPROVED, metamaskNetworkId: 'unit test', - }) + }); messageManager._updateMsg({ id: '1', status: 'blah', hash: 'foo', metamaskNetworkId: 'unit test', - }) - const result = messageManager.getMsg('1') - assert.equal(result.hash, 'foo') - }) - }) + }); + const result = messageManager.getMsg('1'); + assert.equal(result.hash, 'foo'); + }); + }); describe('#getUnapprovedMsgs', function () { it('returns unapproved Msgs in a hash', function () { @@ -93,18 +93,18 @@ describe('Personal Message Manager', function () { id: '1', status: TRANSACTION_STATUSES.UNAPPROVED, metamaskNetworkId: 'unit test', - }) + }); messageManager.addMsg({ id: '2', status: TRANSACTION_STATUSES.APPROVED, metamaskNetworkId: 'unit test', - }) - const result = messageManager.getUnapprovedMsgs() - assert.equal(typeof result, 'object') - assert.equal(result['1'].status, TRANSACTION_STATUSES.UNAPPROVED) - assert.equal(result['2'], undefined) - }) - }) + }); + const result = messageManager.getUnapprovedMsgs(); + assert.equal(typeof result, 'object'); + assert.equal(result['1'].status, TRANSACTION_STATUSES.UNAPPROVED); + assert.equal(result['2'], undefined); + }); + }); describe('#getMsg', function () { it('returns a Msg with the requested id', function () { @@ -112,40 +112,40 @@ describe('Personal Message Manager', function () { id: '1', status: TRANSACTION_STATUSES.UNAPPROVED, metamaskNetworkId: 'unit test', - }) + }); messageManager.addMsg({ id: '2', status: TRANSACTION_STATUSES.APPROVED, metamaskNetworkId: 'unit test', - }) + }); assert.equal( messageManager.getMsg('1').status, TRANSACTION_STATUSES.UNAPPROVED, - ) + ); assert.equal( messageManager.getMsg('2').status, TRANSACTION_STATUSES.APPROVED, - ) - }) - }) + ); + }); + }); describe('#normalizeMsgData', function () { it('converts text to a utf8 hex string', function () { - const input = 'hello' - const output = messageManager.normalizeMsgData(input) - assert.equal(output, '0x68656c6c6f', 'predictably hex encoded') - }) + const input = 'hello'; + const output = messageManager.normalizeMsgData(input); + assert.equal(output, '0x68656c6c6f', 'predictably hex encoded'); + }); it('tolerates a hex prefix', function () { - const input = '0x12' - const output = messageManager.normalizeMsgData(input) - assert.equal(output, '0x12', 'un modified') - }) + const input = '0x12'; + const output = messageManager.normalizeMsgData(input); + assert.equal(output, '0x12', 'un modified'); + }); it('tolerates normal hex', function () { - const input = '12' - const output = messageManager.normalizeMsgData(input) - assert.equal(output, '0x12', 'adds prefix') - }) - }) -}) + const input = '12'; + const output = messageManager.normalizeMsgData(input); + assert.equal(output, '0x12', 'adds prefix'); + }); + }); +}); diff --git a/test/unit/app/seed-phrase-verifier-test.js b/test/unit/app/seed-phrase-verifier-test.js index 9f569c556..650f97eb3 100644 --- a/test/unit/app/seed-phrase-verifier-test.js +++ b/test/unit/app/seed-phrase-verifier-test.js @@ -1,129 +1,129 @@ -import assert from 'assert' -import { cloneDeep } from 'lodash' -import KeyringController from 'eth-keyring-controller' -import firstTimeState from '../../../app/scripts/first-time-state' -import seedPhraseVerifier from '../../../app/scripts/lib/seed-phrase-verifier' -import mockEncryptor from '../../lib/mock-encryptor' +import assert from 'assert'; +import { cloneDeep } from 'lodash'; +import KeyringController from 'eth-keyring-controller'; +import firstTimeState from '../../../app/scripts/first-time-state'; +import seedPhraseVerifier from '../../../app/scripts/lib/seed-phrase-verifier'; +import mockEncryptor from '../../lib/mock-encryptor'; describe('SeedPhraseVerifier', function () { describe('verifyAccounts', function () { - const password = 'passw0rd1' - const hdKeyTree = 'HD Key Tree' + const password = 'passw0rd1'; + const hdKeyTree = 'HD Key Tree'; - let keyringController - let primaryKeyring + let keyringController; + let primaryKeyring; beforeEach(async function () { keyringController = new KeyringController({ initState: cloneDeep(firstTimeState), encryptor: mockEncryptor, - }) + }); - assert(keyringController) + assert(keyringController); - await keyringController.createNewVaultAndKeychain(password) - primaryKeyring = keyringController.getKeyringsByType(hdKeyTree)[0] - }) + await keyringController.createNewVaultAndKeychain(password); + primaryKeyring = keyringController.getKeyringsByType(hdKeyTree)[0]; + }); it('should be able to verify created account with seed words', async function () { - const createdAccounts = await primaryKeyring.getAccounts() - assert.equal(createdAccounts.length, 1) + const createdAccounts = await primaryKeyring.getAccounts(); + assert.equal(createdAccounts.length, 1); - const serialized = await primaryKeyring.serialize() - const seedWords = serialized.mnemonic - assert.notEqual(seedWords.length, 0) + const serialized = await primaryKeyring.serialize(); + const seedWords = serialized.mnemonic; + assert.notEqual(seedWords.length, 0); - await seedPhraseVerifier.verifyAccounts(createdAccounts, seedWords) - }) + await seedPhraseVerifier.verifyAccounts(createdAccounts, seedWords); + }); it('should be able to verify created account (upper case) with seed words', async function () { - const createdAccounts = await primaryKeyring.getAccounts() - assert.equal(createdAccounts.length, 1) + const createdAccounts = await primaryKeyring.getAccounts(); + assert.equal(createdAccounts.length, 1); - const upperCaseAccounts = [createdAccounts[0].toUpperCase()] + const upperCaseAccounts = [createdAccounts[0].toUpperCase()]; - const serialized = await primaryKeyring.serialize() - const seedWords = serialized.mnemonic - assert.notEqual(seedWords.length, 0) + const serialized = await primaryKeyring.serialize(); + const seedWords = serialized.mnemonic; + assert.notEqual(seedWords.length, 0); - await seedPhraseVerifier.verifyAccounts(upperCaseAccounts, seedWords) - }) + await seedPhraseVerifier.verifyAccounts(upperCaseAccounts, seedWords); + }); it('should be able to verify created account (lower case) with seed words', async function () { - const createdAccounts = await primaryKeyring.getAccounts() - assert.equal(createdAccounts.length, 1) - const lowerCaseAccounts = [createdAccounts[0].toLowerCase()] + const createdAccounts = await primaryKeyring.getAccounts(); + assert.equal(createdAccounts.length, 1); + const lowerCaseAccounts = [createdAccounts[0].toLowerCase()]; - const serialized = await primaryKeyring.serialize() - const seedWords = serialized.mnemonic - assert.notEqual(seedWords.length, 0) + const serialized = await primaryKeyring.serialize(); + const seedWords = serialized.mnemonic; + assert.notEqual(seedWords.length, 0); - await seedPhraseVerifier.verifyAccounts(lowerCaseAccounts, seedWords) - }) + await seedPhraseVerifier.verifyAccounts(lowerCaseAccounts, seedWords); + }); it('should return error with good but different seed words', async function () { - const createdAccounts = await primaryKeyring.getAccounts() - assert.equal(createdAccounts.length, 1) + const createdAccounts = await primaryKeyring.getAccounts(); + assert.equal(createdAccounts.length, 1); - await primaryKeyring.serialize() + await primaryKeyring.serialize(); const seedWords = - 'debris dizzy just program just float decrease vacant alarm reduce speak stadium' + 'debris dizzy just program just float decrease vacant alarm reduce speak stadium'; try { - await seedPhraseVerifier.verifyAccounts(createdAccounts, seedWords) - assert.fail('Should reject') + await seedPhraseVerifier.verifyAccounts(createdAccounts, seedWords); + assert.fail('Should reject'); } catch (err) { assert.ok( err.message.indexOf('Not identical accounts!') >= 0, 'Wrong error message', - ) + ); } - }) + }); it('should return error with undefined existing accounts', async function () { - const createdAccounts = await primaryKeyring.getAccounts() - assert.equal(createdAccounts.length, 1) + const createdAccounts = await primaryKeyring.getAccounts(); + assert.equal(createdAccounts.length, 1); - await primaryKeyring.serialize() + await primaryKeyring.serialize(); const seedWords = - 'debris dizzy just program just float decrease vacant alarm reduce speak stadium' + 'debris dizzy just program just float decrease vacant alarm reduce speak stadium'; try { - await seedPhraseVerifier.verifyAccounts(undefined, seedWords) - assert.fail('Should reject') + await seedPhraseVerifier.verifyAccounts(undefined, seedWords); + assert.fail('Should reject'); } catch (err) { - assert.equal(err.message, 'No created accounts defined.') + assert.equal(err.message, 'No created accounts defined.'); } - }) + }); it('should return error with empty accounts array', async function () { - const createdAccounts = await primaryKeyring.getAccounts() - assert.equal(createdAccounts.length, 1) + const createdAccounts = await primaryKeyring.getAccounts(); + assert.equal(createdAccounts.length, 1); - await primaryKeyring.serialize() + await primaryKeyring.serialize(); const seedWords = - 'debris dizzy just program just float decrease vacant alarm reduce speak stadium' + 'debris dizzy just program just float decrease vacant alarm reduce speak stadium'; try { - await seedPhraseVerifier.verifyAccounts([], seedWords) - assert.fail('Should reject') + await seedPhraseVerifier.verifyAccounts([], seedWords); + assert.fail('Should reject'); } catch (err) { - assert.equal(err.message, 'No created accounts defined.') + assert.equal(err.message, 'No created accounts defined.'); } - }) + }); it('should be able to verify more than one created account with seed words', async function () { - await keyringController.addNewAccount(primaryKeyring) - await keyringController.addNewAccount(primaryKeyring) + await keyringController.addNewAccount(primaryKeyring); + await keyringController.addNewAccount(primaryKeyring); - const createdAccounts = await primaryKeyring.getAccounts() - assert.equal(createdAccounts.length, 3) + const createdAccounts = await primaryKeyring.getAccounts(); + assert.equal(createdAccounts.length, 3); - const serialized = await primaryKeyring.serialize() - const seedWords = serialized.mnemonic - assert.notEqual(seedWords.length, 0) + const serialized = await primaryKeyring.serialize(); + const seedWords = serialized.mnemonic; + assert.notEqual(seedWords.length, 0); - await seedPhraseVerifier.verifyAccounts(createdAccounts, seedWords) - }) - }) -}) + await seedPhraseVerifier.verifyAccounts(createdAccounts, seedWords); + }); + }); +}); diff --git a/test/unit/app/typed-message-manager.spec.js b/test/unit/app/typed-message-manager.spec.js index b396b0c22..5d7333688 100644 --- a/test/unit/app/typed-message-manager.spec.js +++ b/test/unit/app/typed-message-manager.spec.js @@ -1,7 +1,7 @@ -import assert from 'assert' -import sinon from 'sinon' -import TypedMessageManager from '../../../app/scripts/lib/typed-message-manager' -import { TRANSACTION_STATUSES } from '../../../shared/constants/transaction' +import assert from 'assert'; +import sinon from 'sinon'; +import TypedMessageManager from '../../../app/scripts/lib/typed-message-manager'; +import { TRANSACTION_STATUSES } from '../../../shared/constants/transaction'; describe('Typed Message Manager', function () { let typedMessageManager, @@ -10,14 +10,14 @@ describe('Typed Message Manager', function () { typedMsgs, messages, msgId, - numberMsgId + numberMsgId; - const address = '0xc42edfcc21ed14dda456aa0756c153f7985d8813' + const address = '0xc42edfcc21ed14dda456aa0756c153f7985d8813'; beforeEach(async function () { typedMessageManager = new TypedMessageManager({ getCurrentChainId: sinon.fake.returns('0x1'), - }) + }); msgParamsV1 = { from: address, @@ -29,7 +29,7 @@ describe('Typed Message Manager', function () { value: '$$$', }, ], - } + }; msgParamsV3 = { from: address, @@ -70,54 +70,57 @@ describe('Typed Message Manager', function () { contents: 'Hello, Bob!', }, }), - } + }; - await typedMessageManager.addUnapprovedMessage(msgParamsV3, null, 'V3') - typedMsgs = typedMessageManager.getUnapprovedMsgs() - messages = typedMessageManager.messages - msgId = Object.keys(typedMsgs)[0] - messages[0].msgParams.metamaskId = parseInt(msgId, 10) - numberMsgId = parseInt(msgId, 10) - }) + await typedMessageManager.addUnapprovedMessage(msgParamsV3, null, 'V3'); + typedMsgs = typedMessageManager.getUnapprovedMsgs(); + messages = typedMessageManager.messages; + msgId = Object.keys(typedMsgs)[0]; + messages[0].msgParams.metamaskId = parseInt(msgId, 10); + numberMsgId = parseInt(msgId, 10); + }); it('supports version 1 of signedTypedData', function () { - typedMessageManager.addUnapprovedMessage(msgParamsV1, null, 'V1') - assert.equal(messages[messages.length - 1].msgParams.data, msgParamsV1.data) - }) + typedMessageManager.addUnapprovedMessage(msgParamsV1, null, 'V1'); + assert.equal( + messages[messages.length - 1].msgParams.data, + msgParamsV1.data, + ); + }); it('has params address', function () { - assert.equal(typedMsgs[msgId].msgParams.from, address) - }) + assert.equal(typedMsgs[msgId].msgParams.from, address); + }); it('adds to unapproved messages and sets status to unapproved', function () { - assert.equal(typedMsgs[msgId].status, TRANSACTION_STATUSES.UNAPPROVED) - }) + assert.equal(typedMsgs[msgId].status, TRANSACTION_STATUSES.UNAPPROVED); + }); it('validates params', function () { assert.doesNotThrow(() => { - typedMessageManager.validateParams(messages[0].msgParams) - }, 'Does not throw with valid parameters') - }) + typedMessageManager.validateParams(messages[0].msgParams); + }, 'Does not throw with valid parameters'); + }); it('gets unapproved by id', function () { - const getMsg = typedMessageManager.getMsg(numberMsgId) - assert.equal(getMsg.id, numberMsgId) - }) + const getMsg = typedMessageManager.getMsg(numberMsgId); + assert.equal(getMsg.id, numberMsgId); + }); it('approves messages', async function () { - const messageMetaMaskId = messages[0].msgParams - typedMessageManager.approveMessage(messageMetaMaskId) - assert.equal(messages[0].status, TRANSACTION_STATUSES.APPROVED) - }) + const messageMetaMaskId = messages[0].msgParams; + typedMessageManager.approveMessage(messageMetaMaskId); + assert.equal(messages[0].status, TRANSACTION_STATUSES.APPROVED); + }); it('sets msg status to signed and adds a raw sig to message details', function () { - typedMessageManager.setMsgStatusSigned(numberMsgId, 'raw sig') - assert.equal(messages[0].status, TRANSACTION_STATUSES.SIGNED) - assert.equal(messages[0].rawSig, 'raw sig') - }) + typedMessageManager.setMsgStatusSigned(numberMsgId, 'raw sig'); + assert.equal(messages[0].status, TRANSACTION_STATUSES.SIGNED); + assert.equal(messages[0].rawSig, 'raw sig'); + }); it('rejects message', function () { - typedMessageManager.rejectMsg(numberMsgId) - assert.equal(messages[0].status, TRANSACTION_STATUSES.REJECTED) - }) -}) + typedMessageManager.rejectMsg(numberMsgId); + assert.equal(messages[0].status, TRANSACTION_STATUSES.REJECTED); + }); +}); diff --git a/test/unit/app/util-test.js b/test/unit/app/util-test.js index ca58f1118..a6d2783f1 100644 --- a/test/unit/app/util-test.js +++ b/test/unit/app/util-test.js @@ -1,75 +1,75 @@ -import { strict as assert } from 'assert' +import { strict as assert } from 'assert'; import { getEnvironmentType, sufficientBalance, -} from '../../../app/scripts/lib/util' -import { isPrefixedFormattedHexString } from '../../../shared/modules/utils' +} from '../../../app/scripts/lib/util'; +import { isPrefixedFormattedHexString } from '../../../shared/modules/utils'; import { ENVIRONMENT_TYPE_POPUP, ENVIRONMENT_TYPE_NOTIFICATION, ENVIRONMENT_TYPE_FULLSCREEN, ENVIRONMENT_TYPE_BACKGROUND, -} from '../../../shared/constants/app' +} from '../../../shared/constants/app'; describe('app utils', function () { describe('getEnvironmentType', function () { it('should return popup type', function () { const environmentType = getEnvironmentType( 'http://extension-id/popup.html', - ) - assert.equal(environmentType, ENVIRONMENT_TYPE_POPUP) - }) + ); + assert.equal(environmentType, ENVIRONMENT_TYPE_POPUP); + }); it('should return notification type', function () { const environmentType = getEnvironmentType( 'http://extension-id/notification.html', - ) - assert.equal(environmentType, ENVIRONMENT_TYPE_NOTIFICATION) - }) + ); + assert.equal(environmentType, ENVIRONMENT_TYPE_NOTIFICATION); + }); it('should return fullscreen type for home.html', function () { const environmentType = getEnvironmentType( 'http://extension-id/home.html', - ) - assert.equal(environmentType, ENVIRONMENT_TYPE_FULLSCREEN) - }) + ); + assert.equal(environmentType, ENVIRONMENT_TYPE_FULLSCREEN); + }); it('should return fullscreen type for phishing.html', function () { const environmentType = getEnvironmentType( 'http://extension-id/phishing.html', - ) - assert.equal(environmentType, ENVIRONMENT_TYPE_FULLSCREEN) - }) + ); + assert.equal(environmentType, ENVIRONMENT_TYPE_FULLSCREEN); + }); it('should return background type', function () { const environmentType = getEnvironmentType( 'http://extension-id/_generated_background_page.html', - ) - assert.equal(environmentType, ENVIRONMENT_TYPE_BACKGROUND) - }) + ); + assert.equal(environmentType, ENVIRONMENT_TYPE_BACKGROUND); + }); it('should return the correct type for a URL with a hash fragment', function () { const environmentType = getEnvironmentType( 'http://extension-id/popup.html#hash', - ) - assert.equal(environmentType, ENVIRONMENT_TYPE_POPUP) - }) + ); + assert.equal(environmentType, ENVIRONMENT_TYPE_POPUP); + }); it('should return the correct type for a URL with query parameters', function () { const environmentType = getEnvironmentType( 'http://extension-id/popup.html?param=foo', - ) - assert.equal(environmentType, ENVIRONMENT_TYPE_POPUP) - }) + ); + assert.equal(environmentType, ENVIRONMENT_TYPE_POPUP); + }); it('should return the correct type for a URL with query parameters and a hash fragment', function () { const environmentType = getEnvironmentType( 'http://extension-id/popup.html?param=foo#hash', - ) - assert.equal(environmentType, ENVIRONMENT_TYPE_POPUP) - }) - }) + ); + assert.equal(environmentType, ENVIRONMENT_TYPE_POPUP); + }); + }); describe('SufficientBalance', function () { it('returns true if max tx cost is equal to balance.', function () { @@ -77,37 +77,37 @@ describe('app utils', function () { value: '0x1', gas: '0x2', gasPrice: '0x3', - } - const balance = '0x8' + }; + const balance = '0x8'; - const result = sufficientBalance(tx, balance) - assert.ok(result, 'sufficient balance found.') - }) + const result = sufficientBalance(tx, balance); + assert.ok(result, 'sufficient balance found.'); + }); it('returns true if max tx cost is less than balance.', function () { const tx = { value: '0x1', gas: '0x2', gasPrice: '0x3', - } - const balance = '0x9' + }; + const balance = '0x9'; - const result = sufficientBalance(tx, balance) - assert.ok(result, 'sufficient balance found.') - }) + const result = sufficientBalance(tx, balance); + assert.ok(result, 'sufficient balance found.'); + }); it('returns false if max tx cost is more than balance.', function () { const tx = { value: '0x1', gas: '0x2', gasPrice: '0x3', - } - const balance = '0x6' + }; + const balance = '0x6'; - const result = sufficientBalance(tx, balance) - assert.ok(!result, 'insufficient balance found.') - }) - }) + const result = sufficientBalance(tx, balance); + assert.ok(!result, 'insufficient balance found.'); + }); + }); describe('isPrefixedFormattedHexString', function () { it('should return true for valid hex strings', function () { @@ -115,77 +115,81 @@ describe('app utils', function () { isPrefixedFormattedHexString('0x1'), true, 'should return true', - ) + ); assert.equal( isPrefixedFormattedHexString('0xa'), true, 'should return true', - ) + ); assert.equal( isPrefixedFormattedHexString('0xabcd1123fae909aad87452'), true, 'should return true', - ) - }) + ); + }); it('should return false for invalid hex strings', function () { assert.equal( isPrefixedFormattedHexString('0x'), false, 'should return false', - ) + ); assert.equal( isPrefixedFormattedHexString('0x0'), false, 'should return false', - ) + ); assert.equal( isPrefixedFormattedHexString('0x01'), false, 'should return false', - ) + ); assert.equal( isPrefixedFormattedHexString(' 0x1'), false, 'should return false', - ) + ); assert.equal( isPrefixedFormattedHexString('0x1 '), false, 'should return false', - ) + ); assert.equal( isPrefixedFormattedHexString('0x1afz'), false, 'should return false', - ) + ); assert.equal( isPrefixedFormattedHexString('z'), false, 'should return false', - ) + ); assert.equal( isPrefixedFormattedHexString(2), false, 'should return false', - ) + ); assert.equal( isPrefixedFormattedHexString(['0x1']), false, 'should return false', - ) + ); - assert.equal(isPrefixedFormattedHexString(), false, 'should return false') - }) - }) -}) + assert.equal( + isPrefixedFormattedHexString(), + false, + 'should return false', + ); + }); + }); +}); diff --git a/test/unit/balance-formatter-test.js b/test/unit/balance-formatter-test.js index 74df60faa..cd63ee68f 100644 --- a/test/unit/balance-formatter-test.js +++ b/test/unit/balance-formatter-test.js @@ -1,27 +1,27 @@ -import assert from 'assert' -import currencyFormatter from 'currency-formatter' -import availableCurrencies from '../../ui/app/helpers/constants/available-conversions.json' +import assert from 'assert'; +import currencyFormatter from 'currency-formatter'; +import availableCurrencies from '../../ui/app/helpers/constants/available-conversions.json'; describe('currencyFormatting', function () { it('be able to format any infura currency', function (done) { - const number = 10000 + const number = 10000; availableCurrencies.forEach((conversion) => { - const code = conversion.code.toUpperCase() - const result = currencyFormatter.format(number, { code }) + const code = conversion.code.toUpperCase(); + const result = currencyFormatter.format(number, { code }); switch (code) { case 'USD': - assert.equal(result, '$10,000.00') - break + assert.equal(result, '$10,000.00'); + break; case 'JPY': - assert.equal(result, '¥10,000') - break + assert.equal(result, '¥10,000'); + break; default: - assert.ok(result, `Currency ${code} formatted as ${result}`) + assert.ok(result, `Currency ${code} formatted as ${result}`); } - }) + }); - done() - }) -}) + done(); + }); +}); diff --git a/test/unit/lib/account-link.test.js b/test/unit/lib/account-link.test.js index 8ba9404e4..a8a25ee31 100644 --- a/test/unit/lib/account-link.test.js +++ b/test/unit/lib/account-link.test.js @@ -1,5 +1,5 @@ -import assert from 'assert' -import getAccountLink from '../../../ui/lib/account-link' +import assert from 'assert'; +import getAccountLink from '../../../ui/lib/account-link'; describe('Account link', function () { describe('getAccountLink', function () { @@ -34,11 +34,11 @@ describe('Account link', function () { blockExplorerUrl: 'https://another.block.explorer/', }, }, - ] + ]; tests.forEach(({ expected, address, network, rpcPrefs }) => { - assert.equal(getAccountLink(address, network, rpcPrefs), expected) - }) - }) - }) -}) + assert.equal(getAccountLink(address, network, rpcPrefs), expected); + }); + }); + }); +}); diff --git a/test/unit/localhostState.js b/test/unit/localhostState.js index 069ac0b78..b758b9120 100644 --- a/test/unit/localhostState.js +++ b/test/unit/localhostState.js @@ -1,4 +1,4 @@ -import { NETWORK_TYPE_RPC } from '../../shared/constants/network' +import { NETWORK_TYPE_RPC } from '../../shared/constants/network'; /** * @typedef {Object} FirstTimeState @@ -18,6 +18,6 @@ const initialState = { chainId: '0x539', }, }, -} +}; -export default initialState +export default initialState; diff --git a/test/unit/migrations/021-test.js b/test/unit/migrations/021-test.js index 028e0e99d..d17615713 100644 --- a/test/unit/migrations/021-test.js +++ b/test/unit/migrations/021-test.js @@ -1,17 +1,17 @@ -import assert from 'assert' -import wallet2 from '../../lib/migrations/002.json' -import migration21 from '../../../app/scripts/migrations/021' +import assert from 'assert'; +import wallet2 from '../../lib/migrations/002.json'; +import migration21 from '../../../app/scripts/migrations/021'; describe('wallet2 is migrated successfully with out the BlacklistController', function () { it('should delete BlacklistController key', function (done) { migration21 .migrate(wallet2) .then((migratedData) => { - assert.equal(migratedData.meta.version, 21) - assert(!migratedData.data.BlacklistController) - assert(!migratedData.data.RecentBlocks) - done() + assert.equal(migratedData.meta.version, 21); + assert(!migratedData.data.BlacklistController); + assert(!migratedData.data.RecentBlocks); + done(); }) - .catch(done) - }) -}) + .catch(done); + }); +}); diff --git a/test/unit/migrations/022-test.js b/test/unit/migrations/022-test.js index 347edf99a..537a2ba41 100644 --- a/test/unit/migrations/022-test.js +++ b/test/unit/migrations/022-test.js @@ -1,8 +1,8 @@ -import assert from 'assert' -import migration22 from '../../../app/scripts/migrations/022' -import { TRANSACTION_STATUSES } from '../../../shared/constants/transaction' +import assert from 'assert'; +import migration22 from '../../../app/scripts/migrations/022'; +import { TRANSACTION_STATUSES } from '../../../shared/constants/transaction'; -const properTime = new Date().getTime() +const properTime = new Date().getTime(); const storage = { meta: {}, data: { @@ -14,7 +14,7 @@ const storage = { ], }, }, -} +}; describe('storage is migrated successfully where transactions that are submitted have submittedTimes', function () { it('should add submittedTime key on the txMeta if appropriate', function (done) { @@ -25,16 +25,16 @@ describe('storage is migrated successfully where transactions that are submitted txMeta1, txMeta2, txMeta3, - ] = migratedData.data.TransactionController.transactions - assert.equal(migratedData.meta.version, 22) + ] = migratedData.data.TransactionController.transactions; + assert.equal(migratedData.meta.version, 22); // should have written a submitted time - assert(txMeta1.submittedTime) + assert(txMeta1.submittedTime); // should not have written a submitted time because it already has one - assert.equal(txMeta2.submittedTime, properTime) + assert.equal(txMeta2.submittedTime, properTime); // should not have written a submitted time - assert(!txMeta3.submittedTime) - done() + assert(!txMeta3.submittedTime); + done(); }) - .catch(done) - }) -}) + .catch(done); + }); +}); diff --git a/test/unit/migrations/023-test.js b/test/unit/migrations/023-test.js index a0cc09f30..d1eb7109b 100644 --- a/test/unit/migrations/023-test.js +++ b/test/unit/migrations/023-test.js @@ -1,6 +1,6 @@ -import assert from 'assert' -import migration23 from '../../../app/scripts/migrations/023' -import { TRANSACTION_STATUSES } from '../../../shared/constants/transaction' +import assert from 'assert'; +import migration23 from '../../../app/scripts/migrations/023'; +import { TRANSACTION_STATUSES } from '../../../shared/constants/transaction'; const storage = { meta: {}, @@ -9,107 +9,110 @@ const storage = { transactions: [], }, }, -} +}; -const transactions = [] -const transactions40 = [] -const transactions20 = [] +const transactions = []; +const transactions40 = []; +const transactions20 = []; -const txStates = Object.values(TRANSACTION_STATUSES) +const txStates = Object.values(TRANSACTION_STATUSES); const deletableTxStates = [ TRANSACTION_STATUSES.CONFIRMED, TRANSACTION_STATUSES.REJECTED, TRANSACTION_STATUSES.FAILED, TRANSACTION_STATUSES.DROPPED, -] +]; -let nonDeletableCount = 0 +let nonDeletableCount = 0; -let status +let status; while (transactions.length <= 100) { - status = txStates[Math.floor(Math.random() * Math.floor(txStates.length - 1))] + status = + txStates[Math.floor(Math.random() * Math.floor(txStates.length - 1))]; // This is an old migration, let's allow it // eslint-disable-next-line no-loop-func if (!deletableTxStates.find((s) => s === status)) { - nonDeletableCount += 1 + nonDeletableCount += 1; } - transactions.push({ status }) + transactions.push({ status }); } while (transactions40.length < 40) { - status = txStates[Math.floor(Math.random() * Math.floor(txStates.length - 1))] - transactions40.push({ status }) + status = + txStates[Math.floor(Math.random() * Math.floor(txStates.length - 1))]; + transactions40.push({ status }); } while (transactions20.length < 20) { - status = txStates[Math.floor(Math.random() * Math.floor(txStates.length - 1))] - transactions20.push({ status }) + status = + txStates[Math.floor(Math.random() * Math.floor(txStates.length - 1))]; + transactions20.push({ status }); } -storage.data.TransactionController.transactions = transactions +storage.data.TransactionController.transactions = transactions; describe('storage is migrated successfully and the proper transactions are remove from state', function () { it('should remove transactions that are unneeded', function (done) { migration23 .migrate(storage) .then((migratedData) => { - let leftoverNonDeletableTxCount = 0 + let leftoverNonDeletableTxCount = 0; const migratedTransactions = - migratedData.data.TransactionController.transactions + migratedData.data.TransactionController.transactions; migratedTransactions.forEach((tx) => { if (!deletableTxStates.find((s) => s === tx.status)) { - leftoverNonDeletableTxCount += 1 + leftoverNonDeletableTxCount += 1; } - }) + }); assert.equal( leftoverNonDeletableTxCount, nonDeletableCount, "migration shouldn't delete transactions we want to keep", - ) + ); assert( migratedTransactions.length >= 40, `should be equal or greater to 40 if they are non deletable states got ${migratedTransactions.length} transactions`, - ) - done() + ); + done(); }) - .catch(done) - }) + .catch(done); + }); it('should not remove any transactions because 40 is the expected limit', function (done) { - storage.meta.version = 22 - storage.data.TransactionController.transactions = transactions40 + storage.meta.version = 22; + storage.data.TransactionController.transactions = transactions40; migration23 .migrate(storage) .then((migratedData) => { const migratedTransactions = - migratedData.data.TransactionController.transactions + migratedData.data.TransactionController.transactions; assert.equal( migratedTransactions.length, 40, "migration shouldn't delete when at limit", - ) - done() + ); + done(); }) - .catch(done) - }) + .catch(done); + }); it('should not remove any transactions because 20 txs is under the expected limit', function (done) { - storage.meta.version = 22 - storage.data.TransactionController.transactions = transactions20 + storage.meta.version = 22; + storage.data.TransactionController.transactions = transactions20; migration23 .migrate(storage) .then((migratedData) => { const migratedTransactions = - migratedData.data.TransactionController.transactions + migratedData.data.TransactionController.transactions; assert.equal( migratedTransactions.length, 20, "migration shouldn't delete when under limit", - ) - done() + ); + done(); }) - .catch(done) - }) -}) + .catch(done); + }); +}); diff --git a/test/unit/migrations/024-test.js b/test/unit/migrations/024-test.js index b753c4d06..a90729c5d 100644 --- a/test/unit/migrations/024-test.js +++ b/test/unit/migrations/024-test.js @@ -1,12 +1,12 @@ -import assert from 'assert' -import migration24 from '../../../app/scripts/migrations/024' -import data from '../../../app/scripts/first-time-state' -import { TRANSACTION_STATUSES } from '../../../shared/constants/transaction' +import assert from 'assert'; +import migration24 from '../../../app/scripts/migrations/024'; +import data from '../../../app/scripts/first-time-state'; +import { TRANSACTION_STATUSES } from '../../../shared/constants/transaction'; const firstTimeState = { meta: {}, data, -} +}; const storage = { meta: {}, data: { @@ -14,22 +14,22 @@ const storage = { transactions: [], }, }, -} +}; -const transactions = [] +const transactions = []; while (transactions.length <= 10) { transactions.push({ txParams: { from: '0x8aCce2391c0d510a6c5E5d8f819a678f79b7e675' }, status: TRANSACTION_STATUSES.UNAPPROVED, - }) + }); transactions.push({ txParams: { from: '0x8aCce2391c0d510a6c5E5d8f819a678f79b7e675' }, status: TRANSACTION_STATUSES.CONFIRMED, - }) + }); } -storage.data.TransactionController.transactions = transactions +storage.data.TransactionController.transactions = transactions; describe('storage is migrated successfully and the txParams.from are lowercase', function () { it('should lowercase the from for unapproved txs', function (done) { @@ -37,32 +37,32 @@ describe('storage is migrated successfully and the txParams.from are lowercase', .migrate(storage) .then((migratedData) => { const migratedTransactions = - migratedData.data.TransactionController.transactions + migratedData.data.TransactionController.transactions; migratedTransactions.forEach((tx) => { if (tx.status === TRANSACTION_STATUSES.UNAPPROVED) { assert.equal( tx.txParams.from, '0x8acce2391c0d510a6c5e5d8f819a678f79b7e675', - ) + ); } else { assert.equal( tx.txParams.from, '0x8aCce2391c0d510a6c5E5d8f819a678f79b7e675', - ) + ); } - }) - done() + }); + done(); }) - .catch(done) - }) + .catch(done); + }); it('should migrate first time state', function (done) { migration24 .migrate(firstTimeState) .then((migratedData) => { - assert.equal(migratedData.meta.version, 24) - done() + assert.equal(migratedData.meta.version, 24); + done(); }) - .catch(done) - }) -}) + .catch(done); + }); +}); diff --git a/test/unit/migrations/025-test.js b/test/unit/migrations/025-test.js index 811cbaef7..f99db5010 100644 --- a/test/unit/migrations/025-test.js +++ b/test/unit/migrations/025-test.js @@ -1,12 +1,12 @@ -import assert from 'assert' -import migration25 from '../../../app/scripts/migrations/025' -import data from '../../../app/scripts/first-time-state' -import { TRANSACTION_STATUSES } from '../../../shared/constants/transaction' +import assert from 'assert'; +import migration25 from '../../../app/scripts/migrations/025'; +import data from '../../../app/scripts/first-time-state'; +import { TRANSACTION_STATUSES } from '../../../shared/constants/transaction'; const firstTimeState = { meta: {}, data, -} +}; const storage = { meta: {}, @@ -15,9 +15,9 @@ const storage = { transactions: [], }, }, -} +}; -const transactions = [] +const transactions = []; while (transactions.length <= 10) { transactions.push({ @@ -27,14 +27,14 @@ while (transactions.length <= 10) { chainId: 2, }, status: TRANSACTION_STATUSES.UNAPPROVED, - }) + }); transactions.push({ txParams: { from: '0x8aCce2391c0d510a6c5E5d8f819a678f79b7e675' }, status: TRANSACTION_STATUSES.CONFIRMED, - }) + }); } -storage.data.TransactionController.transactions = transactions +storage.data.TransactionController.transactions = transactions; describe('storage is migrated successfully and the txParams.from are lowercase', function () { it('should lowercase the from for unapproved txs', function (done) { @@ -42,27 +42,27 @@ describe('storage is migrated successfully and the txParams.from are lowercase', .migrate(storage) .then((migratedData) => { const migratedTransactions = - migratedData.data.TransactionController.transactions + migratedData.data.TransactionController.transactions; migratedTransactions.forEach((tx) => { if (tx.status === TRANSACTION_STATUSES.UNAPPROVED) { - assert(!tx.txParams.random) + assert(!tx.txParams.random); } if (tx.status === TRANSACTION_STATUSES.UNAPPROVED) { - assert(!tx.txParams.chainId) + assert(!tx.txParams.chainId); } - }) - done() + }); + done(); }) - .catch(done) - }) + .catch(done); + }); it('should migrate first time state', function (done) { migration25 .migrate(firstTimeState) .then((migratedData) => { - assert.equal(migratedData.meta.version, 25) - done() + assert.equal(migratedData.meta.version, 25); + done(); }) - .catch(done) - }) -}) + .catch(done); + }); +}); diff --git a/test/unit/migrations/026-test.js b/test/unit/migrations/026-test.js index 9168ea493..684300ba5 100644 --- a/test/unit/migrations/026-test.js +++ b/test/unit/migrations/026-test.js @@ -1,6 +1,6 @@ -import assert from 'assert' -import firstTimeState from '../../../app/scripts/first-time-state' -import migration26 from '../../../app/scripts/migrations/026' +import assert from 'assert'; +import firstTimeState from '../../../app/scripts/first-time-state'; +import migration26 from '../../../app/scripts/migrations/026'; const oldStorage = { meta: { version: 25 }, @@ -13,26 +13,26 @@ const oldStorage = { }, }, }, -} +}; describe('migration #26', function () { it('should move the identities from KeyringController', function (done) { migration26 .migrate(oldStorage) .then((newStorage) => { - const { identities } = newStorage.data.PreferencesController + const { identities } = newStorage.data.PreferencesController; assert.deepEqual(identities, { '0x1e77e2': { name: 'Test Account 1', address: '0x1e77e2' }, '0x7e57e2': { name: 'Test Account 2', address: '0x7e57e2' }, - }) + }); assert.strictEqual( newStorage.data.KeyringController.walletNicknames, undefined, - ) - done() + ); + done(); }) - .catch(done) - }) + .catch(done); + }); it('should successfully migrate first time state', function (done) { migration26 @@ -41,9 +41,9 @@ describe('migration #26', function () { data: firstTimeState, }) .then((migratedData) => { - assert.equal(migratedData.meta.version, migration26.version) - done() + assert.equal(migratedData.meta.version, migration26.version); + done(); }) - .catch(done) - }) -}) + .catch(done); + }); +}); diff --git a/test/unit/migrations/027-test.js b/test/unit/migrations/027-test.js index 18a19107a..c6d2ada97 100644 --- a/test/unit/migrations/027-test.js +++ b/test/unit/migrations/027-test.js @@ -1,7 +1,7 @@ -import assert from 'assert' -import firstTimeState from '../../../app/scripts/first-time-state' -import migration27 from '../../../app/scripts/migrations/027' -import { TRANSACTION_STATUSES } from '../../../shared/constants/transaction' +import assert from 'assert'; +import firstTimeState from '../../../app/scripts/first-time-state'; +import migration27 from '../../../app/scripts/migrations/027'; +import { TRANSACTION_STATUSES } from '../../../shared/constants/transaction'; const oldStorage = { meta: {}, @@ -10,17 +10,17 @@ const oldStorage = { transactions: [], }, }, -} +}; -const transactions = [] +const transactions = []; while (transactions.length < 9) { - transactions.push({ status: TRANSACTION_STATUSES.REJECTED }) - transactions.push({ status: TRANSACTION_STATUSES.UNAPPROVED }) - transactions.push({ status: TRANSACTION_STATUSES.APPROVED }) + transactions.push({ status: TRANSACTION_STATUSES.REJECTED }); + transactions.push({ status: TRANSACTION_STATUSES.UNAPPROVED }); + transactions.push({ status: TRANSACTION_STATUSES.APPROVED }); } -oldStorage.data.TransactionController.transactions = transactions +oldStorage.data.TransactionController.transactions = transactions; describe('migration #27', function () { it('should remove rejected transactions', function (done) { @@ -28,21 +28,21 @@ describe('migration #27', function () { .migrate(oldStorage) .then((newStorage) => { const newTransactions = - newStorage.data.TransactionController.transactions + newStorage.data.TransactionController.transactions; assert.equal( newTransactions.length, 6, 'transactions is expected to have the length of 6', - ) + ); newTransactions.forEach((txMeta) => { if (txMeta.status === TRANSACTION_STATUSES.REJECTED) { - done(new Error('transaction was found with a status of rejected')) + done(new Error('transaction was found with a status of rejected')); } - }) - done() + }); + done(); }) - .catch(done) - }) + .catch(done); + }); it('should successfully migrate first time state', function (done) { migration27 @@ -51,9 +51,9 @@ describe('migration #27', function () { data: firstTimeState, }) .then((migratedData) => { - assert.equal(migratedData.meta.version, migration27.version) - done() + assert.equal(migratedData.meta.version, migration27.version); + done(); }) - .catch(done) - }) -}) + .catch(done); + }); +}); diff --git a/test/unit/migrations/028-test.js b/test/unit/migrations/028-test.js index caa8c86bf..d7483d116 100644 --- a/test/unit/migrations/028-test.js +++ b/test/unit/migrations/028-test.js @@ -1,6 +1,6 @@ -import assert from 'assert' -import firstTimeState from '../../../app/scripts/first-time-state' -import migration28 from '../../../app/scripts/migrations/028' +import assert from 'assert'; +import firstTimeState from '../../../app/scripts/first-time-state'; +import migration28 from '../../../app/scripts/migrations/028'; const oldStorage = { meta: {}, @@ -16,55 +16,55 @@ const oldStorage = { }, }, }, -} +}; describe('migration #28', function () { it('should add corresponding tokens to accountTokens', function (done) { migration28 .migrate(oldStorage) .then((newStorage) => { - const newTokens = newStorage.data.PreferencesController.tokens + const newTokens = newStorage.data.PreferencesController.tokens; const newAccountTokens = - newStorage.data.PreferencesController.accountTokens + newStorage.data.PreferencesController.accountTokens; const testTokens = [ { address: '0xa', symbol: 'A', decimals: 4 }, { address: '0xb', symbol: 'B', decimals: 4 }, - ] + ]; assert.equal( newTokens.length, 0, 'tokens is expected to have the length of 0', - ) + ); assert.equal( newAccountTokens['0x6d14'].mainnet.length, 2, 'tokens for address is expected to have the length of 2', - ) + ); assert.equal( newAccountTokens['0x3695'].mainnet.length, 2, 'tokens for address is expected to have the length of 2', - ) + ); assert.equal( Object.keys(newAccountTokens).length, 2, 'account tokens should be created for all identities', - ) + ); assert.deepEqual( newAccountTokens['0x6d14'].mainnet, testTokens, 'tokens for address should be the same than before', - ) + ); assert.deepEqual( newAccountTokens['0x3695'].mainnet, testTokens, 'tokens for address should be the same than before', - ) - done() + ); + done(); }) - .catch(done) - }) + .catch(done); + }); it('should successfully migrate first time state', function (done) { migration28 @@ -73,9 +73,9 @@ describe('migration #28', function () { data: firstTimeState, }) .then((migratedData) => { - assert.equal(migratedData.meta.version, migration28.version) - done() + assert.equal(migratedData.meta.version, migration28.version); + done(); }) - .catch(done) - }) -}) + .catch(done); + }); +}); diff --git a/test/unit/migrations/029-test.js b/test/unit/migrations/029-test.js index 4e37a48f4..2eb97c128 100644 --- a/test/unit/migrations/029-test.js +++ b/test/unit/migrations/029-test.js @@ -1,8 +1,8 @@ -import assert from 'assert' -import migration29 from '../../../app/scripts/migrations/029' -import { TRANSACTION_STATUSES } from '../../../shared/constants/transaction' +import assert from 'assert'; +import migration29 from '../../../app/scripts/migrations/029'; +import { TRANSACTION_STATUSES } from '../../../shared/constants/transaction'; -const properTime = new Date().getTime() +const properTime = new Date().getTime(); const storage = { meta: {}, data: { @@ -28,40 +28,40 @@ const storage = { ], }, }, -} +}; describe('storage is migrated successfully where transactions that are submitted have submittedTimes', function () { it('should auto fail transactions more than 12 hours old', function (done) { migration29 .migrate(storage) .then((migratedData) => { - const txs = migratedData.data.TransactionController.transactions - const [txMeta1] = txs - assert.equal(migratedData.meta.version, 29) + const txs = migratedData.data.TransactionController.transactions; + const [txMeta1] = txs; + assert.equal(migratedData.meta.version, 29); assert.equal( txMeta1.status, TRANSACTION_STATUSES.FAILED, 'old tx is auto failed', - ) + ); assert( txMeta1.err.message.includes('too long'), 'error message assigned', - ) + ); txs.forEach((tx) => { if (tx.id === 1) { - return + return; } assert.notEqual( tx.status, TRANSACTION_STATUSES.FAILED, 'other tx is not auto failed', - ) - }) + ); + }); - done() + done(); }) - .catch(done) - }) -}) + .catch(done); + }); +}); diff --git a/test/unit/migrations/030-test.js b/test/unit/migrations/030-test.js index 24acbfba2..3610a72b0 100644 --- a/test/unit/migrations/030-test.js +++ b/test/unit/migrations/030-test.js @@ -1,5 +1,5 @@ -import assert from 'assert' -import migrationTemplate from '../../../app/scripts/migrations/030' +import assert from 'assert'; +import migrationTemplate from '../../../app/scripts/migrations/030'; const storage = { meta: {}, @@ -31,31 +31,31 @@ const storage = { ], }, }, -} +}; describe('storage is migrated successfully', function () { it('should work', function (done) { migrationTemplate .migrate(storage) .then((migratedData) => { - assert.equal(migratedData.meta.version, 30) + assert.equal(migratedData.meta.version, 30); assert.equal( migratedData.data.PreferencesController.frequentRpcListDetail[0] .chainId, undefined, - ) + ); assert.equal( migratedData.data.PreferencesController.frequentRpcListDetail[1] .chainId, '1', - ) + ); assert.equal( migratedData.data.NetworkController.provider.chainId, undefined, - ) - assert.equal(migratedData.data.NetworkController.network, undefined) - done() + ); + assert.equal(migratedData.data.NetworkController.network, undefined); + done(); }) - .catch(done) - }) -}) + .catch(done); + }); +}); diff --git a/test/unit/migrations/031-test.js b/test/unit/migrations/031-test.js index 2110fc373..57159176b 100644 --- a/test/unit/migrations/031-test.js +++ b/test/unit/migrations/031-test.js @@ -1,5 +1,5 @@ -import assert from 'assert' -import migration31 from '../../../app/scripts/migrations/031' +import assert from 'assert'; +import migration31 from '../../../app/scripts/migrations/031'; describe('migration #31', function () { it('should set completedOnboarding to true if vault exists', function (done) { @@ -24,7 +24,7 @@ describe('migration #31', function () { }, }, }, - } + }; migration31 .migrate(oldStorage) @@ -32,11 +32,11 @@ describe('migration #31', function () { assert.equal( newStorage.data.PreferencesController.completedOnboarding, true, - ) - done() + ); + done(); }) - .catch(done) - }) + .catch(done); + }); it('should set completedOnboarding to false if vault does not exist', function (done) { const oldStorage = { @@ -54,7 +54,7 @@ describe('migration #31', function () { }, KeyringController: {}, }, - } + }; migration31 .migrate(oldStorage) @@ -62,9 +62,9 @@ describe('migration #31', function () { assert.equal( newStorage.data.PreferencesController.completedOnboarding, false, - ) - done() + ); + done(); }) - .catch(done) - }) -}) + .catch(done); + }); +}); diff --git a/test/unit/migrations/033-test.js b/test/unit/migrations/033-test.js index b09846f0f..ca8018460 100644 --- a/test/unit/migrations/033-test.js +++ b/test/unit/migrations/033-test.js @@ -1,5 +1,5 @@ -import assert from 'assert' -import migration33 from '../../../app/scripts/migrations/033' +import assert from 'assert'; +import migration33 from '../../../app/scripts/migrations/033'; describe('Migration to delete notice controller', function () { const oldStorage = { @@ -29,11 +29,11 @@ describe('Migration to delete notice controller', function () { ], }, }, - } + }; it('removes notice controller from state', function () { migration33.migrate(oldStorage).then((newStorage) => { - assert.equal(newStorage.data.NoticeController, undefined) - }) - }) -}) + assert.equal(newStorage.data.NoticeController, undefined); + }); + }); +}); diff --git a/test/unit/migrations/034-test.js b/test/unit/migrations/034-test.js index 74de274cf..e9554793d 100644 --- a/test/unit/migrations/034-test.js +++ b/test/unit/migrations/034-test.js @@ -1,5 +1,5 @@ -import assert from 'assert' -import migration34 from '../../../app/scripts/migrations/034' +import assert from 'assert'; +import migration34 from '../../../app/scripts/migrations/034'; describe('migration #34', function () { it('should update the version metadata', function (done) { @@ -8,18 +8,18 @@ describe('migration #34', function () { version: 33, }, data: {}, - } + }; migration34 .migrate(oldStorage) .then((newStorage) => { assert.deepEqual(newStorage.meta, { version: 34, - }) - done() + }); + done(); }) - .catch(done) - }) + .catch(done); + }); it('should set migratedPrivacyMode & privacyMode if featureFlags.privacyMode was false', function (done) { const oldStorage = { @@ -31,7 +31,7 @@ describe('migration #34', function () { }, }, }, - } + }; migration34 .migrate(oldStorage) @@ -41,11 +41,11 @@ describe('migration #34', function () { featureFlags: { privacyMode: true, }, - }) - done() + }); + done(); }) - .catch(done) - }) + .catch(done); + }); it('should NOT change any state if migratedPrivacyMode is already set to true', function (done) { const oldStorage = { @@ -58,16 +58,16 @@ describe('migration #34', function () { }, }, }, - } + }; migration34 .migrate(oldStorage) .then((newStorage) => { - assert.deepEqual(newStorage.data, oldStorage.data) - done() + assert.deepEqual(newStorage.data, oldStorage.data); + done(); }) - .catch(done) - }) + .catch(done); + }); it('should NOT change any state if migratedPrivacyMode is already set to false', function (done) { const oldStorage = { @@ -80,31 +80,31 @@ describe('migration #34', function () { }, }, }, - } + }; migration34 .migrate(oldStorage) .then((newStorage) => { - assert.deepEqual(newStorage.data, oldStorage.data) - done() + assert.deepEqual(newStorage.data, oldStorage.data); + done(); }) - .catch(done) - }) + .catch(done); + }); it('should NOT change any state if PreferencesController is missing', function (done) { const oldStorage = { meta: {}, data: {}, - } + }; migration34 .migrate(oldStorage) .then((newStorage) => { - assert.deepEqual(newStorage.data, oldStorage.data) - done() + assert.deepEqual(newStorage.data, oldStorage.data); + done(); }) - .catch(done) - }) + .catch(done); + }); it('should NOT change any state if featureFlags.privacyMode is already true', function (done) { const oldStorage = { @@ -116,14 +116,14 @@ describe('migration #34', function () { }, }, }, - } + }; migration34 .migrate(oldStorage) .then((newStorage) => { - assert.deepEqual(newStorage.data, oldStorage.data) - done() + assert.deepEqual(newStorage.data, oldStorage.data); + done(); }) - .catch(done) - }) -}) + .catch(done); + }); +}); diff --git a/test/unit/migrations/035-test.js b/test/unit/migrations/035-test.js index 263b2e2df..f3e600df2 100644 --- a/test/unit/migrations/035-test.js +++ b/test/unit/migrations/035-test.js @@ -1,5 +1,5 @@ -import assert from 'assert' -import migration35 from '../../../app/scripts/migrations/035' +import assert from 'assert'; +import migration35 from '../../../app/scripts/migrations/035'; describe('migration #35', function () { it('should update the version metadata', function (done) { @@ -8,18 +8,18 @@ describe('migration #35', function () { version: 34, }, data: {}, - } + }; migration35 .migrate(oldStorage) .then((newStorage) => { assert.deepEqual(newStorage.meta, { version: 35, - }) - done() + }); + done(); }) - .catch(done) - }) + .catch(done); + }); it('should delete seedWords', function (done) { const oldStorage = { @@ -29,16 +29,16 @@ describe('migration #35', function () { seedWords: 'seed words', }, }, - } + }; migration35 .migrate(oldStorage) .then((newStorage) => { - assert.deepEqual(newStorage.data.PreferencesController, {}) - done() + assert.deepEqual(newStorage.data.PreferencesController, {}); + done(); }) - .catch(done) - }) + .catch(done); + }); it('should delete falsy seedWords', function (done) { const oldStorage = { @@ -48,16 +48,16 @@ describe('migration #35', function () { seedWords: '', }, }, - } + }; migration35 .migrate(oldStorage) .then((newStorage) => { - assert.deepEqual(newStorage.data.PreferencesController, {}) - done() + assert.deepEqual(newStorage.data.PreferencesController, {}); + done(); }) - .catch(done) - }) + .catch(done); + }); it('should leave state without seedWords unchanged', function (done) { const oldStorage = { @@ -86,14 +86,14 @@ describe('migration #35', function () { metaMetricsSendCount: 0, }, }, - } + }; migration35 .migrate(oldStorage) .then((newStorage) => { - assert.deepEqual(newStorage.data, oldStorage.data) - done() + assert.deepEqual(newStorage.data, oldStorage.data); + done(); }) - .catch(done) - }) -}) + .catch(done); + }); +}); diff --git a/test/unit/migrations/036-test.js b/test/unit/migrations/036-test.js index 380de627b..679fc8a3b 100644 --- a/test/unit/migrations/036-test.js +++ b/test/unit/migrations/036-test.js @@ -1,5 +1,5 @@ -import assert from 'assert' -import migration36 from '../../../app/scripts/migrations/036' +import assert from 'assert'; +import migration36 from '../../../app/scripts/migrations/036'; describe('migration #36', function () { it('should update the version metadata', function (done) { @@ -8,18 +8,18 @@ describe('migration #36', function () { version: 35, }, data: {}, - } + }; migration36 .migrate(oldStorage) .then((newStorage) => { assert.deepEqual(newStorage.meta, { version: 36, - }) - done() + }); + done(); }) - .catch(done) - }) + .catch(done); + }); it('should remove privacyMode if featureFlags.privacyMode was false', function (done) { const oldStorage = { @@ -31,18 +31,18 @@ describe('migration #36', function () { }, }, }, - } + }; migration36 .migrate(oldStorage) .then((newStorage) => { assert.deepEqual(newStorage.data.PreferencesController, { featureFlags: {}, - }) - done() + }); + done(); }) - .catch(done) - }) + .catch(done); + }); it('should remove privacyMode if featureFlags.privacyMode was true', function (done) { const oldStorage = { @@ -54,18 +54,18 @@ describe('migration #36', function () { }, }, }, - } + }; migration36 .migrate(oldStorage) .then((newStorage) => { assert.deepEqual(newStorage.data.PreferencesController, { featureFlags: {}, - }) - done() + }); + done(); }) - .catch(done) - }) + .catch(done); + }); it('should NOT change any state if privacyMode does not exist', function (done) { const oldStorage = { @@ -76,31 +76,31 @@ describe('migration #36', function () { featureFlags: {}, }, }, - } + }; migration36 .migrate(oldStorage) .then((newStorage) => { - assert.deepEqual(newStorage.data, oldStorage.data) - done() + assert.deepEqual(newStorage.data, oldStorage.data); + done(); }) - .catch(done) - }) + .catch(done); + }); it('should NOT change any state if PreferencesController is missing', function (done) { const oldStorage = { meta: {}, data: {}, - } + }; migration36 .migrate(oldStorage) .then((newStorage) => { - assert.deepEqual(newStorage.data, oldStorage.data) - done() + assert.deepEqual(newStorage.data, oldStorage.data); + done(); }) - .catch(done) - }) + .catch(done); + }); it('should NOT change any state if featureFlags is missing', function (done) { const oldStorage = { @@ -108,14 +108,14 @@ describe('migration #36', function () { data: { PreferencesController: {}, }, - } + }; migration36 .migrate(oldStorage) .then((newStorage) => { - assert.deepEqual(newStorage.data, oldStorage.data) - done() + assert.deepEqual(newStorage.data, oldStorage.data); + done(); }) - .catch(done) - }) -}) + .catch(done); + }); +}); diff --git a/test/unit/migrations/037-test.js b/test/unit/migrations/037-test.js index 861ab4cd1..78fe85cb5 100644 --- a/test/unit/migrations/037-test.js +++ b/test/unit/migrations/037-test.js @@ -1,5 +1,5 @@ -import assert from 'assert' -import migration37 from '../../../app/scripts/migrations/037' +import assert from 'assert'; +import migration37 from '../../../app/scripts/migrations/037'; describe('migration #37', function () { it('should update the version metadata', function (done) { @@ -8,18 +8,18 @@ describe('migration #37', function () { version: 36, }, data: {}, - } + }; migration37 .migrate(oldStorage) .then((newStorage) => { assert.deepEqual(newStorage.meta, { version: 37, - }) - done() + }); + done(); }) - .catch(done) - }) + .catch(done); + }); it('should transform old state to new format', function (done) { const oldStorage = { @@ -49,7 +49,7 @@ describe('migration #37', function () { }, }, }, - } + }; migration37 .migrate(oldStorage) @@ -80,11 +80,11 @@ describe('migration #37', function () { name: 'account 2', }, }, - }) - done() + }); + done(); }) - .catch(done) - }) + .catch(done); + }); it('ens validation test', function (done) { const oldStorage = { @@ -101,7 +101,7 @@ describe('migration #37', function () { }, }, }, - } + }; migration37 .migrate(oldStorage) @@ -116,9 +116,9 @@ describe('migration #37', function () { name: 'metamask.eth', }, }, - }) - done() + }); + done(); }) - .catch(done) - }) -}) + .catch(done); + }); +}); diff --git a/test/unit/migrations/038-test.js b/test/unit/migrations/038-test.js index 2c727a352..c1e8e2a1e 100644 --- a/test/unit/migrations/038-test.js +++ b/test/unit/migrations/038-test.js @@ -1,5 +1,5 @@ -import { strict as assert } from 'assert' -import migration38 from '../../../app/scripts/migrations/038' +import { strict as assert } from 'assert'; +import migration38 from '../../../app/scripts/migrations/038'; describe('migration #38', function () { it('should update the version metadata', function (done) { @@ -8,24 +8,24 @@ describe('migration #38', function () { version: 37, }, data: {}, - } + }; migration38 .migrate(oldStorage) .then((newStorage) => { assert.deepEqual(newStorage.meta, { version: 38, - }) - done() + }); + done(); }) - .catch(done) - }) + .catch(done); + }); it('should add a fullScreenVsPopup property set to either "control" or "fullScreen"', function (done) { const oldStorage = { meta: {}, data: {}, - } + }; migration38 .migrate(oldStorage) @@ -33,11 +33,11 @@ describe('migration #38', function () { assert.equal( newStorage.data.ABTestController.abTests.fullScreenVsPopup, 'control', - ) - done() + ); + done(); }) - .catch(done) - }) + .catch(done); + }); it('should leave the fullScreenVsPopup property unchanged if it exists', function (done) { const oldStorage = { @@ -49,7 +49,7 @@ describe('migration #38', function () { }, }, }, - } + }; migration38 .migrate(oldStorage) @@ -58,9 +58,9 @@ describe('migration #38', function () { abTests: { fullScreenVsPopup: 'fullScreen', }, - }) - done() + }); + done(); }) - .catch(done) - }) -}) + .catch(done); + }); +}); diff --git a/test/unit/migrations/039-test.js b/test/unit/migrations/039-test.js index 70b00da5f..8cfc3e0b1 100644 --- a/test/unit/migrations/039-test.js +++ b/test/unit/migrations/039-test.js @@ -1,5 +1,5 @@ -import assert from 'assert' -import migration39 from '../../../app/scripts/migrations/039' +import assert from 'assert'; +import migration39 from '../../../app/scripts/migrations/039'; describe('migration #39', function () { it('should update the version metadata', function (done) { @@ -8,18 +8,18 @@ describe('migration #39', function () { version: 38, }, data: {}, - } + }; migration39 .migrate(oldStorage) .then((newStorage) => { assert.deepEqual(newStorage.meta, { version: 39, - }) - done() + }); + done(); }) - .catch(done) - }) + .catch(done); + }); it('should update old DAI token symbol to SAI in tokens', function (done) { const oldStorage = { @@ -45,7 +45,7 @@ describe('migration #39', function () { ], }, }, - } + }; migration39 .migrate(oldStorage) @@ -68,11 +68,11 @@ describe('migration #39', function () { decimals: 18, }, ], - }) - done() + }); + done(); }) - .catch(done) - }) + .catch(done); + }); it('should update old DAI token symbol to SAI in accountTokens', function (done) { const oldStorage = { @@ -116,7 +116,7 @@ describe('migration #39', function () { }, }, }, - } + }; migration39 .migrate(oldStorage) @@ -157,11 +157,11 @@ describe('migration #39', function () { ], }, }, - }) - done() + }); + done(); }) - .catch(done) - }) + .catch(done); + }); it('should NOT change any state if accountTokens is not an object', function (done) { const oldStorage = { @@ -171,16 +171,16 @@ describe('migration #39', function () { accountTokens: [], }, }, - } + }; migration39 .migrate(oldStorage) .then((newStorage) => { - assert.deepEqual(newStorage.data, oldStorage.data) - done() + assert.deepEqual(newStorage.data, oldStorage.data); + done(); }) - .catch(done) - }) + .catch(done); + }); it('should NOT change any state if accountTokens is an object with invalid values', function (done) { const oldStorage = { @@ -203,16 +203,16 @@ describe('migration #39', function () { }, }, }, - } + }; migration39 .migrate(oldStorage) .then((newStorage) => { - assert.deepEqual(newStorage.data, oldStorage.data) - done() + assert.deepEqual(newStorage.data, oldStorage.data); + done(); }) - .catch(done) - }) + .catch(done); + }); it('should NOT change any state if accountTokens includes the new DAI token', function (done) { const oldStorage = { @@ -256,16 +256,16 @@ describe('migration #39', function () { }, }, }, - } + }; migration39 .migrate(oldStorage) .then((newStorage) => { - assert.deepEqual(newStorage.data, oldStorage.data) - done() + assert.deepEqual(newStorage.data, oldStorage.data); + done(); }) - .catch(done) - }) + .catch(done); + }); it('should NOT change any state if tokens includes the new DAI token', function (done) { const oldStorage = { @@ -286,16 +286,16 @@ describe('migration #39', function () { ], }, }, - } + }; migration39 .migrate(oldStorage) .then((newStorage) => { - assert.deepEqual(newStorage.data, oldStorage.data) - done() + assert.deepEqual(newStorage.data, oldStorage.data); + done(); }) - .catch(done) - }) + .catch(done); + }); it('should NOT change any state if tokens does not include DAI', function (done) { const oldStorage = { @@ -316,16 +316,16 @@ describe('migration #39', function () { ], }, }, - } + }; migration39 .migrate(oldStorage) .then((newStorage) => { - assert.deepEqual(newStorage.data, oldStorage.data) - done() + assert.deepEqual(newStorage.data, oldStorage.data); + done(); }) - .catch(done) - }) + .catch(done); + }); it('should NOT change any state if a tokens property has invalid entries', function (done) { const oldStorage = { @@ -335,16 +335,16 @@ describe('migration #39', function () { tokens: [null, [], undefined, 42], }, }, - } + }; migration39 .migrate(oldStorage) .then((newStorage) => { - assert.deepEqual(newStorage.data, oldStorage.data) - done() + assert.deepEqual(newStorage.data, oldStorage.data); + done(); }) - .catch(done) - }) + .catch(done); + }); it('should NOT change any state if a tokens property is not an array', function (done) { const oldStorage = { @@ -354,16 +354,16 @@ describe('migration #39', function () { tokens: {}, }, }, - } + }; migration39 .migrate(oldStorage) .then((newStorage) => { - assert.deepEqual(newStorage.data, oldStorage.data) - done() + assert.deepEqual(newStorage.data, oldStorage.data); + done(); }) - .catch(done) - }) + .catch(done); + }); it('should NOT change any state if a tokens property is null', function (done) { const oldStorage = { @@ -373,16 +373,16 @@ describe('migration #39', function () { tokens: null, }, }, - } + }; migration39 .migrate(oldStorage) .then((newStorage) => { - assert.deepEqual(newStorage.data, oldStorage.data) - done() + assert.deepEqual(newStorage.data, oldStorage.data); + done(); }) - .catch(done) - }) + .catch(done); + }); it('should NOT change any state if a tokens property is missing', function (done) { const oldStorage = { @@ -390,16 +390,16 @@ describe('migration #39', function () { data: { PreferencesController: {}, }, - } + }; migration39 .migrate(oldStorage) .then((newStorage) => { - assert.deepEqual(newStorage.data, oldStorage.data) - done() + assert.deepEqual(newStorage.data, oldStorage.data); + done(); }) - .catch(done) - }) + .catch(done); + }); it('should NOT change any state if a accountTokens property is missing', function (done) { const oldStorage = { @@ -407,29 +407,29 @@ describe('migration #39', function () { data: { PreferencesController: {}, }, - } + }; migration39 .migrate(oldStorage) .then((newStorage) => { - assert.deepEqual(newStorage.data, oldStorage.data) - done() + assert.deepEqual(newStorage.data, oldStorage.data); + done(); }) - .catch(done) - }) + .catch(done); + }); it('should NOT change any state if PreferencesController is missing', function (done) { const oldStorage = { meta: {}, data: {}, - } + }; migration39 .migrate(oldStorage) .then((newStorage) => { - assert.deepEqual(newStorage.data, oldStorage.data) - done() + assert.deepEqual(newStorage.data, oldStorage.data); + done(); }) - .catch(done) - }) -}) + .catch(done); + }); +}); diff --git a/test/unit/migrations/040-test.js b/test/unit/migrations/040-test.js index fd4f48193..98fce305b 100644 --- a/test/unit/migrations/040-test.js +++ b/test/unit/migrations/040-test.js @@ -1,5 +1,5 @@ -import assert from 'assert' -import migration40 from '../../../app/scripts/migrations/040' +import assert from 'assert'; +import migration40 from '../../../app/scripts/migrations/040'; describe('migration #40', function () { it('should update the version metadata', function (done) { @@ -8,18 +8,18 @@ describe('migration #40', function () { version: 39, }, data: {}, - } + }; migration40 .migrate(oldStorage) .then((newStorage) => { assert.deepEqual(newStorage.meta, { version: 40, - }) - done() + }); + done(); }) - .catch(done) - }) + .catch(done); + }); it('should delete ProviderApprovalController storage key', function (done) { const oldStorage = { @@ -28,29 +28,29 @@ describe('migration #40', function () { ProviderApprovalController: {}, foo: 'bar', }, - } + }; migration40 .migrate(oldStorage) .then((newStorage) => { - assert.deepEqual(newStorage.data, { foo: 'bar' }) - done() + assert.deepEqual(newStorage.data, { foo: 'bar' }); + done(); }) - .catch(done) - }) + .catch(done); + }); it('should do nothing if no ProviderApprovalController storage key', function (done) { const oldStorage = { meta: {}, data: { foo: 'bar' }, - } + }; migration40 .migrate(oldStorage) .then((newStorage) => { - assert.deepEqual(newStorage.data, { foo: 'bar' }) - done() + assert.deepEqual(newStorage.data, { foo: 'bar' }); + done(); }) - .catch(done) - }) -}) + .catch(done); + }); +}); diff --git a/test/unit/migrations/041-test.js b/test/unit/migrations/041-test.js index 7b95dfa3f..e61ce66e2 100644 --- a/test/unit/migrations/041-test.js +++ b/test/unit/migrations/041-test.js @@ -1,5 +1,5 @@ -import assert from 'assert' -import migration41 from '../../../app/scripts/migrations/041' +import assert from 'assert'; +import migration41 from '../../../app/scripts/migrations/041'; describe('migration #41', function () { it('should update the version metadata', function (done) { @@ -8,18 +8,18 @@ describe('migration #41', function () { version: 40, }, data: {}, - } + }; migration41 .migrate(oldStorage) .then((newStorage) => { assert.deepEqual(newStorage.meta, { version: 41, - }) - done() + }); + done(); }) - .catch(done) - }) + .catch(done); + }); it('should rename autoLogoutTimeLimit storage key', function (done) { const oldStorage = { @@ -34,7 +34,7 @@ describe('migration #41', function () { }, foo: 'bar', }, - } + }; migration41 .migrate(oldStorage) @@ -48,11 +48,11 @@ describe('migration #41', function () { bar: 'baz', }, foo: 'bar', - }) - done() + }); + done(); }) - .catch(done) - }) + .catch(done); + }); it('should do nothing if no PreferencesController key', function (done) { const oldStorage = { @@ -60,18 +60,18 @@ describe('migration #41', function () { data: { foo: 'bar', }, - } + }; migration41 .migrate(oldStorage) .then((newStorage) => { assert.deepEqual(newStorage.data, { foo: 'bar', - }) - done() + }); + done(); }) - .catch(done) - }) + .catch(done); + }); it('should do nothing if no preferences key', function (done) { const oldStorage = { @@ -82,7 +82,7 @@ describe('migration #41', function () { }, foo: 'bar', }, - } + }; migration41 .migrate(oldStorage) @@ -92,9 +92,9 @@ describe('migration #41', function () { bar: 'baz', }, foo: 'bar', - }) - done() + }); + done(); }) - .catch(done) - }) -}) + .catch(done); + }); +}); diff --git a/test/unit/migrations/042-test.js b/test/unit/migrations/042-test.js index 0c2cbf01a..9159fb756 100644 --- a/test/unit/migrations/042-test.js +++ b/test/unit/migrations/042-test.js @@ -1,5 +1,5 @@ -import assert from 'assert' -import migration42 from '../../../app/scripts/migrations/042' +import assert from 'assert'; +import migration42 from '../../../app/scripts/migrations/042'; describe('migration #42', function () { it('should update the version metadata', function (done) { @@ -8,18 +8,18 @@ describe('migration #42', function () { version: 41, }, data: {}, - } + }; migration42 .migrate(oldStorage) .then((newStorage) => { assert.deepEqual(newStorage.meta, { version: 42, - }) - done() + }); + done(); }) - .catch(done) - }) + .catch(done); + }); it('should set connectedStatusPopoverHasBeenShown to false', function (done) { const oldStorage = { @@ -31,7 +31,7 @@ describe('migration #42', function () { }, foo: 'bar', }, - } + }; migration42 .migrate(oldStorage) @@ -42,11 +42,11 @@ describe('migration #42', function () { bar: 'baz', }, foo: 'bar', - }) - done() + }); + done(); }) - .catch(done) - }) + .catch(done); + }); it('should initialize AppStateController if it does not exist', function (done) { const oldStorage = { @@ -54,7 +54,7 @@ describe('migration #42', function () { data: { foo: 'bar', }, - } + }; migration42 .migrate(oldStorage) @@ -64,9 +64,9 @@ describe('migration #42', function () { AppStateController: { connectedStatusPopoverHasBeenShown: false, }, - }) - done() + }); + done(); }) - .catch(done) - }) -}) + .catch(done); + }); +}); diff --git a/test/unit/migrations/043-test.js b/test/unit/migrations/043-test.js index 5a25e676c..25ac0336d 100644 --- a/test/unit/migrations/043-test.js +++ b/test/unit/migrations/043-test.js @@ -1,5 +1,5 @@ -import { strict as assert } from 'assert' -import migration43 from '../../../app/scripts/migrations/043' +import { strict as assert } from 'assert'; +import migration43 from '../../../app/scripts/migrations/043'; describe('migration #43', function () { it('should update the version metadata', async function () { @@ -8,13 +8,13 @@ describe('migration #43', function () { version: 42, }, data: {}, - } + }; - const newStorage = await migration43.migrate(oldStorage) + const newStorage = await migration43.migrate(oldStorage); assert.deepEqual(newStorage.meta, { version: 43, - }) - }) + }); + }); it('should delete currentAccountTab state', async function () { const oldStorage = { @@ -26,16 +26,16 @@ describe('migration #43', function () { }, foo: 'bar', }, - } + }; - const newStorage = await migration43.migrate(oldStorage) + const newStorage = await migration43.migrate(oldStorage); assert.deepEqual(newStorage.data, { PreferencesController: { bar: 'baz', }, foo: 'bar', - }) - }) + }); + }); it('should do nothing if currentAccountTab state does not exist', async function () { const oldStorage = { @@ -46,9 +46,9 @@ describe('migration #43', function () { }, foo: 'bar', }, - } + }; - const newStorage = await migration43.migrate(oldStorage) - assert.deepEqual(oldStorage.data, newStorage.data) - }) -}) + const newStorage = await migration43.migrate(oldStorage); + assert.deepEqual(oldStorage.data, newStorage.data); + }); +}); diff --git a/test/unit/migrations/044-test.js b/test/unit/migrations/044-test.js index 0fe8a9648..0b53b506b 100644 --- a/test/unit/migrations/044-test.js +++ b/test/unit/migrations/044-test.js @@ -1,5 +1,5 @@ -import { strict as assert } from 'assert' -import migration44 from '../../../app/scripts/migrations/044' +import { strict as assert } from 'assert'; +import migration44 from '../../../app/scripts/migrations/044'; describe('migration #44', function () { it('should update the version metadata', async function () { @@ -8,13 +8,13 @@ describe('migration #44', function () { version: 43, }, data: {}, - } + }; - const newStorage = await migration44.migrate(oldStorage) + const newStorage = await migration44.migrate(oldStorage); assert.deepEqual(newStorage.meta, { version: 44, - }) - }) + }); + }); it('should delete mkrMigrationReminderTimestamp state', async function () { const oldStorage = { @@ -26,16 +26,16 @@ describe('migration #44', function () { }, foo: 'bar', }, - } + }; - const newStorage = await migration44.migrate(oldStorage) + const newStorage = await migration44.migrate(oldStorage); assert.deepEqual(newStorage.data, { AppStateController: { bar: 'baz', }, foo: 'bar', - }) - }) + }); + }); it('should delete mkrMigrationReminderTimestamp state if it is null', async function () { const oldStorage = { @@ -47,16 +47,16 @@ describe('migration #44', function () { }, foo: 'bar', }, - } + }; - const newStorage = await migration44.migrate(oldStorage) + const newStorage = await migration44.migrate(oldStorage); assert.deepEqual(newStorage.data, { AppStateController: { bar: 'baz', }, foo: 'bar', - }) - }) + }); + }); it('should do nothing if mkrMigrationReminderTimestamp state does not exist', async function () { const oldStorage = { @@ -67,9 +67,9 @@ describe('migration #44', function () { }, foo: 'bar', }, - } + }; - const newStorage = await migration44.migrate(oldStorage) - assert.deepEqual(oldStorage.data, newStorage.data) - }) -}) + const newStorage = await migration44.migrate(oldStorage); + assert.deepEqual(oldStorage.data, newStorage.data); + }); +}); diff --git a/test/unit/migrations/045-test.js b/test/unit/migrations/045-test.js index 6547203da..bd102a927 100644 --- a/test/unit/migrations/045-test.js +++ b/test/unit/migrations/045-test.js @@ -1,5 +1,5 @@ -import assert from 'assert' -import migration45 from '../../../app/scripts/migrations/045' +import assert from 'assert'; +import migration45 from '../../../app/scripts/migrations/045'; describe('migration #45', function () { it('should update the version metadata', function (done) { @@ -8,18 +8,18 @@ describe('migration #45', function () { version: 44, }, data: {}, - } + }; migration45 .migrate(oldStorage) .then((newStorage) => { assert.deepEqual(newStorage.meta, { version: 45, - }) - done() + }); + done(); }) - .catch(done) - }) + .catch(done); + }); it('should update ipfsGateway value if outdated', function (done) { const oldStorage = { @@ -31,7 +31,7 @@ describe('migration #45', function () { }, foo: 'bar', }, - } + }; migration45 .migrate(oldStorage) @@ -42,11 +42,11 @@ describe('migration #45', function () { bar: 'baz', }, foo: 'bar', - }) - done() + }); + done(); }) - .catch(done) - }) + .catch(done); + }); it('should not update ipfsGateway value if custom set', function (done) { const oldStorage = { @@ -58,7 +58,7 @@ describe('migration #45', function () { }, foo: 'bar', }, - } + }; migration45 .migrate(oldStorage) @@ -69,11 +69,11 @@ describe('migration #45', function () { bar: 'baz', }, foo: 'bar', - }) - done() + }); + done(); }) - .catch(done) - }) + .catch(done); + }); it('should do nothing if no PreferencesController key', function (done) { const oldStorage = { @@ -81,16 +81,16 @@ describe('migration #45', function () { data: { foo: 'bar', }, - } + }; migration45 .migrate(oldStorage) .then((newStorage) => { assert.deepEqual(newStorage.data, { foo: 'bar', - }) - done() + }); + done(); }) - .catch(done) - }) -}) + .catch(done); + }); +}); diff --git a/test/unit/migrations/046-test.js b/test/unit/migrations/046-test.js index 0c327eb8a..43a79da94 100644 --- a/test/unit/migrations/046-test.js +++ b/test/unit/migrations/046-test.js @@ -1,5 +1,5 @@ -import { strict as assert } from 'assert' -import migration46 from '../../../app/scripts/migrations/046' +import { strict as assert } from 'assert'; +import migration46 from '../../../app/scripts/migrations/046'; describe('migration #46', function () { it('should update the version metadata', async function () { @@ -8,13 +8,13 @@ describe('migration #46', function () { version: 45, }, data: {}, - } + }; - const newStorage = await migration46.migrate(oldStorage) + const newStorage = await migration46.migrate(oldStorage); assert.deepEqual(newStorage.meta, { version: 46, - }) - }) + }); + }); it('should delete ABTestController state', async function () { const oldStorage = { @@ -27,13 +27,13 @@ describe('migration #46', function () { }, foo: 'bar', }, - } + }; - const newStorage = await migration46.migrate(oldStorage) + const newStorage = await migration46.migrate(oldStorage); assert.deepEqual(newStorage.data, { foo: 'bar', - }) - }) + }); + }); it('should do nothing if ABTestController state does not exist', async function () { const oldStorage = { @@ -44,9 +44,9 @@ describe('migration #46', function () { }, foo: 'bar', }, - } + }; - const newStorage = await migration46.migrate(oldStorage) - assert.deepEqual(oldStorage.data, newStorage.data) - }) -}) + const newStorage = await migration46.migrate(oldStorage); + assert.deepEqual(oldStorage.data, newStorage.data); + }); +}); diff --git a/test/unit/migrations/047-test.js b/test/unit/migrations/047-test.js index bdaf66175..12dc35fdf 100644 --- a/test/unit/migrations/047-test.js +++ b/test/unit/migrations/047-test.js @@ -1,5 +1,5 @@ -import { strict as assert } from 'assert' -import migration47 from '../../../app/scripts/migrations/047' +import { strict as assert } from 'assert'; +import migration47 from '../../../app/scripts/migrations/047'; describe('migration #47', function () { it('should update the version metadata', async function () { @@ -8,13 +8,13 @@ describe('migration #47', function () { version: 46, }, data: {}, - } + }; - const newStorage = await migration47.migrate(oldStorage) + const newStorage = await migration47.migrate(oldStorage); assert.deepEqual(newStorage.meta, { version: 47, - }) - }) + }); + }); it('should stringify transactions metamaskNetworkId values', async function () { const oldStorage = { @@ -30,9 +30,9 @@ describe('migration #47', function () { }, foo: 'bar', }, - } + }; - const newStorage = await migration47.migrate(oldStorage) + const newStorage = await migration47.migrate(oldStorage); assert.deepEqual(newStorage.data, { TransactionController: { transactions: [ @@ -43,8 +43,8 @@ describe('migration #47', function () { ], }, foo: 'bar', - }) - }) + }); + }); it('should do nothing if transactions metamaskNetworkId values are already strings', async function () { const oldStorage = { @@ -60,11 +60,11 @@ describe('migration #47', function () { }, foo: 'bar', }, - } + }; - const newStorage = await migration47.migrate(oldStorage) - assert.deepEqual(oldStorage.data, newStorage.data) - }) + const newStorage = await migration47.migrate(oldStorage); + assert.deepEqual(oldStorage.data, newStorage.data); + }); it('should do nothing if transactions state does not exist', async function () { const oldStorage = { @@ -75,11 +75,11 @@ describe('migration #47', function () { }, foo: 'bar', }, - } + }; - const newStorage = await migration47.migrate(oldStorage) - assert.deepEqual(oldStorage.data, newStorage.data) - }) + const newStorage = await migration47.migrate(oldStorage); + assert.deepEqual(oldStorage.data, newStorage.data); + }); it('should do nothing if transactions state is empty', async function () { const oldStorage = { @@ -91,19 +91,19 @@ describe('migration #47', function () { }, foo: 'bar', }, - } + }; - const newStorage = await migration47.migrate(oldStorage) - assert.deepEqual(oldStorage.data, newStorage.data) - }) + const newStorage = await migration47.migrate(oldStorage); + assert.deepEqual(oldStorage.data, newStorage.data); + }); it('should do nothing if state is empty', async function () { const oldStorage = { meta: {}, data: {}, - } + }; - const newStorage = await migration47.migrate(oldStorage) - assert.deepEqual(oldStorage.data, newStorage.data) - }) -}) + const newStorage = await migration47.migrate(oldStorage); + assert.deepEqual(oldStorage.data, newStorage.data); + }); +}); diff --git a/test/unit/migrations/048-test.js b/test/unit/migrations/048-test.js index bf96a0715..cd731c38e 100644 --- a/test/unit/migrations/048-test.js +++ b/test/unit/migrations/048-test.js @@ -1,5 +1,5 @@ -import { strict as assert } from 'assert' -import migration48 from '../../../app/scripts/migrations/048' +import { strict as assert } from 'assert'; +import migration48 from '../../../app/scripts/migrations/048'; const localhostNetwork = { rpcUrl: 'http://localhost:8545', @@ -7,7 +7,7 @@ const localhostNetwork = { ticker: 'ETH', nickname: 'Localhost 8545', rpcPrefs: {}, -} +}; const expectedPreferencesState = { PreferencesController: { frequentRpcListDetail: [ @@ -16,7 +16,7 @@ const expectedPreferencesState = { }, ], }, -} +}; describe('migration #48', function () { it('should update the version metadata', async function () { @@ -25,13 +25,13 @@ describe('migration #48', function () { version: 47, }, data: {}, - } + }; - const newStorage = await migration48.migrate(oldStorage) + const newStorage = await migration48.migrate(oldStorage); assert.deepEqual(newStorage.meta, { version: 48, - }) - }) + }); + }); it('should delete NetworkController.settings', async function () { const oldStorage = { @@ -47,9 +47,9 @@ describe('migration #48', function () { }, foo: 'bar', }, - } + }; - const newStorage = await migration48.migrate(oldStorage) + const newStorage = await migration48.migrate(oldStorage); assert.deepEqual(newStorage.data, { ...expectedPreferencesState, NetworkController: { @@ -58,8 +58,8 @@ describe('migration #48', function () { }, }, foo: 'bar', - }) - }) + }); + }); it('should migrate NetworkController.provider to Rinkeby if the type is "rpc" and the chainId is invalid (1)', async function () { const oldStorage = { @@ -75,9 +75,9 @@ describe('migration #48', function () { }, foo: 'bar', }, - } + }; - const newStorage = await migration48.migrate(oldStorage) + const newStorage = await migration48.migrate(oldStorage); assert.deepEqual(newStorage.data, { ...expectedPreferencesState, NetworkController: { @@ -92,8 +92,8 @@ describe('migration #48', function () { foo: 'bar', }, foo: 'bar', - }) - }) + }); + }); it('should migrate NetworkController.provider to Rinkeby if the type is "rpc" and the chainId is invalid (2)', async function () { const oldStorage = { @@ -109,9 +109,9 @@ describe('migration #48', function () { }, foo: 'bar', }, - } + }; - const newStorage = await migration48.migrate(oldStorage) + const newStorage = await migration48.migrate(oldStorage); assert.deepEqual(newStorage.data, { ...expectedPreferencesState, NetworkController: { @@ -126,8 +126,8 @@ describe('migration #48', function () { foo: 'bar', }, foo: 'bar', - }) - }) + }); + }); it('should not migrate NetworkController.provider to Rinkeby if the type is "rpc" and the chainId is valid', async function () { const oldStorage = { @@ -143,9 +143,9 @@ describe('migration #48', function () { }, foo: 'bar', }, - } + }; - const newStorage = await migration48.migrate(oldStorage) + const newStorage = await migration48.migrate(oldStorage); assert.deepEqual(newStorage.data, { ...expectedPreferencesState, NetworkController: { @@ -157,8 +157,8 @@ describe('migration #48', function () { foo: 'bar', }, foo: 'bar', - }) - }) + }); + }); it('should migrate NetworkController.provider to Rinkeby if the type is "localhost"', async function () { const oldStorage = { @@ -173,9 +173,9 @@ describe('migration #48', function () { }, foo: 'bar', }, - } + }; - const newStorage = await migration48.migrate(oldStorage) + const newStorage = await migration48.migrate(oldStorage); assert.deepEqual(newStorage.data, { ...expectedPreferencesState, NetworkController: { @@ -190,8 +190,8 @@ describe('migration #48', function () { foo: 'bar', }, foo: 'bar', - }) - }) + }); + }); it('should re-key NetworkController.provider.rpcTarget to rpcUrl if the type is not "rpc" or "localhost"', async function () { const oldStorage = { @@ -207,9 +207,9 @@ describe('migration #48', function () { }, foo: 'bar', }, - } + }; - const newStorage = await migration48.migrate(oldStorage) + const newStorage = await migration48.migrate(oldStorage); assert.deepEqual(newStorage.data, { ...expectedPreferencesState, NetworkController: { @@ -221,8 +221,8 @@ describe('migration #48', function () { }, }, foo: 'bar', - }) - }) + }); + }); it('should do nothing to NetworkController if affected state does not exist', async function () { const oldStorage = { @@ -235,20 +235,20 @@ describe('migration #48', function () { }, foo: 'bar', }, - } + }; - const newStorage = await migration48.migrate(oldStorage) + const newStorage = await migration48.migrate(oldStorage); assert.deepEqual( { ...expectedPreferencesState, ...oldStorage.data }, { ...expectedPreferencesState, ...newStorage.data }, - ) - }) + ); + }); it('should add frequentRpcListDetail item to beginning of list', async function () { const existingList = [ { rpcUrl: 'foo', chainId: '0x1' }, { rpcUrl: 'bar', chainId: '0x2' }, - ] + ]; const oldStorage = { meta: {}, @@ -258,16 +258,16 @@ describe('migration #48', function () { }, foo: 'bar', }, - } + }; - const newStorage = await migration48.migrate(oldStorage) + const newStorage = await migration48.migrate(oldStorage); assert.deepEqual(newStorage.data, { PreferencesController: { frequentRpcListDetail: [{ ...localhostNetwork }, ...existingList], }, foo: 'bar', - }) - }) + }); + }); it('should delete CachedBalancesController.cachedBalances', async function () { const oldStorage = { @@ -283,9 +283,9 @@ describe('migration #48', function () { }, foo: 'bar', }, - } + }; - const newStorage = await migration48.migrate(oldStorage) + const newStorage = await migration48.migrate(oldStorage); assert.deepEqual(newStorage.data, { ...expectedPreferencesState, CachedBalancesController: { @@ -294,8 +294,8 @@ describe('migration #48', function () { }, }, foo: 'bar', - }) - }) + }); + }); it('should convert hex transaction metamaskNetworkId values to decimal', async function () { const oldStorage = { @@ -320,9 +320,9 @@ describe('migration #48', function () { }, foo: 'bar', }, - } + }; - const newStorage = await migration48.migrate(oldStorage) + const newStorage = await migration48.migrate(oldStorage); assert.deepEqual(newStorage.data, { ...expectedPreferencesState, TransactionController: { @@ -343,8 +343,8 @@ describe('migration #48', function () { }, }, foo: 'bar', - }) - }) + }); + }); it('should migrate the address book', async function () { const oldStorage = { @@ -377,9 +377,9 @@ describe('migration #48', function () { }, foo: 'bar', }, - } + }; - const newStorage = await migration48.migrate(oldStorage) + const newStorage = await migration48.migrate(oldStorage); assert.deepEqual(newStorage.data, { ...expectedPreferencesState, AddressBookController: { @@ -408,8 +408,8 @@ describe('migration #48', function () { }, }, foo: 'bar', - }) - }) + }); + }); it('should migrate the address book and merge entries', async function () { const oldStorage = { @@ -449,9 +449,9 @@ describe('migration #48', function () { }, foo: 'bar', }, - } + }; - const newStorage = await migration48.migrate(oldStorage) + const newStorage = await migration48.migrate(oldStorage); assert.deepEqual(newStorage.data, { ...expectedPreferencesState, AddressBookController: { @@ -480,8 +480,8 @@ describe('migration #48', function () { }, }, foo: 'bar', - }) - }) + }); + }); it('should not modify address book if all entries are valid or un-parseable', async function () { const oldStorage = { @@ -498,9 +498,9 @@ describe('migration #48', function () { }, foo: 'bar', }, - } + }; - const newStorage = await migration48.migrate(oldStorage) + const newStorage = await migration48.migrate(oldStorage); assert.deepEqual(newStorage.data, { ...expectedPreferencesState, AddressBookController: { @@ -513,8 +513,8 @@ describe('migration #48', function () { }, }, foo: 'bar', - }) - }) + }); + }); it('should delete localhost key in IncomingTransactionsController', async function () { const oldStorage = { @@ -529,9 +529,9 @@ describe('migration #48', function () { }, foo: 'bar', }, - } + }; - const newStorage = await migration48.migrate(oldStorage) + const newStorage = await migration48.migrate(oldStorage); assert.deepEqual(newStorage.data, { ...expectedPreferencesState, IncomingTransactionsController: { @@ -541,8 +541,8 @@ describe('migration #48', function () { bar: 'baz', }, foo: 'bar', - }) - }) + }); + }); it('should not modify IncomingTransactionsController state if affected key is missing', async function () { const oldStorage = { @@ -557,9 +557,9 @@ describe('migration #48', function () { }, foo: 'bar', }, - } + }; - const newStorage = await migration48.migrate(oldStorage) + const newStorage = await migration48.migrate(oldStorage); assert.deepEqual(newStorage.data, { ...expectedPreferencesState, IncomingTransactionsController: { @@ -570,8 +570,8 @@ describe('migration #48', function () { bar: 'baz', }, foo: 'bar', - }) - }) + }); + }); it('should merge localhost token list into rpc token list', async function () { const oldStorage = { @@ -601,9 +601,9 @@ describe('migration #48', function () { }, foo: 'bar', }, - } + }; - const newStorage = await migration48.migrate(oldStorage) + const newStorage = await migration48.migrate(oldStorage); assert.deepEqual(newStorage.data, { PreferencesController: { accountTokens: { @@ -630,6 +630,6 @@ describe('migration #48', function () { ], }, foo: 'bar', - }) - }) -}) + }); + }); +}); diff --git a/test/unit/migrations/049-test.js b/test/unit/migrations/049-test.js index f720a4723..df441a47a 100644 --- a/test/unit/migrations/049-test.js +++ b/test/unit/migrations/049-test.js @@ -1,5 +1,5 @@ -import assert from 'assert' -import migration49 from '../../../app/scripts/migrations/049' +import assert from 'assert'; +import migration49 from '../../../app/scripts/migrations/049'; describe('migration #49', function () { it('should update the version metadata', async function () { @@ -8,13 +8,13 @@ describe('migration #49', function () { version: 48, }, data: {}, - } + }; - const newStorage = await migration49.migrate(oldStorage) + const newStorage = await migration49.migrate(oldStorage); assert.deepStrictEqual(newStorage.meta, { version: 49, - }) - }) + }); + }); it('should move metaMetricsId to MetaMetricsController', async function () { const oldStorage = { @@ -26,9 +26,9 @@ describe('migration #49', function () { }, foo: 'bar', }, - } + }; - const newStorage = await migration49.migrate(oldStorage) + const newStorage = await migration49.migrate(oldStorage); assert.deepStrictEqual(newStorage.data, { PreferencesController: { bar: 'baz', @@ -37,8 +37,8 @@ describe('migration #49', function () { metaMetricsId: '0xaab', }, foo: 'bar', - }) - }) + }); + }); it('should move participateInMetaMetrics to MetaMetricsController', async function () { const oldStorage = { @@ -50,9 +50,9 @@ describe('migration #49', function () { }, foo: 'bar', }, - } + }; - const newStorage = await migration49.migrate(oldStorage) + const newStorage = await migration49.migrate(oldStorage); assert.deepStrictEqual(newStorage.data, { PreferencesController: { bar: 'baz', @@ -61,8 +61,8 @@ describe('migration #49', function () { participateInMetaMetrics: false, }, foo: 'bar', - }) - }) + }); + }); it('should move metaMetricsSendCount to MetaMetricsController', async function () { const oldStorage = { @@ -74,9 +74,9 @@ describe('migration #49', function () { }, foo: 'bar', }, - } + }; - const newStorage = await migration49.migrate(oldStorage) + const newStorage = await migration49.migrate(oldStorage); assert.deepStrictEqual(newStorage.data, { PreferencesController: { bar: 'baz', @@ -85,8 +85,8 @@ describe('migration #49', function () { metaMetricsSendCount: 1, }, foo: 'bar', - }) - }) + }); + }); it('should move all metaMetrics fields to MetaMetricsController', async function () { const oldStorage = { @@ -100,9 +100,9 @@ describe('migration #49', function () { }, foo: 'bar', }, - } + }; - const newStorage = await migration49.migrate(oldStorage) + const newStorage = await migration49.migrate(oldStorage); assert.deepStrictEqual(newStorage.data, { PreferencesController: { bar: 'baz', @@ -113,8 +113,8 @@ describe('migration #49', function () { participateInMetaMetrics: true, }, foo: 'bar', - }) - }) + }); + }); it('should do nothing if no PreferencesController key', async function () { const oldStorage = { @@ -122,11 +122,11 @@ describe('migration #49', function () { data: { foo: 'bar', }, - } + }; - const newStorage = await migration49.migrate(oldStorage) + const newStorage = await migration49.migrate(oldStorage); assert.deepStrictEqual(newStorage.data, { foo: 'bar', - }) - }) -}) + }); + }); +}); diff --git a/test/unit/migrations/050-test.js b/test/unit/migrations/050-test.js index fea2f1b06..05aa735ae 100644 --- a/test/unit/migrations/050-test.js +++ b/test/unit/migrations/050-test.js @@ -1,6 +1,6 @@ -import { strict as assert } from 'assert' -import sinon from 'sinon' -import migration50 from '../../../app/scripts/migrations/050' +import { strict as assert } from 'assert'; +import sinon from 'sinon'; +import migration50 from '../../../app/scripts/migrations/050'; const LEGACY_LOCAL_STORAGE_KEYS = [ 'METASWAP_GAS_PRICE_ESTIMATES_LAST_RETRIEVED', @@ -12,18 +12,18 @@ const LEGACY_LOCAL_STORAGE_KEYS = [ 'BASIC_GAS_AND_TIME_API_ESTIMATES_LAST_RETRIEVED', 'GAS_API_ESTIMATES_LAST_RETRIEVED', 'GAS_API_ESTIMATES', -] +]; describe('migration #50', function () { - let mockLocalStorageRemoveItem + let mockLocalStorageRemoveItem; beforeEach(function () { - mockLocalStorageRemoveItem = sinon.stub(window.localStorage, 'removeItem') - }) + mockLocalStorageRemoveItem = sinon.stub(window.localStorage, 'removeItem'); + }); afterEach(function () { - sinon.restore() - }) + sinon.restore(); + }); it('should update the version metadata', async function () { const oldStorage = { @@ -31,13 +31,13 @@ describe('migration #50', function () { version: 49, }, data: {}, - } + }; - const newStorage = await migration50.migrate(oldStorage) + const newStorage = await migration50.migrate(oldStorage); assert.deepEqual(newStorage.meta, { version: 50, - }) - }) + }); + }); it('should call window.localStorage.removeItem for each legacy key', async function () { const oldStorage = { @@ -45,45 +45,45 @@ describe('migration #50', function () { version: 49, }, data: {}, - } + }; - await migration50.migrate(oldStorage) - assert.equal(mockLocalStorageRemoveItem.callCount, 9) + await migration50.migrate(oldStorage); + assert.equal(mockLocalStorageRemoveItem.callCount, 9); assert.equal( mockLocalStorageRemoveItem.getCall(0).args[0], LEGACY_LOCAL_STORAGE_KEYS[0], - ) + ); assert.equal( mockLocalStorageRemoveItem.getCall(1).args[0], LEGACY_LOCAL_STORAGE_KEYS[1], - ) + ); assert.equal( mockLocalStorageRemoveItem.getCall(2).args[0], LEGACY_LOCAL_STORAGE_KEYS[2], - ) + ); assert.equal( mockLocalStorageRemoveItem.getCall(3).args[0], LEGACY_LOCAL_STORAGE_KEYS[3], - ) + ); assert.equal( mockLocalStorageRemoveItem.getCall(4).args[0], LEGACY_LOCAL_STORAGE_KEYS[4], - ) + ); assert.equal( mockLocalStorageRemoveItem.getCall(5).args[0], LEGACY_LOCAL_STORAGE_KEYS[5], - ) + ); assert.equal( mockLocalStorageRemoveItem.getCall(6).args[0], LEGACY_LOCAL_STORAGE_KEYS[6], - ) + ); assert.equal( mockLocalStorageRemoveItem.getCall(7).args[0], LEGACY_LOCAL_STORAGE_KEYS[7], - ) + ); assert.equal( mockLocalStorageRemoveItem.getCall(8).args[0], LEGACY_LOCAL_STORAGE_KEYS[8], - ) - }) -}) + ); + }); +}); diff --git a/test/unit/migrations/051-test.js b/test/unit/migrations/051-test.js index ae0a78afe..4d1428a87 100644 --- a/test/unit/migrations/051-test.js +++ b/test/unit/migrations/051-test.js @@ -1,9 +1,9 @@ -import { strict as assert } from 'assert' -import migration51 from '../../../app/scripts/migrations/051' +import { strict as assert } from 'assert'; +import migration51 from '../../../app/scripts/migrations/051'; import { INFURA_PROVIDER_TYPES, NETWORK_TYPE_TO_ID_MAP, -} from '../../../shared/constants/network' +} from '../../../shared/constants/network'; describe('migration #51', function () { it('should update the version metadata', async function () { @@ -12,13 +12,13 @@ describe('migration #51', function () { version: 50, }, data: {}, - } + }; - const newStorage = await migration51.migrate(oldStorage) + const newStorage = await migration51.migrate(oldStorage); assert.deepEqual(newStorage.meta, { version: 51, - }) - }) + }); + }); describe('setting chainId', function () { INFURA_PROVIDER_TYPES.forEach(function (type) { @@ -36,8 +36,8 @@ describe('migration #51', function () { }, foo: 'bar', }, - } - const newStorage = await migration51.migrate(oldStorage) + }; + const newStorage = await migration51.migrate(oldStorage); assert.deepEqual(newStorage.data, { NetworkController: { settings: { @@ -49,8 +49,8 @@ describe('migration #51', function () { }, }, foo: 'bar', - }) - }) + }); + }); it(`should correctly set the chainId for the Infura network "${type}", if an incorrect chainId is set`, async function () { const oldStorage = { @@ -67,8 +67,8 @@ describe('migration #51', function () { }, foo: 'bar', }, - } - const newStorage = await migration51.migrate(oldStorage) + }; + const newStorage = await migration51.migrate(oldStorage); assert.deepEqual(newStorage.data, { NetworkController: { settings: { @@ -80,9 +80,9 @@ describe('migration #51', function () { }, }, foo: 'bar', - }) - }) - }) + }); + }); + }); it('should not set the chainId for a non-Infura network that does not have chainId set', async function () { const oldStorage = { @@ -97,10 +97,10 @@ describe('migration #51', function () { }, }, }, - } - const newStorage = await migration51.migrate(oldStorage) - assert.deepEqual(newStorage.data, oldStorage.data) - }) + }; + const newStorage = await migration51.migrate(oldStorage); + assert.deepEqual(newStorage.data, oldStorage.data); + }); it('should not set the chainId for a non-Infura network that does have chainId set', async function () { const oldStorage = { @@ -116,9 +116,9 @@ describe('migration #51', function () { }, }, }, - } - const newStorage = await migration51.migrate(oldStorage) - assert.deepEqual(newStorage.data, oldStorage.data) - }) - }) -}) + }; + const newStorage = await migration51.migrate(oldStorage); + assert.deepEqual(newStorage.data, oldStorage.data); + }); + }); +}); diff --git a/test/unit/migrations/migrations-test.js b/test/unit/migrations/migrations-test.js index a61376145..d5fcd6bdc 100644 --- a/test/unit/migrations/migrations-test.js +++ b/test/unit/migrations/migrations-test.js @@ -1,91 +1,91 @@ -import assert from 'assert' -import wallet1 from '../../lib/migrations/001.json' -import vault4 from '../../lib/migrations/004.json' -import migration2 from '../../../app/scripts/migrations/002' -import migration3 from '../../../app/scripts/migrations/003' -import migration4 from '../../../app/scripts/migrations/004' -import migration5 from '../../../app/scripts/migrations/005' -import migration6 from '../../../app/scripts/migrations/006' -import migration7 from '../../../app/scripts/migrations/007' -import migration8 from '../../../app/scripts/migrations/008' -import migration9 from '../../../app/scripts/migrations/009' -import migration10 from '../../../app/scripts/migrations/010' -import migration11 from '../../../app/scripts/migrations/011' -import migration12 from '../../../app/scripts/migrations/012' -import migration13 from '../../../app/scripts/migrations/013' +import assert from 'assert'; +import wallet1 from '../../lib/migrations/001.json'; +import vault4 from '../../lib/migrations/004.json'; +import migration2 from '../../../app/scripts/migrations/002'; +import migration3 from '../../../app/scripts/migrations/003'; +import migration4 from '../../../app/scripts/migrations/004'; +import migration5 from '../../../app/scripts/migrations/005'; +import migration6 from '../../../app/scripts/migrations/006'; +import migration7 from '../../../app/scripts/migrations/007'; +import migration8 from '../../../app/scripts/migrations/008'; +import migration9 from '../../../app/scripts/migrations/009'; +import migration10 from '../../../app/scripts/migrations/010'; +import migration11 from '../../../app/scripts/migrations/011'; +import migration12 from '../../../app/scripts/migrations/012'; +import migration13 from '../../../app/scripts/migrations/013'; -let vault5, vault6, vault7, vault8, vault9 // vault10, vault11 +let vault5, vault6, vault7, vault8, vault9; // vault10, vault11 -const oldTestRpc = 'https://rawtestrpc.metamask.io/' -const newTestRpc = 'https://testrpc.metamask.io/' +const oldTestRpc = 'https://rawtestrpc.metamask.io/'; +const newTestRpc = 'https://testrpc.metamask.io/'; describe('wallet1 is migrated successfully', function () { it('should convert providers', function () { - wallet1.data.config.provider = { type: 'etherscan', rpcTarget: null } + wallet1.data.config.provider = { type: 'etherscan', rpcTarget: null }; return migration2 .migrate(wallet1) .then((secondResult) => { - const secondData = secondResult.data + const secondData = secondResult.data; assert.equal( secondData.config.provider.type, 'rpc', 'provider should be rpc', - ) + ); assert.equal( secondData.config.provider.rpcTarget, 'https://rpc.metamask.io/', 'main provider should be our rpc', - ) - secondResult.data.config.provider.rpcTarget = oldTestRpc - return migration3.migrate(secondResult) + ); + secondResult.data.config.provider.rpcTarget = oldTestRpc; + return migration3.migrate(secondResult); }) .then((thirdResult) => { assert.equal( thirdResult.data.config.provider.rpcTarget, newTestRpc, 'config.provider.rpcTarget should be set to the proper testrpc url.', - ) - return migration4.migrate(thirdResult) + ); + return migration4.migrate(thirdResult); }) .then((fourthResult) => { - const fourthData = fourthResult.data + const fourthData = fourthResult.data; assert.equal( fourthData.config.provider.rpcTarget, null, 'old rpcTarget should not exist.', - ) + ); assert.equal( fourthData.config.provider.type, 'testnet', 'config.provider should be set to testnet.', - ) + ); - return migration5.migrate(vault4) + return migration5.migrate(vault4); }) .then((fifthResult) => { - const fifthData = fifthResult.data - assert.equal(fifthData.vault, null, 'old vault should not exist') + const fifthData = fifthResult.data; + assert.equal(fifthData.vault, null, 'old vault should not exist'); assert.equal( fifthData.walletNicknames, null, 'old walletNicknames should not exist', - ) + ); assert.equal( fifthData.config.selectedAccount, null, 'old config.selectedAccount should not exist', - ) + ); assert.equal( fifthData.KeyringController.vault, vault4.data.vault, 'KeyringController.vault should exist', - ) + ); assert.equal( fifthData.KeyringController.selectedAccount, vault4.data.config.selectedAccount, 'KeyringController.selectedAccount should have moved', - ) + ); assert.equal( fifthData.KeyringController.walletNicknames[ '0x0beb674745816b125fbc07285d39fd373e64895c' @@ -94,159 +94,159 @@ describe('wallet1 is migrated successfully', function () { '0x0beb674745816b125fbc07285d39fd373e64895c' ], 'KeyringController.walletNicknames should have moved', - ) + ); - vault5 = fifthResult - return migration6.migrate(fifthResult) + vault5 = fifthResult; + return migration6.migrate(fifthResult); }) .then((sixthResult) => { assert.equal( sixthResult.data.KeyringController.selectedAccount, null, 'old selectedAccount should not exist', - ) + ); assert.equal( sixthResult.data.PreferencesController.selectedAddress, vault5.data.KeyringController.selectedAccount, 'selectedAccount should have moved', - ) + ); - vault6 = sixthResult - return migration7.migrate(sixthResult) + vault6 = sixthResult; + return migration7.migrate(sixthResult); }) .then((seventhResult) => { assert.equal( seventhResult.data.transactions, null, 'old transactions should not exist', - ) + ); assert.equal( seventhResult.data.gasMultiplier, null, 'old gasMultiplier should not exist', - ) + ); assert.equal( seventhResult.data.TransactionManager.transactions[0].id, vault6.data.transactions[0].id, 'transactions should have moved', - ) + ); assert.equal( seventhResult.data.TransactionManager.gasMultiplier, vault6.data.gasMultiplier, 'gasMultiplier should have moved', - ) + ); - vault7 = seventhResult - return migration8.migrate(seventhResult) + vault7 = seventhResult; + return migration8.migrate(seventhResult); }) .then((eighthResult) => { assert.equal( eighthResult.data.noticesList, null, 'old noticesList should not exist', - ) + ); assert.equal( eighthResult.data.NoticeController.noticesList[0].title, vault7.data.noticesList[0].title, 'noticesList should have moved', - ) + ); - vault8 = eighthResult - return migration9.migrate(eighthResult) + vault8 = eighthResult; + return migration9.migrate(eighthResult); }) .then((ninthResult) => { assert.equal( ninthResult.data.currentFiat, null, 'old currentFiat should not exist', - ) + ); assert.equal( ninthResult.data.fiatCurrency, null, 'old fiatCurrency should not exist', - ) + ); assert.equal( ninthResult.data.conversionRate, null, 'old conversionRate should not exist', - ) + ); assert.equal( ninthResult.data.conversionDate, null, 'old conversionDate should not exist', - ) + ); assert.equal( ninthResult.data.CurrencyController.currentCurrency, vault8.data.fiatCurrency, 'currentFiat should have moved', - ) + ); assert.equal( ninthResult.data.CurrencyController.conversionRate, vault8.data.conversionRate, 'conversionRate should have moved', - ) + ); assert.equal( ninthResult.data.CurrencyController.conversionDate, vault8.data.conversionDate, 'conversionDate should have moved', - ) + ); - vault9 = ninthResult - return migration10.migrate(ninthResult) + vault9 = ninthResult; + return migration10.migrate(ninthResult); }) .then((tenthResult) => { assert.equal( tenthResult.data.shapeShiftTxList, null, 'old shapeShiftTxList should not exist', - ) + ); assert.equal( tenthResult.data.ShapeShiftController.shapeShiftTxList[0].transaction, vault9.data.shapeShiftTxList[0].transaction, - ) + ); - return migration11.migrate(tenthResult) + return migration11.migrate(tenthResult); }) .then((eleventhResult) => { assert.equal( eleventhResult.data.isDisclaimerConfirmed, null, 'isDisclaimerConfirmed should not exist', - ) + ); assert.equal( eleventhResult.data.TOSHash, null, 'TOSHash should not exist', - ) + ); - return migration12.migrate(eleventhResult) + return migration12.migrate(eleventhResult); }) .then((twelfthResult) => { assert.equal( twelfthResult.data.NoticeController.noticesList[0].body, '', 'notices that have been read should have an empty body.', - ) + ); assert.equal( twelfthResult.data.NoticeController.noticesList[1].body, 'nonempty', 'notices that have not been read should not have an empty body.', - ) + ); assert.equal( twelfthResult.data.config.provider.type, 'testnet', 'network is originally testnet.', - ) - return migration13.migrate(twelfthResult) + ); + return migration13.migrate(twelfthResult); }) .then((thirteenthResult) => { assert.equal( thirteenthResult.data.config.provider.type, 'ropsten', 'network has been changed to ropsten.', - ) - }) - }) -}) + ); + }); + }); +}); diff --git a/test/unit/migrations/migrator-test.js b/test/unit/migrations/migrator-test.js index 7c5001596..ee20cc7a6 100644 --- a/test/unit/migrations/migrator-test.js +++ b/test/unit/migrations/migrator-test.js @@ -1,107 +1,107 @@ -import fs from 'fs' -import assert from 'assert' -import { cloneDeep } from 'lodash' -import Migrator from '../../../app/scripts/lib/migrator' -import liveMigrations from '../../../app/scripts/migrations' -import data from '../../../app/scripts/first-time-state' +import fs from 'fs'; +import assert from 'assert'; +import { cloneDeep } from 'lodash'; +import Migrator from '../../../app/scripts/lib/migrator'; +import liveMigrations from '../../../app/scripts/migrations'; +import data from '../../../app/scripts/first-time-state'; const stubMigrations = [ { version: 1, migrate: (state) => { // clone the data just like we do in migrations - const clonedData = cloneDeep(state) - clonedData.meta.version = 1 - return Promise.resolve(clonedData) + const clonedData = cloneDeep(state); + clonedData.meta.version = 1; + return Promise.resolve(clonedData); }, }, { version: 2, migrate: (state) => { - const clonedData = cloneDeep(state) - clonedData.meta.version = 2 - return Promise.resolve(clonedData) + const clonedData = cloneDeep(state); + clonedData.meta.version = 2; + return Promise.resolve(clonedData); }, }, { version: 3, migrate: (state) => { - const clonedData = cloneDeep(state) - clonedData.meta.version = 3 - return Promise.resolve(clonedData) + const clonedData = cloneDeep(state); + clonedData.meta.version = 3; + return Promise.resolve(clonedData); }, }, -] -const versionedData = { meta: { version: 0 }, data: { hello: 'world' } } +]; +const versionedData = { meta: { version: 0 }, data: { hello: 'world' } }; const firstTimeState = { meta: { version: 0 }, data, -} +}; describe('migrations', function () { describe('liveMigrations require list', function () { - let migrationNumbers + let migrationNumbers; before(function () { - const fileNames = fs.readdirSync('./app/scripts/migrations/') + const fileNames = fs.readdirSync('./app/scripts/migrations/'); migrationNumbers = fileNames .reduce((acc, filename) => { - const name = filename.split('.')[0] + const name = filename.split('.')[0]; if (/^\d+$/u.test(name)) { - acc.push(name) + acc.push(name); } - return acc + return acc; }, []) - .map((num) => parseInt(num, 10)) - }) + .map((num) => parseInt(num, 10)); + }); it('should include all migrations', function () { migrationNumbers.forEach((num) => { - const migration = liveMigrations.find((m) => m.version === num) + const migration = liveMigrations.find((m) => m.version === num); assert( migration, `migration not included in 'migrations/index.js': ${num}`, - ) - }) - }) + ); + }); + }); it('should have tests for all migrations', function () { - const fileNames = fs.readdirSync('./test/unit/migrations/') + const fileNames = fs.readdirSync('./test/unit/migrations/'); const testNumbers = fileNames .reduce((acc, filename) => { - const name = filename.split('-test.')[0] + const name = filename.split('-test.')[0]; if (/^\d+$/u.test(name)) { - acc.push(name) + acc.push(name); } - return acc + return acc; }, []) - .map((num) => parseInt(num, 10)) + .map((num) => parseInt(num, 10)); migrationNumbers.forEach((num) => { if (num >= 33) { assert.ok( testNumbers.includes(num), `no test found for migration: ${num}`, - ) + ); } - }) - }) - }) + }); + }); + }); describe('Migrator', function () { it('migratedData version should be version 3', async function () { - const migrator = new Migrator({ migrations: stubMigrations }) - const migratedData = await migrator.migrateData(versionedData) - assert.equal(migratedData.meta.version, stubMigrations[2].version) - }) + const migrator = new Migrator({ migrations: stubMigrations }); + const migratedData = await migrator.migrateData(versionedData); + assert.equal(migratedData.meta.version, stubMigrations[2].version); + }); it('should match the last version in live migrations', async function () { - const migrator = new Migrator({ migrations: liveMigrations }) - const migratedData = await migrator.migrateData(firstTimeState) - const last = liveMigrations.length - 1 - assert.equal(migratedData.meta.version, liveMigrations[last].version) - }) + const migrator = new Migrator({ migrations: liveMigrations }); + const migratedData = await migrator.migrateData(firstTimeState); + const last = liveMigrations.length - 1; + assert.equal(migratedData.meta.version, liveMigrations[last].version); + }); it('should emit an error', async function () { const migrator = new Migrator({ @@ -109,12 +109,12 @@ describe('migrations', function () { { version: 1, async migrate() { - throw new Error('test') + throw new Error('test'); }, }, ], - }) - await assert.rejects(migrator.migrateData({ meta: { version: 0 } })) - }) - }) -}) + }); + await assert.rejects(migrator.migrateData({ meta: { version: 0 } })); + }); + }); +}); diff --git a/test/unit/migrations/template-test.js b/test/unit/migrations/template-test.js index ca74b30f0..79b127ed9 100644 --- a/test/unit/migrations/template-test.js +++ b/test/unit/migrations/template-test.js @@ -1,19 +1,19 @@ -import assert from 'assert' -import migrationTemplate from '../../../app/scripts/migrations/template' +import assert from 'assert'; +import migrationTemplate from '../../../app/scripts/migrations/template'; const storage = { meta: {}, data: {}, -} +}; describe('storage is migrated successfully', function () { it('should work', function (done) { migrationTemplate .migrate(storage) .then((migratedData) => { - assert.equal(migratedData.meta.version, 0) - done() + assert.equal(migratedData.meta.version, 0); + done(); }) - .catch(done) - }) -}) + .catch(done); + }); +}); diff --git a/test/unit/responsive/components/dropdown-test.js b/test/unit/responsive/components/dropdown-test.js index fc550a6fd..a7f83b07d 100644 --- a/test/unit/responsive/components/dropdown-test.js +++ b/test/unit/responsive/components/dropdown-test.js @@ -1,15 +1,15 @@ -import assert from 'assert' -import React from 'react' -import configureMockStore from 'redux-mock-store' -import { fireEvent } from '@testing-library/react' -import sinon from 'sinon' -import { renderWithProvider } from '../../../lib/render-helpers' -import { Dropdown } from '../../../../ui/app/components/app/dropdowns/components/dropdown' +import assert from 'assert'; +import React from 'react'; +import configureMockStore from 'redux-mock-store'; +import { fireEvent } from '@testing-library/react'; +import sinon from 'sinon'; +import { renderWithProvider } from '../../../lib/render-helpers'; +import { Dropdown } from '../../../../ui/app/components/app/dropdowns/components/dropdown'; describe('Dropdown components', function () { const mockState = { metamask: {}, - } + }; const props = { isOpen: true, @@ -21,12 +21,12 @@ describe('Dropdown components', function () { top: '36px', }, innerStyle: {}, - } + }; it('invokes click handler when item clicked', function () { - const store = configureMockStore()(mockState) + const store = configureMockStore()(mockState); - const onClickSpy = sinon.spy() + const onClickSpy = sinon.spy(); const { getByText } = renderWithProvider( @@ -34,11 +34,11 @@ describe('Dropdown components', function () {
  • Item 2
  • , store, - ) + ); - const item1 = getByText(/Item 1/u) - fireEvent.click(item1) + const item1 = getByText(/Item 1/u); + fireEvent.click(item1); - assert.ok(onClickSpy.calledOnce) - }) -}) + assert.ok(onClickSpy.calledOnce); + }); +}); diff --git a/test/unit/ui/app/actions.spec.js b/test/unit/ui/app/actions.spec.js index 6a02830a8..5cb248434 100644 --- a/test/unit/ui/app/actions.spec.js +++ b/test/unit/ui/app/actions.spec.js @@ -1,30 +1,30 @@ -import assert from 'assert' -import sinon from 'sinon' -import configureStore from 'redux-mock-store' -import thunk from 'redux-thunk' -import EthQuery from 'eth-query' -import Eth from 'ethjs' -import { createTestProviderTools } from '../../../stub/provider' -import enLocale from '../../../../app/_locales/en/messages.json' -import * as actions from '../../../../ui/app/store/actions' -import MetaMaskController from '../../../../app/scripts/metamask-controller' -import { TRANSACTION_STATUSES } from '../../../../shared/constants/transaction' +import assert from 'assert'; +import sinon from 'sinon'; +import configureStore from 'redux-mock-store'; +import thunk from 'redux-thunk'; +import EthQuery from 'eth-query'; +import Eth from 'ethjs'; +import { createTestProviderTools } from '../../../stub/provider'; +import enLocale from '../../../../app/_locales/en/messages.json'; +import * as actions from '../../../../ui/app/store/actions'; +import MetaMaskController from '../../../../app/scripts/metamask-controller'; +import { TRANSACTION_STATUSES } from '../../../../shared/constants/transaction'; -const { provider } = createTestProviderTools({ scaffold: {} }) -const middleware = [thunk] +const { provider } = createTestProviderTools({ scaffold: {} }); +const middleware = [thunk]; const defaultState = { metamask: { currentLocale: 'test', selectedAddress: '0xFirstAddress', provider: { chainId: '0x1' }, }, -} -const mockStore = (state = defaultState) => configureStore(middleware)(state) +}; +const mockStore = (state = defaultState) => configureStore(middleware)(state); describe('Actions', function () { - let background + let background; - const currentNetworkId = '42' + const currentNetworkId = '42'; beforeEach(async function () { background = sinon.createStubInstance(MetaMaskController, { @@ -34,28 +34,28 @@ describe('Actions', function () { selectedAddress: '0xFirstAddress', }), ), - }) + }); - global.ethQuery = new EthQuery(provider) - }) + global.ethQuery = new EthQuery(provider); + }); describe('#tryUnlockMetamask', function () { afterEach(function () { - sinon.restore() - }) + sinon.restore(); + }); it('calls submitPassword and verifySeedPhrase', async function () { - const store = mockStore() + const store = mockStore(); const submitPassword = background.submitPassword.callsFake((_, cb) => cb(), - ) + ); const verifySeedPhrase = background.verifySeedPhrase.callsFake((cb) => cb(), - ) + ); - actions._setBackgroundConnection(background) + actions._setBackgroundConnection(background); const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', value: undefined }, @@ -69,95 +69,95 @@ describe('Actions', function () { }, }, { type: 'HIDE_LOADING_INDICATION' }, - ] + ]; - await store.dispatch(actions.tryUnlockMetamask()) + await store.dispatch(actions.tryUnlockMetamask()); - assert(submitPassword.calledOnce) - assert(verifySeedPhrase.calledOnce) + assert(submitPassword.calledOnce); + assert(verifySeedPhrase.calledOnce); - assert.deepStrictEqual(store.getActions(), expectedActions) - }) + assert.deepStrictEqual(store.getActions(), expectedActions); + }); it('errors on submitPassword will fail', async function () { - const store = mockStore() + const store = mockStore(); - background.submitPassword.callsFake((_, cb) => cb(new Error('error'))) + background.submitPassword.callsFake((_, cb) => cb(new Error('error'))); - actions._setBackgroundConnection(background) + actions._setBackgroundConnection(background); const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', value: undefined }, { type: 'UNLOCK_IN_PROGRESS' }, { type: 'UNLOCK_FAILED', value: 'error' }, { type: 'HIDE_LOADING_INDICATION' }, - ] + ]; try { - await store.dispatch(actions.tryUnlockMetamask('test')) - assert.fail('Should have thrown error') + await store.dispatch(actions.tryUnlockMetamask('test')); + assert.fail('Should have thrown error'); } catch (_) { - assert.deepStrictEqual(store.getActions(), expectedActions) + assert.deepStrictEqual(store.getActions(), expectedActions); } - }) + }); it('displays warning error and unlock failed when verifySeed fails', async function () { - const store = mockStore() + const store = mockStore(); - background.submitPassword.callsFake((_, cb) => cb()) + background.submitPassword.callsFake((_, cb) => cb()); background.verifySeedPhrase.callsFake((cb) => { - cb(new Error('error')) - }) + cb(new Error('error')); + }); - actions._setBackgroundConnection(background) + actions._setBackgroundConnection(background); - const displayWarningError = [{ type: 'DISPLAY_WARNING', value: 'error' }] - const unlockFailedError = [{ type: 'UNLOCK_FAILED', value: 'error' }] + const displayWarningError = [{ type: 'DISPLAY_WARNING', value: 'error' }]; + const unlockFailedError = [{ type: 'UNLOCK_FAILED', value: 'error' }]; try { - await store.dispatch(actions.tryUnlockMetamask('test')) - assert.fail('Should have thrown error') + await store.dispatch(actions.tryUnlockMetamask('test')); + assert.fail('Should have thrown error'); } catch (_) { - const actions1 = store.getActions() + const actions1 = store.getActions(); const warning = actions1.filter( (action) => action.type === 'DISPLAY_WARNING', - ) + ); const unlockFailed = actions1.filter( (action) => action.type === 'UNLOCK_FAILED', - ) - assert.deepStrictEqual(warning, displayWarningError) - assert.deepStrictEqual(unlockFailed, unlockFailedError) + ); + assert.deepStrictEqual(warning, displayWarningError); + assert.deepStrictEqual(unlockFailed, unlockFailedError); } - }) - }) + }); + }); describe('#createNewVaultAndRestore', function () { afterEach(function () { - sinon.restore() - }) + sinon.restore(); + }); it('calls createNewVaultAndRestore', async function () { - const store = mockStore() + const store = mockStore(); const createNewVaultAndRestore = background.createNewVaultAndRestore.callsFake( (_, __, cb) => cb(), - ) + ); - background.unMarkPasswordForgotten.callsFake((cb) => cb()) + background.unMarkPasswordForgotten.callsFake((cb) => cb()); - actions._setBackgroundConnection(background) + actions._setBackgroundConnection(background); - await store.dispatch(actions.createNewVaultAndRestore()) - assert(createNewVaultAndRestore.calledOnce) - }) + await store.dispatch(actions.createNewVaultAndRestore()); + assert(createNewVaultAndRestore.calledOnce); + }); it('calls the expected actions', async function () { - const store = mockStore() + const store = mockStore(); - background.createNewVaultAndRestore.callsFake((_, __, cb) => cb()) - background.unMarkPasswordForgotten.callsFake((cb) => cb()) + background.createNewVaultAndRestore.callsFake((_, __, cb) => cb()); + background.unMarkPasswordForgotten.callsFake((cb) => cb()); - actions._setBackgroundConnection(background) + actions._setBackgroundConnection(background); const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', value: undefined }, @@ -171,102 +171,102 @@ describe('Actions', function () { }, { type: 'SHOW_ACCOUNTS_PAGE' }, { type: 'HIDE_LOADING_INDICATION' }, - ] + ]; - await store.dispatch(actions.createNewVaultAndRestore()) + await store.dispatch(actions.createNewVaultAndRestore()); - assert.deepStrictEqual(store.getActions(), expectedActions) - }) + assert.deepStrictEqual(store.getActions(), expectedActions); + }); it('errors when callback in createNewVaultAndRestore throws', async function () { - const store = mockStore() + const store = mockStore(); background.createNewVaultAndRestore.callsFake((_, __, cb) => cb(new Error('error')), - ) + ); - actions._setBackgroundConnection(background) + actions._setBackgroundConnection(background); const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', value: undefined }, { type: 'DISPLAY_WARNING', value: 'error' }, { type: 'HIDE_LOADING_INDICATION' }, - ] + ]; try { - await store.dispatch(actions.createNewVaultAndRestore()) - assert.fail('Should have thrown error') + await store.dispatch(actions.createNewVaultAndRestore()); + assert.fail('Should have thrown error'); } catch (_) { - assert.deepStrictEqual(store.getActions(), expectedActions) + assert.deepStrictEqual(store.getActions(), expectedActions); } - }) - }) + }); + }); describe('#requestRevealSeedWords', function () { afterEach(function () { - sinon.restore() - }) + sinon.restore(); + }); it('calls verifyPassword in background', async function () { - const store = mockStore() + const store = mockStore(); const verifyPassword = background.verifyPassword.callsFake((_, cb) => cb(), - ) + ); const verifySeedPhrase = background.verifySeedPhrase.callsFake((cb) => cb(), - ) + ); - actions._setBackgroundConnection(background) + actions._setBackgroundConnection(background); - await store.dispatch(actions.requestRevealSeedWords()) - assert(verifyPassword.calledOnce) - assert(verifySeedPhrase.calledOnce) - }) + await store.dispatch(actions.requestRevealSeedWords()); + assert(verifyPassword.calledOnce); + assert(verifySeedPhrase.calledOnce); + }); it('displays warning error message then callback in background errors', async function () { - const store = mockStore() + const store = mockStore(); - background.verifyPassword.callsFake((_, cb) => cb()) + background.verifyPassword.callsFake((_, cb) => cb()); background.verifySeedPhrase.callsFake((cb) => { - cb(new Error('error')) - }) + cb(new Error('error')); + }); - actions._setBackgroundConnection(background) + actions._setBackgroundConnection(background); const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', value: undefined }, { type: 'DISPLAY_WARNING', value: 'error' }, { type: 'HIDE_LOADING_INDICATION' }, - ] + ]; try { - await store.dispatch(actions.requestRevealSeedWords()) - assert.fail('Should have thrown error') + await store.dispatch(actions.requestRevealSeedWords()); + assert.fail('Should have thrown error'); } catch (_) { - assert.deepStrictEqual(store.getActions(), expectedActions) + assert.deepStrictEqual(store.getActions(), expectedActions); } - }) - }) + }); + }); describe('#removeAccount', function () { afterEach(function () { - sinon.restore() - }) + sinon.restore(); + }); it('calls removeAccount in background and expect actions to show account', async function () { - const store = mockStore() + const store = mockStore(); background.getState.callsFake((cb) => cb(null, { currentLocale: 'test', selectedAddress: '0xAnotherAddress', }), - ) + ); - const removeAccount = background.removeAccount.callsFake((_, cb) => cb()) + const removeAccount = background.removeAccount.callsFake((_, cb) => cb()); - actions._setBackgroundConnection(background) + actions._setBackgroundConnection(background); const expectedActions = [ 'SHOW_LOADING_INDICATION', @@ -274,122 +274,122 @@ describe('Actions', function () { 'UPDATE_METAMASK_STATE', 'HIDE_LOADING_INDICATION', 'SHOW_ACCOUNTS_PAGE', - ] + ]; await store.dispatch( actions.removeAccount('0xe18035bf8712672935fdb4e5e431b1a0183d2dfc'), - ) - assert(removeAccount.calledOnce) - const actionTypes = store.getActions().map((action) => action.type) - assert.deepStrictEqual(actionTypes, expectedActions) - }) + ); + assert(removeAccount.calledOnce); + const actionTypes = store.getActions().map((action) => action.type); + assert.deepStrictEqual(actionTypes, expectedActions); + }); it('displays warning error message when removeAccount callback errors', async function () { - const store = mockStore() + const store = mockStore(); background.removeAccount.callsFake((_, cb) => { - cb(new Error('error')) - }) + cb(new Error('error')); + }); - actions._setBackgroundConnection(background) + actions._setBackgroundConnection(background); const expectedActions = [ 'SHOW_LOADING_INDICATION', 'DISPLAY_WARNING', 'HIDE_LOADING_INDICATION', - ] + ]; try { await store.dispatch( actions.removeAccount('0xe18035bf8712672935fdb4e5e431b1a0183d2dfc'), - ) - assert.fail('Should have thrown error') + ); + assert.fail('Should have thrown error'); } catch (_) { - const actionTypes = store.getActions().map((action) => action.type) - assert.deepStrictEqual(actionTypes, expectedActions) + const actionTypes = store.getActions().map((action) => action.type); + assert.deepStrictEqual(actionTypes, expectedActions); } - }) - }) + }); + }); describe('#resetAccount', function () { afterEach(function () { - sinon.restore() - }) + sinon.restore(); + }); it('resets account', async function () { - const store = mockStore() + const store = mockStore(); - const resetAccount = background.resetAccount.callsFake((cb) => cb()) + const resetAccount = background.resetAccount.callsFake((cb) => cb()); - actions._setBackgroundConnection(background) + actions._setBackgroundConnection(background); const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', value: undefined }, { type: 'HIDE_LOADING_INDICATION' }, { type: 'SHOW_ACCOUNTS_PAGE' }, - ] + ]; - await store.dispatch(actions.resetAccount()) - assert(resetAccount.calledOnce) - assert.deepStrictEqual(store.getActions(), expectedActions) - }) + await store.dispatch(actions.resetAccount()); + assert(resetAccount.calledOnce); + assert.deepStrictEqual(store.getActions(), expectedActions); + }); it('throws if resetAccount throws', async function () { - const store = mockStore() + const store = mockStore(); background.resetAccount.callsFake((cb) => { - cb(new Error('error')) - }) + cb(new Error('error')); + }); - actions._setBackgroundConnection(background) + actions._setBackgroundConnection(background); const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', value: undefined }, { type: 'HIDE_LOADING_INDICATION' }, { type: 'DISPLAY_WARNING', value: 'error' }, - ] + ]; try { - await store.dispatch(actions.resetAccount()) - assert.fail('Should have thrown error') + await store.dispatch(actions.resetAccount()); + assert.fail('Should have thrown error'); } catch (_) { - assert.deepStrictEqual(store.getActions(), expectedActions) + assert.deepStrictEqual(store.getActions(), expectedActions); } - }) - }) + }); + }); describe('#importNewAccount', function () { afterEach(function () { - sinon.restore() - }) + sinon.restore(); + }); it('calls importAccountWithStrategies in background', async function () { - const store = mockStore() + const store = mockStore(); const importAccountWithStrategy = background.importAccountWithStrategy.callsFake( (_, __, cb) => { - cb() + cb(); }, - ) + ); - actions._setBackgroundConnection(background) + actions._setBackgroundConnection(background); await store.dispatch( actions.importNewAccount('Private Key', [ 'c87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3', ]), - ) - assert(importAccountWithStrategy.calledOnce) - }) + ); + assert(importAccountWithStrategy.calledOnce); + }); it('displays warning error message when importAccount in background callback errors', async function () { - const store = mockStore() + const store = mockStore(); background.importAccountWithStrategy.callsFake((_, __, cb) => cb(new Error('error')), - ) + ); - actions._setBackgroundConnection(background) + actions._setBackgroundConnection(background); const expectedActions = [ { @@ -398,169 +398,169 @@ describe('Actions', function () { }, { type: 'DISPLAY_WARNING', value: 'error' }, { type: 'HIDE_LOADING_INDICATION' }, - ] + ]; try { - await store.dispatch(actions.importNewAccount()) - assert.fail('Should have thrown error') + await store.dispatch(actions.importNewAccount()); + assert.fail('Should have thrown error'); } catch (_) { - assert.deepStrictEqual(store.getActions(), expectedActions) + assert.deepStrictEqual(store.getActions(), expectedActions); } - }) - }) + }); + }); describe('#addNewAccount', function () { it('Adds a new account', async function () { - const store = mockStore({ metamask: { identities: {} } }) + const store = mockStore({ metamask: { identities: {} } }); const addNewAccount = background.addNewAccount.callsFake((cb) => cb(null, { identities: {}, }), - ) + ); - actions._setBackgroundConnection(background) + actions._setBackgroundConnection(background); - await store.dispatch(actions.addNewAccount()) - assert(addNewAccount.calledOnce) - }) + await store.dispatch(actions.addNewAccount()); + assert(addNewAccount.calledOnce); + }); it('displays warning error message when addNewAccount in background callback errors', async function () { - const store = mockStore() + const store = mockStore(); background.addNewAccount.callsFake((cb) => { - cb(new Error('error')) - }) + cb(new Error('error')); + }); - actions._setBackgroundConnection(background) + actions._setBackgroundConnection(background); const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', value: undefined }, { type: 'DISPLAY_WARNING', value: 'error' }, { type: 'HIDE_LOADING_INDICATION' }, - ] + ]; try { - await store.dispatch(actions.addNewAccount()) - assert.fail('Should have thrown error') + await store.dispatch(actions.addNewAccount()); + assert.fail('Should have thrown error'); } catch (_) { - assert.deepStrictEqual(store.getActions(), expectedActions) + assert.deepStrictEqual(store.getActions(), expectedActions); } - }) - }) + }); + }); describe('#checkHardwareStatus', function () { afterEach(function () { - sinon.restore() - }) + sinon.restore(); + }); it('calls checkHardwareStatus in background', async function () { - const store = mockStore() + const store = mockStore(); const checkHardwareStatus = background.checkHardwareStatus.callsFake( (_, __, cb) => { - cb() + cb(); }, - ) + ); - actions._setBackgroundConnection(background) + actions._setBackgroundConnection(background); await store.dispatch( actions.checkHardwareStatus('ledger', `m/44'/60'/0'/0`), - ) - assert.strictEqual(checkHardwareStatus.calledOnce, true) - }) + ); + assert.strictEqual(checkHardwareStatus.calledOnce, true); + }); it('shows loading indicator and displays error', async function () { - const store = mockStore() + const store = mockStore(); background.checkHardwareStatus.callsFake((_, __, cb) => cb(new Error('error')), - ) + ); - actions._setBackgroundConnection(background) + actions._setBackgroundConnection(background); const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', value: undefined }, { type: 'DISPLAY_WARNING', value: 'error' }, { type: 'HIDE_LOADING_INDICATION' }, - ] + ]; try { - await store.dispatch(actions.checkHardwareStatus()) - assert.fail('Should have thrown error') + await store.dispatch(actions.checkHardwareStatus()); + assert.fail('Should have thrown error'); } catch (_) { - assert.deepStrictEqual(store.getActions(), expectedActions) + assert.deepStrictEqual(store.getActions(), expectedActions); } - }) - }) + }); + }); describe('#forgetDevice', function () { afterEach(function () { - sinon.restore() - }) + sinon.restore(); + }); it('calls forgetDevice in background', async function () { - const store = mockStore() + const store = mockStore(); - const forgetDevice = background.forgetDevice.callsFake((_, cb) => cb()) + const forgetDevice = background.forgetDevice.callsFake((_, cb) => cb()); - actions._setBackgroundConnection(background) + actions._setBackgroundConnection(background); - await store.dispatch(actions.forgetDevice('ledger')) - assert(forgetDevice.calledOnce) - }) + await store.dispatch(actions.forgetDevice('ledger')); + assert(forgetDevice.calledOnce); + }); it('shows loading indicator and displays error', async function () { - const store = mockStore() + const store = mockStore(); - background.forgetDevice.callsFake((_, cb) => cb(new Error('error'))) + background.forgetDevice.callsFake((_, cb) => cb(new Error('error'))); - actions._setBackgroundConnection(background) + actions._setBackgroundConnection(background); const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', value: undefined }, { type: 'DISPLAY_WARNING', value: 'error' }, { type: 'HIDE_LOADING_INDICATION' }, - ] + ]; try { - await store.dispatch(actions.forgetDevice()) - assert.fail('Should have thrown error') + await store.dispatch(actions.forgetDevice()); + assert.fail('Should have thrown error'); } catch (_) { - assert.deepStrictEqual(store.getActions(), expectedActions) + assert.deepStrictEqual(store.getActions(), expectedActions); } - }) - }) + }); + }); describe('#connectHardware', function () { afterEach(function () { - sinon.restore() - }) + sinon.restore(); + }); it('calls connectHardware in background', async function () { - const store = mockStore() + const store = mockStore(); const connectHardware = background.connectHardware.callsFake( (_, __, ___, cb) => cb(), - ) + ); - actions._setBackgroundConnection(background) + actions._setBackgroundConnection(background); await store.dispatch( actions.connectHardware('ledger', 0, `m/44'/60'/0'/0`), - ) - assert(connectHardware.calledOnce) - }) + ); + assert(connectHardware.calledOnce); + }); it('shows loading indicator and displays error', async function () { - const store = mockStore() + const store = mockStore(); background.connectHardware.callsFake((_, __, ___, cb) => cb(new Error('error')), - ) + ); - actions._setBackgroundConnection(background) + actions._setBackgroundConnection(background); const expectedActions = [ { @@ -569,67 +569,67 @@ describe('Actions', function () { }, { type: 'DISPLAY_WARNING', value: 'error' }, { type: 'HIDE_LOADING_INDICATION' }, - ] + ]; try { - await store.dispatch(actions.connectHardware('ledger')) - assert.fail('Should have thrown error') + await store.dispatch(actions.connectHardware('ledger')); + assert.fail('Should have thrown error'); } catch (_) { - assert.deepStrictEqual(store.getActions(), expectedActions) + assert.deepStrictEqual(store.getActions(), expectedActions); } - }) - }) + }); + }); describe('#unlockHardwareWalletAccount', function () { afterEach(function () { - sinon.restore() - }) + sinon.restore(); + }); it('calls unlockHardwareWalletAccount in background', async function () { - const store = mockStore() + const store = mockStore(); const unlockHardwareWalletAccount = background.unlockHardwareWalletAccount.callsFake( (_, __, ___, cb) => cb(), - ) + ); - actions._setBackgroundConnection(background) + actions._setBackgroundConnection(background); await store.dispatch( actions.unlockHardwareWalletAccount('ledger', 0, `m/44'/60'/0'/0`), - ) - assert(unlockHardwareWalletAccount.calledOnce) - }) + ); + assert(unlockHardwareWalletAccount.calledOnce); + }); it('shows loading indicator and displays error', async function () { - const store = mockStore() + const store = mockStore(); background.unlockHardwareWalletAccount.callsFake((_, __, ___, cb) => cb(new Error('error')), - ) + ); - actions._setBackgroundConnection(background) + actions._setBackgroundConnection(background); const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', value: undefined }, { type: 'HIDE_LOADING_INDICATION' }, { type: 'DISPLAY_WARNING', value: 'error' }, - ] + ]; try { - await store.dispatch(actions.unlockHardwareWalletAccount()) - assert.fail('Should have thrown error') + await store.dispatch(actions.unlockHardwareWalletAccount()); + assert.fail('Should have thrown error'); } catch (error) { - assert.deepStrictEqual(store.getActions(), expectedActions) + assert.deepStrictEqual(store.getActions(), expectedActions); } - }) - }) + }); + }); describe('#setCurrentCurrency', function () { afterEach(function () { - sinon.restore() - }) + sinon.restore(); + }); it('calls setCurrentCurrency', async function () { - const store = mockStore() + const store = mockStore(); const setCurrentCurrency = background.setCurrentCurrency.callsFake( (_, cb) => cb(null, { @@ -637,31 +637,33 @@ describe('Actions', function () { conversionRate: 100, conversionDate: 1611839083653, }), - ) + ); - actions._setBackgroundConnection(background) + actions._setBackgroundConnection(background); - await store.dispatch(actions.setCurrentCurrency('jpy')) - assert(setCurrentCurrency.calledOnce) - }) + await store.dispatch(actions.setCurrentCurrency('jpy')); + assert(setCurrentCurrency.calledOnce); + }); it('throws if setCurrentCurrency throws', async function () { - const store = mockStore() + const store = mockStore(); - background.setCurrentCurrency.callsFake((_, cb) => cb(new Error('error'))) + background.setCurrentCurrency.callsFake((_, cb) => + cb(new Error('error')), + ); - actions._setBackgroundConnection(background) + actions._setBackgroundConnection(background); const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', value: undefined }, { type: 'DISPLAY_WARNING', value: 'error' }, { type: 'HIDE_LOADING_INDICATION' }, - ] + ]; - await store.dispatch(actions.setCurrentCurrency()) - assert.deepStrictEqual(store.getActions(), expectedActions) - }) - }) + await store.dispatch(actions.setCurrentCurrency()); + assert.deepStrictEqual(store.getActions(), expectedActions); + }); + }); describe('#signMsg', function () { const msgParams = { @@ -669,94 +671,94 @@ describe('Actions', function () { from: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc', data: '0x879a053d4800c6354e76c7985a865d2922c82fb5b3f4577b2fe08b998954f2e0', - } + }; afterEach(function () { - sinon.restore() - }) + sinon.restore(); + }); it('calls signMsg in background', async function () { - const store = mockStore() + const store = mockStore(); const signMessage = background.signMessage.callsFake((_, cb) => cb(null, defaultState), - ) + ); - actions._setBackgroundConnection(background) + actions._setBackgroundConnection(background); - await store.dispatch(actions.signMsg(msgParams)) - assert(signMessage.calledOnce) - }) + await store.dispatch(actions.signMsg(msgParams)); + assert(signMessage.calledOnce); + }); it('errors when signMessage in background throws', async function () { - const store = mockStore() + const store = mockStore(); - background.signMessage.callsFake((_, cb) => cb(new Error('error'))) + background.signMessage.callsFake((_, cb) => cb(new Error('error'))); - actions._setBackgroundConnection(background) + actions._setBackgroundConnection(background); const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', value: undefined }, { type: 'DISPLAY_WARNING', value: 'error' }, { type: 'HIDE_LOADING_INDICATION' }, - ] + ]; try { - await store.dispatch(actions.signMsg(msgParams)) - assert.fail('Should have thrown error') + await store.dispatch(actions.signMsg(msgParams)); + assert.fail('Should have thrown error'); } catch (_) { - assert.deepStrictEqual(store.getActions(), expectedActions) + assert.deepStrictEqual(store.getActions(), expectedActions); } - }) - }) + }); + }); describe('#signPersonalMsg', function () { const msgParams = { from: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc', data: '0x879a053d4800c6354e76c7985a865d2922c82fb5b3f4577b2fe08b998954f2e0', - } + }; afterEach(function () { - sinon.restore() - }) + sinon.restore(); + }); it('calls signPersonalMessage', async function () { - const store = mockStore() + const store = mockStore(); const signPersonalMessage = background.signPersonalMessage.callsFake( (_, cb) => cb(null, defaultState), - ) + ); - actions._setBackgroundConnection(background) + actions._setBackgroundConnection(background); - await store.dispatch(actions.signPersonalMsg(msgParams)) - assert(signPersonalMessage.calledOnce) - }) + await store.dispatch(actions.signPersonalMsg(msgParams)); + assert(signPersonalMessage.calledOnce); + }); it('throws if signPersonalMessage throws', async function () { - const store = mockStore() + const store = mockStore(); background.signPersonalMessage.callsFake((_, cb) => { - cb(new Error('error')) - }) + cb(new Error('error')); + }); - actions._setBackgroundConnection(background) + actions._setBackgroundConnection(background); const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', value: undefined }, { type: 'DISPLAY_WARNING', value: 'error' }, { type: 'HIDE_LOADING_INDICATION' }, - ] + ]; try { - await store.dispatch(actions.signPersonalMsg(msgParams)) - assert.fail('Should have thrown error') + await store.dispatch(actions.signPersonalMsg(msgParams)); + assert.fail('Should have thrown error'); } catch (_) { - assert.deepEqual(store.getActions(), expectedActions) + assert.deepEqual(store.getActions(), expectedActions); } - }) - }) + }); + }); describe('#signTypedMsg', function () { const msgParamsV3 = { @@ -797,83 +799,83 @@ describe('Actions', function () { contents: 'Hello, Bob!', }, }), - } + }; afterEach(function () { - sinon.restore() - }) + sinon.restore(); + }); it('calls signTypedMsg in background with no error', async function () { - const store = mockStore() + const store = mockStore(); const signTypedMsg = background.signTypedMessage.callsFake((_, cb) => cb(null, defaultState), - ) + ); - actions._setBackgroundConnection(background) + actions._setBackgroundConnection(background); - await store.dispatch(actions.signTypedMsg(msgParamsV3)) - assert(signTypedMsg.calledOnce) - }) + await store.dispatch(actions.signTypedMsg(msgParamsV3)); + assert(signTypedMsg.calledOnce); + }); it('returns expected actions with error', async function () { - const store = mockStore() + const store = mockStore(); - background.signTypedMessage.callsFake((_, cb) => cb(new Error('error'))) + background.signTypedMessage.callsFake((_, cb) => cb(new Error('error'))); - actions._setBackgroundConnection(background) + actions._setBackgroundConnection(background); const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', value: undefined }, { type: 'DISPLAY_WARNING', value: 'error' }, { type: 'HIDE_LOADING_INDICATION' }, - ] + ]; try { - await store.dispatch(actions.signTypedMsg()) - assert.fail('Should have thrown error') + await store.dispatch(actions.signTypedMsg()); + assert.fail('Should have thrown error'); } catch (_) { - assert.deepStrictEqual(store.getActions(), expectedActions) + assert.deepStrictEqual(store.getActions(), expectedActions); } - }) - }) + }); + }); describe('#signTx', function () { - let sendTransaction + let sendTransaction; beforeEach(function () { - sendTransaction = sinon.stub(global.ethQuery, 'sendTransaction') - }) + sendTransaction = sinon.stub(global.ethQuery, 'sendTransaction'); + }); afterEach(function () { - sendTransaction.restore() - }) + sendTransaction.restore(); + }); it('calls sendTransaction in global ethQuery', function () { - const store = mockStore() + const store = mockStore(); - store.dispatch(actions.signTx()) - assert(sendTransaction.calledOnce) - }) + store.dispatch(actions.signTx()); + assert(sendTransaction.calledOnce); + }); it('errors in when sendTransaction throws', function () { - const store = mockStore() + const store = mockStore(); const expectedActions = [ { type: 'DISPLAY_WARNING', value: 'error' }, { type: 'SHOW_CONF_TX_PAGE', id: undefined }, - ] + ]; sendTransaction.callsFake((_, callback) => { - callback(new Error('error')) - }) + callback(new Error('error')); + }); - store.dispatch(actions.signTx()) - assert.deepStrictEqual(store.getActions(), expectedActions) - }) - }) + store.dispatch(actions.signTx()); + assert.deepStrictEqual(store.getActions(), expectedActions); + }); + }); describe('#updatedGasData', function () { it('errors when get code does not return', async function () { - const store = mockStore() + const store = mockStore(); const expectedActions = [ { type: 'GAS_LOADING_STARTED' }, @@ -882,7 +884,7 @@ describe('Actions', function () { value: { gasLoadingError: 'gasLoadingError' }, }, { type: 'GAS_LOADING_FINISHED' }, - ] + ]; const mockData = { gasPrice: '0x3b9aca00', // @@ -890,15 +892,15 @@ describe('Actions', function () { selectedAddress: '0x0DCD5D886577d5081B0c52e242Ef29E70Be3E7bc', to: '0xEC1Adf982415D2Ef5ec55899b9Bfb8BC0f29251B', value: '0xde0b6b3a7640000', // 1000000000000000000 - } + }; try { - await store.dispatch(actions.updateGasData(mockData)) - assert.fail('Should have thrown error') + await store.dispatch(actions.updateGasData(mockData)); + assert.fail('Should have thrown error'); } catch (error) { - assert.deepStrictEqual(store.getActions(), expectedActions) + assert.deepStrictEqual(store.getActions(), expectedActions); } - }) + }); it('returns default gas limit for basic eth transaction', async function () { const mockData = { @@ -907,12 +909,12 @@ describe('Actions', function () { selectedAddress: '0x0DCD5D886577d5081B0c52e242Ef29E70Be3E7bc', to: '0xEC1Adf982415D2Ef5ec55899b9Bfb8BC0f29251B', value: '0xde0b6b3a7640000', // 1000000000000000000 - } + }; global.eth = { getCode: sinon.stub().returns('0x'), - } - const store = mockStore() + }; + const store = mockStore(); const expectedActions = [ { type: 'GAS_LOADING_STARTED' }, @@ -920,24 +922,24 @@ describe('Actions', function () { { type: 'metamask/gas/SET_CUSTOM_GAS_LIMIT', value: '0x5208' }, { type: 'UPDATE_SEND_ERRORS', value: { gasLoadingError: null } }, { type: 'GAS_LOADING_FINISHED' }, - ] + ]; - await store.dispatch(actions.updateGasData(mockData)) - assert.deepStrictEqual(store.getActions(), expectedActions) - global.eth.getCode.reset() - }) - }) + await store.dispatch(actions.updateGasData(mockData)); + assert.deepStrictEqual(store.getActions(), expectedActions); + global.eth.getCode.reset(); + }); + }); describe('#signTokenTx', function () { it('calls eth.contract', function () { - global.eth = new Eth(provider) - const tokenSpy = sinon.spy(global.eth, 'contract') - const store = mockStore() - store.dispatch(actions.signTokenTx()) - assert(tokenSpy.calledOnce) - tokenSpy.restore() - }) - }) + global.eth = new Eth(provider); + const tokenSpy = sinon.spy(global.eth, 'contract'); + const store = mockStore(); + store.dispatch(actions.signTokenTx()); + assert(tokenSpy.calledOnce); + tokenSpy.restore(); + }); + }); describe('#updateTransaction', function () { const txParams = { @@ -946,23 +948,23 @@ describe('Actions', function () { gasPrice: '0x3b9aca00', to: '0x2', value: '0x0', - } + }; const txData = { id: '1', status: TRANSACTION_STATUSES.UNAPPROVED, metamaskNetworkId: currentNetworkId, txParams, - } + }; afterEach(function () { - sinon.restore() - }) + sinon.restore(); + }); it('updates transaction', async function () { - const store = mockStore() + const store = mockStore(); - const updateTransactionStub = sinon.stub().callsFake((_, cb) => cb()) + const updateTransactionStub = sinon.stub().callsFake((_, cb) => cb()); background.getApi.returns({ updateTransaction: updateTransactionStub, @@ -972,27 +974,27 @@ describe('Actions', function () { selectedAddress: '0xFirstAddress', }), ), - }) + }); - actions._setBackgroundConnection(background.getApi()) + actions._setBackgroundConnection(background.getApi()); - await store.dispatch(actions.updateTransaction(txData)) + await store.dispatch(actions.updateTransaction(txData)); - const resultantActions = store.getActions() - assert(updateTransactionStub.calledOnce) + const resultantActions = store.getActions(); + assert(updateTransactionStub.calledOnce); assert.deepStrictEqual(resultantActions[1], { type: 'UPDATE_TRANSACTION_PARAMS', id: txData.id, value: txParams, - }) - }) + }); + }); it('rejects with error message', async function () { - const store = mockStore() + const store = mockStore(); background.getApi.returns({ updateTransaction: (_, callback) => { - callback(new Error('error')) + callback(new Error('error')); }, getState: sinon.stub().callsFake((cb) => cb(null, { @@ -1000,198 +1002,198 @@ describe('Actions', function () { selectedAddress: '0xFirstAddress', }), ), - }) + }); - actions._setBackgroundConnection(background.getApi()) + actions._setBackgroundConnection(background.getApi()); try { - await store.dispatch(actions.updateTransaction(txData)) - assert.fail('Should have thrown error') + await store.dispatch(actions.updateTransaction(txData)); + assert.fail('Should have thrown error'); } catch (error) { - assert.strictEqual(error.message, 'error') + assert.strictEqual(error.message, 'error'); } - }) - }) + }); + }); describe('#lockMetamask', function () { afterEach(function () { - sinon.restore() - }) + sinon.restore(); + }); it('calls setLocked', async function () { - const store = mockStore() + const store = mockStore(); - const backgroundSetLocked = background.setLocked.callsFake((cb) => cb()) + const backgroundSetLocked = background.setLocked.callsFake((cb) => cb()); - actions._setBackgroundConnection(background) + actions._setBackgroundConnection(background); - await store.dispatch(actions.lockMetamask()) - assert(backgroundSetLocked.calledOnce) - }) + await store.dispatch(actions.lockMetamask()); + assert(backgroundSetLocked.calledOnce); + }); it('returns display warning error with value when setLocked in background callback errors', async function () { - const store = mockStore() + const store = mockStore(); background.setLocked.callsFake((cb) => { - cb(new Error('error')) - }) + cb(new Error('error')); + }); - actions._setBackgroundConnection(background) + actions._setBackgroundConnection(background); const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', value: undefined }, { type: 'DISPLAY_WARNING', value: 'error' }, { type: 'HIDE_LOADING_INDICATION' }, { type: 'LOCK_METAMASK' }, - ] + ]; try { - await store.dispatch(actions.lockMetamask()) - assert.fail('Should have thrown error') + await store.dispatch(actions.lockMetamask()); + assert.fail('Should have thrown error'); } catch (error) { - assert.deepStrictEqual(store.getActions(), expectedActions) + assert.deepStrictEqual(store.getActions(), expectedActions); } - }) - }) + }); + }); describe('#setSelectedAddress', function () { afterEach(function () { - sinon.restore() - }) + sinon.restore(); + }); it('calls setSelectedAddress in background', async function () { - const store = mockStore() + const store = mockStore(); - const setSelectedAddressSpy = sinon.stub().callsFake((_, cb) => cb()) + const setSelectedAddressSpy = sinon.stub().callsFake((_, cb) => cb()); background.getApi.returns({ setSelectedAddress: setSelectedAddressSpy, - }) + }); - actions._setBackgroundConnection(background.getApi()) + actions._setBackgroundConnection(background.getApi()); await store.dispatch( actions.setSelectedAddress( '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc', ), - ) - assert(setSelectedAddressSpy.calledOnce) - }) + ); + assert(setSelectedAddressSpy.calledOnce); + }); it('errors when setSelectedAddress throws', async function () { - const store = mockStore() + const store = mockStore(); const setSelectedAddressSpy = sinon .stub() - .callsFake((_, cb) => cb(new Error('error'))) + .callsFake((_, cb) => cb(new Error('error'))); background.getApi.returns({ setSelectedAddress: setSelectedAddressSpy, - }) + }); - actions._setBackgroundConnection(background.getApi()) + actions._setBackgroundConnection(background.getApi()); const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', value: undefined }, { type: 'DISPLAY_WARNING', value: 'error' }, { type: 'HIDE_LOADING_INDICATION' }, - ] + ]; - await store.dispatch(actions.setSelectedAddress()) - assert.deepStrictEqual(store.getActions(), expectedActions) - }) - }) + await store.dispatch(actions.setSelectedAddress()); + assert.deepStrictEqual(store.getActions(), expectedActions); + }); + }); describe('#showAccountDetail', function () { afterEach(function () { - sinon.restore() - }) + sinon.restore(); + }); it('#showAccountDetail', async function () { const store = mockStore({ activeTab: {}, metamask: { alertEnabledness: {}, selectedAddress: '0x123' }, - }) + }); - const setSelectedAddressSpy = sinon.stub().callsFake((_, cb) => cb()) + const setSelectedAddressSpy = sinon.stub().callsFake((_, cb) => cb()); background.getApi.returns({ setSelectedAddress: setSelectedAddressSpy, - }) + }); - actions._setBackgroundConnection(background.getApi()) + actions._setBackgroundConnection(background.getApi()); - await store.dispatch(actions.showAccountDetail()) - assert(setSelectedAddressSpy.calledOnce) - }) + await store.dispatch(actions.showAccountDetail()); + assert(setSelectedAddressSpy.calledOnce); + }); it('displays warning if setSelectedAddress throws', async function () { const store = mockStore({ activeTab: {}, metamask: { alertEnabledness: {}, selectedAddress: '0x123' }, - }) + }); const setSelectedAddressSpy = sinon .stub() - .callsFake((_, cb) => cb(new Error('error'))) + .callsFake((_, cb) => cb(new Error('error'))); background.getApi.returns({ setSelectedAddress: setSelectedAddressSpy, - }) + }); - actions._setBackgroundConnection(background.getApi()) + actions._setBackgroundConnection(background.getApi()); const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', value: undefined }, { type: 'DISPLAY_WARNING', value: 'error' }, { type: 'HIDE_LOADING_INDICATION' }, - ] + ]; - await store.dispatch(actions.showAccountDetail()) - assert.deepStrictEqual(store.getActions(), expectedActions) - }) - }) + await store.dispatch(actions.showAccountDetail()); + assert.deepStrictEqual(store.getActions(), expectedActions); + }); + }); describe('#addToken', function () { afterEach(function () { - sinon.restore() - }) + sinon.restore(); + }); it('calls addToken in background', async function () { - const store = mockStore() + const store = mockStore(); const addTokenStub = sinon .stub() - .callsFake((_, __, ___, ____, cb) => cb()) + .callsFake((_, __, ___, ____, cb) => cb()); background.getApi.returns({ addToken: addTokenStub, - }) + }); - actions._setBackgroundConnection(background.getApi()) + actions._setBackgroundConnection(background.getApi()); - await store.dispatch(actions.addToken()) - assert(addTokenStub.calledOnce) - }) + await store.dispatch(actions.addToken()); + assert(addTokenStub.calledOnce); + }); it('expected actions', async function () { - const store = mockStore() + const store = mockStore(); const tokenDetails = { address: 'tokenAddress', symbol: 'token', decimal: 18, - } + }; const addTokenStub = sinon .stub() - .callsFake((_, __, ___, ____, cb) => cb(null, tokenDetails)) + .callsFake((_, __, ___, ____, cb) => cb(null, tokenDetails)); background.getApi.returns({ addToken: addTokenStub, - }) + }); - actions._setBackgroundConnection(background.getApi()) + actions._setBackgroundConnection(background.getApi()); const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', value: undefined }, @@ -1200,201 +1202,201 @@ describe('Actions', function () { type: 'UPDATE_TOKENS', newTokens: tokenDetails, }, - ] + ]; - await store.dispatch(actions.addToken()) + await store.dispatch(actions.addToken()); - assert.deepStrictEqual(store.getActions(), expectedActions) - }) + assert.deepStrictEqual(store.getActions(), expectedActions); + }); it('errors when addToken in background throws', async function () { - const store = mockStore() + const store = mockStore(); const addTokenStub = sinon .stub() - .callsFake((_, __, ___, ____, cb) => cb(new Error('error'))) + .callsFake((_, __, ___, ____, cb) => cb(new Error('error'))); background.getApi.returns({ addToken: addTokenStub, - }) + }); - actions._setBackgroundConnection(background.getApi()) + actions._setBackgroundConnection(background.getApi()); const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', value: undefined }, { type: 'HIDE_LOADING_INDICATION' }, { type: 'DISPLAY_WARNING', value: 'error' }, - ] + ]; try { - await store.dispatch(actions.addToken()) - assert.fail('Should have thrown error') + await store.dispatch(actions.addToken()); + assert.fail('Should have thrown error'); } catch (_) { - assert.deepEqual(store.getActions(), expectedActions) + assert.deepEqual(store.getActions(), expectedActions); } - }) - }) + }); + }); describe('#removeToken', function () { afterEach(function () { - sinon.restore() - }) + sinon.restore(); + }); it('calls removeToken in background', async function () { - const store = mockStore() + const store = mockStore(); - const removeTokenStub = sinon.stub().callsFake((_, cb) => cb()) + const removeTokenStub = sinon.stub().callsFake((_, cb) => cb()); background.getApi.returns({ removeToken: removeTokenStub, - }) + }); - actions._setBackgroundConnection(background.getApi()) + actions._setBackgroundConnection(background.getApi()); - await store.dispatch(actions.removeToken()) - assert(removeTokenStub.calledOnce) - }) + await store.dispatch(actions.removeToken()); + assert(removeTokenStub.calledOnce); + }); it('errors when removeToken in background fails', async function () { - const store = mockStore() + const store = mockStore(); background.getApi.returns({ removeToken: sinon.stub().callsFake((_, cb) => cb(new Error('error'))), - }) + }); - actions._setBackgroundConnection(background.getApi()) + actions._setBackgroundConnection(background.getApi()); const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', value: undefined }, { type: 'HIDE_LOADING_INDICATION' }, { type: 'DISPLAY_WARNING', value: 'error' }, - ] + ]; try { - await store.dispatch(actions.removeToken()) - assert.fail('Should have thrown error') + await store.dispatch(actions.removeToken()); + assert.fail('Should have thrown error'); } catch (_) { - assert.deepStrictEqual(store.getActions(), expectedActions) + assert.deepStrictEqual(store.getActions(), expectedActions); } - }) - }) + }); + }); describe('#setProviderType', function () { afterEach(function () { - sinon.restore() - }) + sinon.restore(); + }); it('calls setProviderType', async function () { - const store = mockStore() + const store = mockStore(); - const setProviderTypeStub = sinon.stub().callsFake((_, cb) => cb()) + const setProviderTypeStub = sinon.stub().callsFake((_, cb) => cb()); background.getApi.returns({ setProviderType: setProviderTypeStub, - }) + }); - actions._setBackgroundConnection(background.getApi()) + actions._setBackgroundConnection(background.getApi()); - await store.dispatch(actions.setProviderType()) - assert(setProviderTypeStub.calledOnce) - }) + await store.dispatch(actions.setProviderType()); + assert(setProviderTypeStub.calledOnce); + }); it('displays warning when setProviderType throws', async function () { - const store = mockStore() + const store = mockStore(); background.getApi.returns({ setProviderType: sinon .stub() .callsFake((_, cb) => cb(new Error('error'))), - }) + }); - actions._setBackgroundConnection(background.getApi()) + actions._setBackgroundConnection(background.getApi()); const expectedActions = [ { type: 'DISPLAY_WARNING', value: 'Had a problem changing networks!' }, - ] + ]; - await store.dispatch(actions.setProviderType()) - assert.deepStrictEqual(store.getActions(), expectedActions) - }) - }) + await store.dispatch(actions.setProviderType()); + assert.deepStrictEqual(store.getActions(), expectedActions); + }); + }); describe('#setRpcTarget', function () { afterEach(function () { - sinon.restore() - }) + sinon.restore(); + }); it('calls setRpcTarget', async function () { - const store = mockStore() + const store = mockStore(); - background.setCustomRpc.callsFake((_, __, ___, ____, cb) => cb()) + background.setCustomRpc.callsFake((_, __, ___, ____, cb) => cb()); - actions._setBackgroundConnection(background) + actions._setBackgroundConnection(background); - await store.dispatch(actions.setRpcTarget('http://localhost:8545')) - assert(background.setCustomRpc.calledOnce) - }) + await store.dispatch(actions.setRpcTarget('http://localhost:8545')); + assert(background.setCustomRpc.calledOnce); + }); it('displays warning when setRpcTarget throws', async function () { - const store = mockStore() + const store = mockStore(); background.setCustomRpc.callsFake((_, __, ___, ____, cb) => cb(new Error('error')), - ) + ); - actions._setBackgroundConnection(background) + actions._setBackgroundConnection(background); const expectedActions = [ { type: 'DISPLAY_WARNING', value: 'Had a problem changing networks!' }, - ] + ]; - await store.dispatch(actions.setRpcTarget()) - assert.deepStrictEqual(store.getActions(), expectedActions) - }) - }) + await store.dispatch(actions.setRpcTarget()); + assert.deepStrictEqual(store.getActions(), expectedActions); + }); + }); describe('#addToAddressBook', function () { it('calls setAddressBook', async function () { - const store = mockStore() + const store = mockStore(); const setAddressBookStub = sinon .stub() - .callsFake((_, __, ___, ____, cb) => cb()) + .callsFake((_, __, ___, ____, cb) => cb()); background.getApi.returns({ setAddressBook: setAddressBookStub, - }) + }); - actions._setBackgroundConnection(background.getApi()) + actions._setBackgroundConnection(background.getApi()); - await store.dispatch(actions.addToAddressBook('test')) - assert(setAddressBookStub.calledOnce) - sinon.restore() - }) - }) + await store.dispatch(actions.addToAddressBook('test')); + assert(setAddressBookStub.calledOnce); + sinon.restore(); + }); + }); describe('#exportAccount', function () { afterEach(function () { - sinon.restore() - }) + sinon.restore(); + }); it('returns expected actions for successful action', async function () { - const store = mockStore() + const store = mockStore(); - const testPrivKey = 'a-test-priv-key' + const testPrivKey = 'a-test-priv-key'; - const verifyPasswordStub = sinon.stub().callsFake((_, cb) => cb()) + const verifyPasswordStub = sinon.stub().callsFake((_, cb) => cb()); const exportAccountStub = sinon .stub() - .callsFake((_, cb) => cb(null, testPrivKey)) + .callsFake((_, cb) => cb(null, testPrivKey)); background.getApi.returns({ verifyPassword: verifyPasswordStub, exportAccount: exportAccountStub, - }) + }); - actions._setBackgroundConnection(background.getApi()) + actions._setBackgroundConnection(background.getApi()); const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', value: undefined }, @@ -1403,60 +1405,60 @@ describe('Actions', function () { type: 'SHOW_PRIVATE_KEY', value: testPrivKey, }, - ] + ]; await store.dispatch( actions.exportAccount('a-test-password', '0xAddress'), - ) - assert(verifyPasswordStub.calledOnce) - assert(exportAccountStub.calledOnce) - assert.deepStrictEqual(store.getActions(), expectedActions) - }) + ); + assert(verifyPasswordStub.calledOnce); + assert(exportAccountStub.calledOnce); + assert.deepStrictEqual(store.getActions(), expectedActions); + }); it('returns action errors when first func callback errors', async function () { - const store = mockStore() + const store = mockStore(); const verifyPasswordStub = sinon .stub() - .callsFake((_, cb) => cb(new Error('error'))) + .callsFake((_, cb) => cb(new Error('error'))); background.getApi.returns({ verifyPassword: verifyPasswordStub, - }) + }); - actions._setBackgroundConnection(background.getApi()) + actions._setBackgroundConnection(background.getApi()); const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', value: undefined }, { type: 'HIDE_LOADING_INDICATION' }, { type: 'DISPLAY_WARNING', value: 'Incorrect Password.' }, - ] + ]; try { await store.dispatch( actions.exportAccount('a-test-password', '0xAddress'), - ) - assert.fail('Should have thrown error') + ); + assert.fail('Should have thrown error'); } catch (_) { - assert.deepStrictEqual(store.getActions(), expectedActions) + assert.deepStrictEqual(store.getActions(), expectedActions); } - }) + }); it('returns action errors when second func callback errors', async function () { - const store = mockStore() + const store = mockStore(); - const verifyPasswordStub = sinon.stub().callsFake((_, cb) => cb()) + const verifyPasswordStub = sinon.stub().callsFake((_, cb) => cb()); const exportAccountStub = sinon .stub() - .callsFake((_, cb) => cb(new Error('error'))) + .callsFake((_, cb) => cb(new Error('error'))); background.getApi.returns({ verifyPassword: verifyPasswordStub, exportAccount: exportAccountStub, - }) + }); - actions._setBackgroundConnection(background.getApi()) + actions._setBackgroundConnection(background.getApi()); const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', value: undefined }, @@ -1465,60 +1467,60 @@ describe('Actions', function () { type: 'DISPLAY_WARNING', value: 'Had a problem exporting the account.', }, - ] + ]; try { await store.dispatch( actions.exportAccount('a-test-password', '0xAddress'), - ) - assert.fail('Should have thrown error') + ); + assert.fail('Should have thrown error'); } catch (_) { - assert.deepStrictEqual(store.getActions(), expectedActions) + assert.deepStrictEqual(store.getActions(), expectedActions); } - }) - }) + }); + }); describe('#setAccountLabel', function () { afterEach(function () { - sinon.restore() - }) + sinon.restore(); + }); it('calls setAccountLabel', async function () { - const store = mockStore() + const store = mockStore(); - const setAccountLabelStub = sinon.stub().callsFake((_, __, cb) => cb()) + const setAccountLabelStub = sinon.stub().callsFake((_, __, cb) => cb()); background.getApi.returns({ setAccountLabel: setAccountLabelStub, - }) + }); - actions._setBackgroundConnection(background.getApi()) + actions._setBackgroundConnection(background.getApi()); await store.dispatch( actions.setAccountLabel( '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc', 'test', ), - ) - assert(setAccountLabelStub.calledOnce) - }) + ); + assert(setAccountLabelStub.calledOnce); + }); it('returns action errors when func callback errors', async function () { - const store = mockStore() + const store = mockStore(); background.getApi.returns({ setAccountLabel: sinon .stub() .callsFake((_, __, cb) => cb(new Error('error'))), - }) + }); - actions._setBackgroundConnection(background.getApi()) + actions._setBackgroundConnection(background.getApi()); const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', value: undefined }, { type: 'HIDE_LOADING_INDICATION' }, { type: 'DISPLAY_WARNING', value: 'error' }, - ] + ]; try { await store.dispatch( @@ -1526,159 +1528,159 @@ describe('Actions', function () { '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc', 'test', ), - ) - assert.fail('Should have thrown error') + ); + assert.fail('Should have thrown error'); } catch (error) { - assert.deepStrictEqual(store.getActions(), expectedActions) + assert.deepStrictEqual(store.getActions(), expectedActions); } - }) - }) + }); + }); describe('#setFeatureFlag', function () { afterEach(function () { - sinon.restore() - }) + sinon.restore(); + }); it('calls setFeatureFlag in the background', async function () { - const store = mockStore() + const store = mockStore(); - const setFeatureFlagStub = sinon.stub().callsFake((_, __, cb) => cb()) + const setFeatureFlagStub = sinon.stub().callsFake((_, __, cb) => cb()); background.getApi.returns({ setFeatureFlag: setFeatureFlagStub, - }) + }); - actions._setBackgroundConnection(background.getApi()) + actions._setBackgroundConnection(background.getApi()); - await store.dispatch(actions.setFeatureFlag()) - assert(setFeatureFlagStub.calledOnce) - }) + await store.dispatch(actions.setFeatureFlag()); + assert(setFeatureFlagStub.calledOnce); + }); it('errors when setFeatureFlag in background throws', async function () { - const store = mockStore() + const store = mockStore(); background.getApi.returns({ setFeatureFlag: sinon .stub() .callsFake((_, __, cb) => cb(new Error('error'))), - }) + }); - actions._setBackgroundConnection(background.getApi()) + actions._setBackgroundConnection(background.getApi()); const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', value: undefined }, { type: 'HIDE_LOADING_INDICATION' }, { type: 'DISPLAY_WARNING', value: 'error' }, - ] + ]; try { - await store.dispatch(actions.setFeatureFlag()) - assert.fail('Should have thrown error') + await store.dispatch(actions.setFeatureFlag()); + assert.fail('Should have thrown error'); } catch (_) { - assert.deepStrictEqual(store.getActions(), expectedActions) + assert.deepStrictEqual(store.getActions(), expectedActions); } - }) - }) + }); + }); describe('#setCompletedOnboarding', function () { afterEach(function () { - sinon.restore() - }) + sinon.restore(); + }); it('completes onboarding', async function () { - const store = mockStore() - const completeOnboardingStub = sinon.stub().callsFake((cb) => cb()) + const store = mockStore(); + const completeOnboardingStub = sinon.stub().callsFake((cb) => cb()); background.getApi.returns({ completeOnboarding: completeOnboardingStub, - }) + }); - actions._setBackgroundConnection(background.getApi()) + actions._setBackgroundConnection(background.getApi()); - await store.dispatch(actions.setCompletedOnboarding()) - assert(completeOnboardingStub.calledOnce) - }) + await store.dispatch(actions.setCompletedOnboarding()); + assert(completeOnboardingStub.calledOnce); + }); it('errors when setCompletedOnboarding in background throws', async function () { - const store = mockStore() + const store = mockStore(); background.getApi.returns({ completeOnboarding: sinon .stub() .callsFake((cb) => cb(new Error('error'))), - }) + }); - actions._setBackgroundConnection(background.getApi()) + actions._setBackgroundConnection(background.getApi()); const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', value: undefined }, { type: 'DISPLAY_WARNING', value: 'error' }, { type: 'HIDE_LOADING_INDICATION' }, - ] + ]; try { - await store.dispatch(actions.setCompletedOnboarding()) - assert.fail('Should have thrown error') + await store.dispatch(actions.setCompletedOnboarding()); + assert.fail('Should have thrown error'); } catch (_) { - assert.deepStrictEqual(store.getActions(), expectedActions) + assert.deepStrictEqual(store.getActions(), expectedActions); } - }) - }) + }); + }); describe('#setUseBlockie', function () { afterEach(function () { - sinon.restore() - }) + sinon.restore(); + }); it('calls setUseBlockie in background', async function () { - const store = mockStore() + const store = mockStore(); const setUseBlockStub = background.setUseBlockie.callsFake((_, cb) => cb(), - ) + ); - actions._setBackgroundConnection(background) + actions._setBackgroundConnection(background); - await store.dispatch(actions.setUseBlockie()) - assert(setUseBlockStub.calledOnce) - }) + await store.dispatch(actions.setUseBlockie()); + assert(setUseBlockStub.calledOnce); + }); it('errors when setUseBlockie in background throws', async function () { - const store = mockStore() + const store = mockStore(); - background.setUseBlockie.callsFake((_, cb) => cb(new Error('error'))) + background.setUseBlockie.callsFake((_, cb) => cb(new Error('error'))); - actions._setBackgroundConnection(background) + actions._setBackgroundConnection(background); const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', value: undefined }, { type: 'HIDE_LOADING_INDICATION' }, { type: 'DISPLAY_WARNING', value: 'error' }, { type: 'SET_USE_BLOCKIE', value: undefined }, - ] + ]; - await store.dispatch(actions.setUseBlockie()) - assert.deepStrictEqual(store.getActions(), expectedActions) - }) - }) + await store.dispatch(actions.setUseBlockie()); + assert.deepStrictEqual(store.getActions(), expectedActions); + }); + }); describe('#updateCurrentLocale', function () { beforeEach(function () { sinon.stub(window, 'fetch').resolves({ json: async () => enLocale, - }) - }) + }); + }); afterEach(function () { - sinon.restore() - }) + sinon.restore(); + }); it('calls expected actions', async function () { - const store = mockStore() + const store = mockStore(); - background.setCurrentLocale.callsFake((_, cb) => cb()) + background.setCurrentLocale.callsFake((_, cb) => cb()); - actions._setBackgroundConnection(background) + actions._setBackgroundConnection(background); const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', value: undefined }, @@ -1687,63 +1689,65 @@ describe('Actions', function () { value: { locale: 'test', messages: enLocale }, }, { type: 'HIDE_LOADING_INDICATION' }, - ] + ]; - await store.dispatch(actions.updateCurrentLocale('test')) - assert(background.setCurrentLocale.calledOnce) - assert.deepStrictEqual(store.getActions(), expectedActions) - }) + await store.dispatch(actions.updateCurrentLocale('test')); + assert(background.setCurrentLocale.calledOnce); + assert.deepStrictEqual(store.getActions(), expectedActions); + }); it('errors when setCurrentLocale throws', async function () { - const store = mockStore() + const store = mockStore(); - background.setCurrentLocale.callsFake((_, cb) => cb(new Error('error'))) + background.setCurrentLocale.callsFake((_, cb) => cb(new Error('error'))); - actions._setBackgroundConnection(background) + actions._setBackgroundConnection(background); const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', value: undefined }, { type: 'DISPLAY_WARNING', value: 'error' }, { type: 'HIDE_LOADING_INDICATION' }, - ] + ]; try { - await store.dispatch(actions.updateCurrentLocale('test')) - assert.fail('Should have thrown error') + await store.dispatch(actions.updateCurrentLocale('test')); + assert.fail('Should have thrown error'); } catch (_) { - assert.deepStrictEqual(store.getActions(), expectedActions) + assert.deepStrictEqual(store.getActions(), expectedActions); } - }) - }) + }); + }); describe('#markPasswordForgotten', function () { afterEach(function () { - sinon.restore() - }) + sinon.restore(); + }); it('calls markPasswordForgotten', async function () { - const store = mockStore() + const store = mockStore(); - background.markPasswordForgotten.callsFake((cb) => cb()) + background.markPasswordForgotten.callsFake((cb) => cb()); - actions._setBackgroundConnection(background) + actions._setBackgroundConnection(background); - await store.dispatch(actions.markPasswordForgotten()) + await store.dispatch(actions.markPasswordForgotten()); - const resultantActions = store.getActions() + const resultantActions = store.getActions(); assert.deepStrictEqual(resultantActions[1], { type: 'FORGOT_PASSWORD', value: true, - }) - assert(background.markPasswordForgotten.calledOnce) - }) + }); + assert(background.markPasswordForgotten.calledOnce); + }); it('errors when markPasswordForgotten throws', async function () { - const store = mockStore() + const store = mockStore(); - background.markPasswordForgotten.callsFake((cb) => cb(new Error('error'))) + background.markPasswordForgotten.callsFake((cb) => + cb(new Error('error')), + ); - actions._setBackgroundConnection(background) + actions._setBackgroundConnection(background); const expectedActions = [ { type: 'HIDE_LOADING_INDICATION' }, @@ -1755,33 +1759,33 @@ describe('Actions', function () { selectedAddress: '0xFirstAddress', }, }, - ] + ]; try { - await store.dispatch(actions.markPasswordForgotten('test')) - assert.fail('Should have thrown error') + await store.dispatch(actions.markPasswordForgotten('test')); + assert.fail('Should have thrown error'); } catch (_) { - assert.deepStrictEqual(store.getActions(), expectedActions) + assert.deepStrictEqual(store.getActions(), expectedActions); } - }) - }) + }); + }); describe('#unMarkPasswordForgotten', function () { it('calls unMarkPasswordForgotten', async function () { - const store = mockStore() + const store = mockStore(); - background.unMarkPasswordForgotten.callsFake((cb) => cb()) + background.unMarkPasswordForgotten.callsFake((cb) => cb()); - actions._setBackgroundConnection(background) + actions._setBackgroundConnection(background); - await store.dispatch(actions.unMarkPasswordForgotten()) + await store.dispatch(actions.unMarkPasswordForgotten()); - const resultantActions = store.getActions() + const resultantActions = store.getActions(); assert.deepStrictEqual(resultantActions[0], { type: 'FORGOT_PASSWORD', value: false, - }) - assert(background.unMarkPasswordForgotten.calledOnce) - }) - }) -}) + }); + assert(background.unMarkPasswordForgotten.calledOnce); + }); + }); +}); diff --git a/test/unit/ui/app/reducers/app.spec.js b/test/unit/ui/app/reducers/app.spec.js index 3cf350b7f..f95060e32 100644 --- a/test/unit/ui/app/reducers/app.spec.js +++ b/test/unit/ui/app/reducers/app.spec.js @@ -1,8 +1,8 @@ -import assert from 'assert' -import reduceApp from '../../../../../ui/app/ducks/app/app' -import * as actionConstants from '../../../../../ui/app/store/actionConstants' +import assert from 'assert'; +import reduceApp from '../../../../../ui/app/ducks/app/app'; +import * as actionConstants from '../../../../../ui/app/store/actionConstants'; -const actions = actionConstants +const actions = actionConstants; describe('App State', function () { const metamaskState = { @@ -13,86 +13,86 @@ describe('App State', function () { address: '0xAddress', }, }, - } + }; it('App init state', function () { - const initState = reduceApp(metamaskState, {}) + const initState = reduceApp(metamaskState, {}); - assert(initState) - }) + assert(initState); + }); it('sets networkDropdownOpen dropdown to true', function () { const state = reduceApp(metamaskState, { type: actions.NETWORK_DROPDOWN_OPEN, - }) + }); - assert.equal(state.networkDropdownOpen, true) - }) + assert.equal(state.networkDropdownOpen, true); + }); it('sets networkDropdownOpen dropdown to false', function () { - const dropdown = { networkDropdowopen: true } - const state = { ...metamaskState, ...dropdown } + const dropdown = { networkDropdowopen: true }; + const state = { ...metamaskState, ...dropdown }; const newState = reduceApp(state, { type: actions.NETWORK_DROPDOWN_CLOSE, - }) + }); - assert.equal(newState.networkDropdownOpen, false) - }) + assert.equal(newState.networkDropdownOpen, false); + }); it('opens sidebar', function () { const value = { transitionName: 'sidebar-right', type: 'wallet-view', isOpen: true, - } + }; const state = reduceApp(metamaskState, { type: actions.SIDEBAR_OPEN, value, - }) + }); - assert.deepEqual(state.sidebar, value) - }) + assert.deepEqual(state.sidebar, value); + }); it('closes sidebar', function () { - const openSidebar = { sidebar: { isOpen: true } } - const state = { ...metamaskState, ...openSidebar } + const openSidebar = { sidebar: { isOpen: true } }; + const state = { ...metamaskState, ...openSidebar }; const newState = reduceApp(state, { type: actions.SIDEBAR_CLOSE, - }) + }); - assert.equal(newState.sidebar.isOpen, false) - }) + assert.equal(newState.sidebar.isOpen, false); + }); it('opens alert', function () { const state = reduceApp(metamaskState, { type: actions.ALERT_OPEN, value: 'test message', - }) + }); - assert.equal(state.alertOpen, true) - assert.equal(state.alertMessage, 'test message') - }) + assert.equal(state.alertOpen, true); + assert.equal(state.alertMessage, 'test message'); + }); it('closes alert', function () { - const alert = { alertOpen: true, alertMessage: 'test message' } - const state = { ...metamaskState, ...alert } + const alert = { alertOpen: true, alertMessage: 'test message' }; + const state = { ...metamaskState, ...alert }; const newState = reduceApp(state, { type: actions.ALERT_CLOSE, - }) + }); - assert.equal(newState.alertOpen, false) - assert.equal(newState.alertMessage, null) - }) + assert.equal(newState.alertOpen, false); + assert.equal(newState.alertMessage, null); + }); it('detects qr code data', function () { const state = reduceApp(metamaskState, { type: actions.QR_CODE_DETECTED, value: 'qr data', - }) + }); - assert.equal(state.qrCodeData, 'qr data') - }) + assert.equal(state.qrCodeData, 'qr data'); + }); it('opens modal', function () { const state = reduceApp(metamaskState, { @@ -100,11 +100,11 @@ describe('App State', function () { payload: { name: 'test', }, - }) + }); - assert.equal(state.modal.open, true) - assert.equal(state.modal.modalState.name, 'test') - }) + assert.equal(state.modal.open, true); + assert.equal(state.modal.modalState.name, 'test'); + }); it('closes modal, but moves open modal state to previous modal state', function () { const opensModal = { @@ -114,54 +114,54 @@ describe('App State', function () { name: 'test', }, }, - } + }; - const state = { ...metamaskState, appState: { ...opensModal } } + const state = { ...metamaskState, appState: { ...opensModal } }; const newState = reduceApp(state, { type: actions.MODAL_CLOSE, - }) + }); - assert.equal(newState.modal.open, false) - assert.equal(newState.modal.modalState.name, null) - }) + assert.equal(newState.modal.open, false); + assert.equal(newState.modal.modalState.name, null); + }); it('shows send token page', function () { const state = reduceApp(metamaskState, { type: actions.SHOW_SEND_TOKEN_PAGE, - }) + }); - assert.equal(state.warning, null) - }) + assert.equal(state.warning, null); + }); it('locks Metamask', function () { const state = reduceApp(metamaskState, { type: actions.LOCK_METAMASK, - }) + }); - assert.equal(state.warning, null) - }) + assert.equal(state.warning, null); + }); it('goes home', function () { const state = reduceApp(metamaskState, { type: actions.GO_HOME, - }) + }); - assert.equal(state.accountDetail.subview, 'transactions') - assert.equal(state.accountDetail.accountExport, 'none') - assert.equal(state.accountDetail.privateKey, '') - assert.equal(state.warning, null) - }) + assert.equal(state.accountDetail.subview, 'transactions'); + assert.equal(state.accountDetail.accountExport, 'none'); + assert.equal(state.accountDetail.privateKey, ''); + assert.equal(state.warning, null); + }); it('shows account detail', function () { const state = reduceApp(metamaskState, { type: actions.SHOW_ACCOUNT_DETAIL, value: 'context address', - }) - assert.equal(state.forgottenPassword, null) // default - assert.equal(state.accountDetail.subview, 'transactions') // default - assert.equal(state.accountDetail.accountExport, 'none') // default - assert.equal(state.accountDetail.privateKey, '') // default - }) + }); + assert.equal(state.forgottenPassword, null); // default + assert.equal(state.accountDetail.subview, 'transactions'); // default + assert.equal(state.accountDetail.accountExport, 'none'); // default + assert.equal(state.accountDetail.privateKey, ''); // default + }); it('clears account details', function () { const exportPrivKeyModal = { @@ -170,26 +170,26 @@ describe('App State', function () { accountExport: 'completed', privateKey: 'a-priv-key', }, - } + }; - const state = { ...metamaskState, appState: { ...exportPrivKeyModal } } + const state = { ...metamaskState, appState: { ...exportPrivKeyModal } }; const newState = reduceApp(state, { type: actions.CLEAR_ACCOUNT_DETAILS, - }) + }); - assert.deepStrictEqual(newState.accountDetail, {}) - }) + assert.deepStrictEqual(newState.accountDetail, {}); + }); it('shoes account page', function () { const state = reduceApp(metamaskState, { type: actions.SHOW_ACCOUNTS_PAGE, - }) + }); - assert.equal(state.isLoading, false) - assert.equal(state.warning, null) - assert.equal(state.scrollToBottom, false) - assert.equal(state.forgottenPassword, false) - }) + assert.equal(state.isLoading, false); + assert.equal(state.warning, null); + assert.equal(state.scrollToBottom, false); + assert.equal(state.forgottenPassword, false); + }); it('shows confirm tx page', function () { const txs = { @@ -201,17 +201,17 @@ describe('App State', function () { id: 2, }, }, - } - const oldState = { ...metamaskState, ...txs } + }; + const oldState = { ...metamaskState, ...txs }; const state = reduceApp(oldState, { type: actions.SHOW_CONF_TX_PAGE, id: 2, - }) + }); - assert.equal(state.txId, 2) - assert.equal(state.warning, null) - assert.equal(state.isLoading, false) - }) + assert.equal(state.txId, 2); + assert.equal(state.warning, null); + assert.equal(state.isLoading, false); + }); it('completes tx continues to show pending txs current view context', function () { const txs = { @@ -223,20 +223,20 @@ describe('App State', function () { id: 2, }, }, - } + }; - const oldState = { ...metamaskState, ...txs } + const oldState = { ...metamaskState, ...txs }; const state = reduceApp(oldState, { type: actions.COMPLETED_TX, value: { id: 1, }, - }) + }); - assert.equal(state.txId, null) - assert.equal(state.warning, null) - }) + assert.equal(state.txId, null); + assert.equal(state.warning, null); + }); it('returns to account detail page when no unconf actions completed tx', function () { const state = reduceApp(metamaskState, { @@ -244,131 +244,131 @@ describe('App State', function () { value: { unconfirmedActionsCount: 0, }, - }) + }); - assert.equal(state.warning, null) - assert.equal(state.accountDetail.subview, 'transactions') - }) + assert.equal(state.warning, null); + assert.equal(state.accountDetail.subview, 'transactions'); + }); it('sets default warning when unlock fails', function () { const state = reduceApp(metamaskState, { type: actions.UNLOCK_FAILED, - }) + }); - assert.equal(state.warning, 'Incorrect password. Try again.') - }) + assert.equal(state.warning, 'Incorrect password. Try again.'); + }); it('sets errors when unlock fails', function () { const state = reduceApp(metamaskState, { type: actions.UNLOCK_FAILED, value: 'errors', - }) + }); - assert.equal(state.warning, 'errors') - }) + assert.equal(state.warning, 'errors'); + }); it('sets warning to empty string when unlock succeeds', function () { - const errorState = { warning: 'errors' } - const oldState = { ...metamaskState, ...errorState } + const errorState = { warning: 'errors' }; + const oldState = { ...metamaskState, ...errorState }; const state = reduceApp(oldState, { type: actions.UNLOCK_SUCCEEDED, - }) + }); - assert.equal(state.warning, '') - }) + assert.equal(state.warning, ''); + }); it('sets hardware wallet default hd path', function () { const hdPaths = { trezor: "m/44'/60'/0'/0", ledger: "m/44'/60'/0'", - } + }; const state = reduceApp(metamaskState, { type: actions.SET_HARDWARE_WALLET_DEFAULT_HD_PATH, value: { device: 'ledger', path: "m/44'/60'/0'", }, - }) + }); - assert.deepEqual(state.defaultHdPaths, hdPaths) - }) + assert.deepEqual(state.defaultHdPaths, hdPaths); + }); it('shows loading message', function () { const state = reduceApp(metamaskState, { type: actions.SHOW_LOADING, value: 'loading', - }) + }); - assert.equal(state.isLoading, true) - assert.equal(state.loadingMessage, 'loading') - }) + assert.equal(state.isLoading, true); + assert.equal(state.loadingMessage, 'loading'); + }); it('hides loading message', function () { - const loadingState = { isLoading: true } - const oldState = { ...metamaskState, ...loadingState } + const loadingState = { isLoading: true }; + const oldState = { ...metamaskState, ...loadingState }; const state = reduceApp(oldState, { type: actions.HIDE_LOADING, - }) + }); - assert.equal(state.isLoading, false) - }) + assert.equal(state.isLoading, false); + }); it('displays warning', function () { const state = reduceApp(metamaskState, { type: actions.DISPLAY_WARNING, value: 'warning', - }) + }); - assert.equal(state.isLoading, false) - assert.equal(state.warning, 'warning') - }) + assert.equal(state.isLoading, false); + assert.equal(state.warning, 'warning'); + }); it('hides warning', function () { - const displayWarningState = { warning: 'warning' } - const oldState = { ...metamaskState, ...displayWarningState } + const displayWarningState = { warning: 'warning' }; + const oldState = { ...metamaskState, ...displayWarningState }; const state = reduceApp(oldState, { type: actions.HIDE_WARNING, - }) + }); - assert.equal(state.warning, undefined) - }) + assert.equal(state.warning, undefined); + }); it('shows private key', function () { const state = reduceApp(metamaskState, { type: actions.SHOW_PRIVATE_KEY, value: 'private key', - }) + }); - assert.equal(state.accountDetail.subview, 'export') - assert.equal(state.accountDetail.accountExport, 'completed') - assert.equal(state.accountDetail.privateKey, 'private key') - }) + assert.equal(state.accountDetail.subview, 'export'); + assert.equal(state.accountDetail.accountExport, 'completed'); + assert.equal(state.accountDetail.privateKey, 'private key'); + }); it('set mouse user state', function () { const state = reduceApp(metamaskState, { type: actions.SET_MOUSE_USER_STATE, value: true, - }) + }); - assert.equal(state.isMouseUser, true) - }) + assert.equal(state.isMouseUser, true); + }); it('sets gas loading', function () { const state = reduceApp(metamaskState, { type: actions.GAS_LOADING_STARTED, - }) + }); - assert.equal(state.gasIsLoading, true) - }) + assert.equal(state.gasIsLoading, true); + }); it('unsets gas loading', function () { - const gasLoadingState = { gasIsLoading: true } - const oldState = { ...metamaskState, ...gasLoadingState } + const gasLoadingState = { gasIsLoading: true }; + const oldState = { ...metamaskState, ...gasLoadingState }; const state = reduceApp(oldState, { type: actions.GAS_LOADING_FINISHED, - }) + }); - assert.equal(state.gasIsLoading, false) - }) -}) + assert.equal(state.gasIsLoading, false); + }); +}); diff --git a/test/unit/ui/app/reducers/metamask.spec.js b/test/unit/ui/app/reducers/metamask.spec.js index c36ad1bb9..faf765b86 100644 --- a/test/unit/ui/app/reducers/metamask.spec.js +++ b/test/unit/ui/app/reducers/metamask.spec.js @@ -1,24 +1,24 @@ -import assert from 'assert' -import reduceMetamask from '../../../../../ui/app/ducks/metamask/metamask' -import * as actionConstants from '../../../../../ui/app/store/actionConstants' +import assert from 'assert'; +import reduceMetamask from '../../../../../ui/app/ducks/metamask/metamask'; +import * as actionConstants from '../../../../../ui/app/store/actionConstants'; describe('MetaMask Reducers', function () { it('init state', function () { - const initState = reduceMetamask(undefined, {}) - assert(initState) - }) + const initState = reduceMetamask(undefined, {}); + assert(initState); + }); it('locks MetaMask', function () { const unlockMetaMaskState = { isUnlocked: true, selectedAddress: 'test address', - } + }; const lockMetaMask = reduceMetamask(unlockMetaMaskState, { type: actionConstants.LOCK_METAMASK, - }) + }); - assert.equal(lockMetaMask.isUnlocked, false) - }) + assert.equal(lockMetaMask.isUnlocked, false); + }); it('sets rpc target', function () { const state = reduceMetamask( @@ -27,10 +27,10 @@ describe('MetaMask Reducers', function () { type: actionConstants.SET_RPC_TARGET, value: 'https://custom.rpc', }, - ) + ); - assert.equal(state.provider.rpcUrl, 'https://custom.rpc') - }) + assert.equal(state.provider.rpcUrl, 'https://custom.rpc'); + }); it('sets provider type', function () { const state = reduceMetamask( @@ -39,10 +39,10 @@ describe('MetaMask Reducers', function () { type: actionConstants.SET_PROVIDER_TYPE, value: 'provider type', }, - ) + ); - assert.equal(state.provider.type, 'provider type') - }) + assert.equal(state.provider.type, 'provider type'); + }); it('shows account detail', function () { const state = reduceMetamask( @@ -51,12 +51,12 @@ describe('MetaMask Reducers', function () { type: actionConstants.SHOW_ACCOUNT_DETAIL, value: 'test address', }, - ) + ); - assert.equal(state.isUnlocked, true) - assert.equal(state.isInitialized, true) - assert.equal(state.selectedAddress, 'test address') - }) + assert.equal(state.isUnlocked, true); + assert.equal(state.isInitialized, true); + assert.equal(state.selectedAddress, 'test address'); + }); it('sets account label', function () { const state = reduceMetamask( @@ -68,19 +68,19 @@ describe('MetaMask Reducers', function () { label: 'test label', }, }, - ) + ); assert.deepEqual(state.identities, { 'test account': { name: 'test label' }, - }) - }) + }); + }); it('sets current fiat', function () { const value = { currentCurrency: 'yen', conversionRate: 3.14, conversionDate: new Date(2018, 9), - } + }; const state = reduceMetamask( {}, @@ -88,19 +88,19 @@ describe('MetaMask Reducers', function () { type: actionConstants.SET_CURRENT_FIAT, value, }, - ) + ); - assert.equal(state.currentCurrency, value.currentCurrency) - assert.equal(state.conversionRate, value.conversionRate) - assert.equal(state.conversionDate, value.conversionDate) - }) + assert.equal(state.currentCurrency, value.currentCurrency); + assert.equal(state.conversionRate, value.conversionRate); + assert.equal(state.conversionDate, value.conversionDate); + }); it('updates tokens', function () { const newTokens = { address: '0x617b3f8050a0bd94b6b1da02b4384ee5b4df13f4', decimals: 18, symbol: 'META', - } + }; const state = reduceMetamask( {}, @@ -108,10 +108,10 @@ describe('MetaMask Reducers', function () { type: actionConstants.UPDATE_TOKENS, newTokens, }, - ) + ); - assert.deepEqual(state.tokens, newTokens) - }) + assert.deepEqual(state.tokens, newTokens); + }); it('updates send gas limit', function () { const state = reduceMetamask( @@ -120,10 +120,10 @@ describe('MetaMask Reducers', function () { type: actionConstants.UPDATE_GAS_LIMIT, value: '0xGasLimit', }, - ) + ); - assert.equal(state.send.gasLimit, '0xGasLimit') - }) + assert.equal(state.send.gasLimit, '0xGasLimit'); + }); it('updates send gas price', function () { const state = reduceMetamask( @@ -132,10 +132,10 @@ describe('MetaMask Reducers', function () { type: actionConstants.UPDATE_GAS_PRICE, value: '0xGasPrice', }, - ) + ); - assert.equal(state.send.gasPrice, '0xGasPrice') - }) + assert.equal(state.send.gasPrice, '0xGasPrice'); + }); it('toggles account menu ', function () { const state = reduceMetamask( @@ -143,10 +143,10 @@ describe('MetaMask Reducers', function () { { type: actionConstants.TOGGLE_ACCOUNT_MENU, }, - ) + ); - assert.equal(state.isAccountMenuOpen, true) - }) + assert.equal(state.isAccountMenuOpen, true); + }); it('updates gas total', function () { const state = reduceMetamask( @@ -155,10 +155,10 @@ describe('MetaMask Reducers', function () { type: actionConstants.UPDATE_GAS_TOTAL, value: '0xGasTotal', }, - ) + ); - assert.equal(state.send.gasTotal, '0xGasTotal') - }) + assert.equal(state.send.gasTotal, '0xGasTotal'); + }); it('updates send token balance', function () { const state = reduceMetamask( @@ -167,10 +167,10 @@ describe('MetaMask Reducers', function () { type: actionConstants.UPDATE_SEND_TOKEN_BALANCE, value: '0xTokenBalance', }, - ) + ); - assert.equal(state.send.tokenBalance, '0xTokenBalance') - }) + assert.equal(state.send.tokenBalance, '0xTokenBalance'); + }); it('updates data', function () { const state = reduceMetamask( @@ -179,10 +179,10 @@ describe('MetaMask Reducers', function () { type: actionConstants.UPDATE_SEND_HEX_DATA, value: '0xData', }, - ) + ); - assert.equal(state.send.data, '0xData') - }) + assert.equal(state.send.data, '0xData'); + }); it('updates send to', function () { const state = reduceMetamask( @@ -194,11 +194,11 @@ describe('MetaMask Reducers', function () { nickname: 'nickname', }, }, - ) + ); - assert.equal(state.send.to, '0xAddress') - assert.equal(state.send.toNickname, 'nickname') - }) + assert.equal(state.send.to, '0xAddress'); + assert.equal(state.send.toNickname, 'nickname'); + }); it('update send amount', function () { const state = reduceMetamask( @@ -207,10 +207,10 @@ describe('MetaMask Reducers', function () { type: actionConstants.UPDATE_SEND_AMOUNT, value: '0xAmount', }, - ) + ); - assert.equal(state.send.amount, '0xAmount') - }) + assert.equal(state.send.amount, '0xAmount'); + }); it('updates max mode', function () { const state = reduceMetamask( @@ -219,10 +219,10 @@ describe('MetaMask Reducers', function () { type: actionConstants.UPDATE_MAX_MODE, value: true, }, - ) + ); - assert.equal(state.send.maxModeOn, true) - }) + assert.equal(state.send.maxModeOn, true); + }); it('update send', function () { const value = { @@ -240,7 +240,7 @@ describe('MetaMask Reducers', function () { editingTransactionId: 22, ensResolution: null, ensResolutionError: '', - } + }; const sendState = reduceMetamask( {}, @@ -248,10 +248,10 @@ describe('MetaMask Reducers', function () { type: actionConstants.UPDATE_SEND, value, }, - ) + ); - assert.deepEqual(sendState.send, value) - }) + assert.deepEqual(sendState.send, value); + }); it('clears send', function () { const initStateSend = { @@ -269,7 +269,7 @@ describe('MetaMask Reducers', function () { editingTransactionId: null, toNickname: '', }, - } + }; const sendState = { send: { @@ -286,14 +286,14 @@ describe('MetaMask Reducers', function () { errors: {}, editingTransactionId: 22, }, - } + }; const state = reduceMetamask(sendState, { type: actionConstants.CLEAR_SEND, - }) + }); - assert.deepEqual(state.send, initStateSend.send) - }) + assert.deepEqual(state.send, initStateSend.send); + }); it('updates value of tx by id', function () { const oldState = { @@ -303,16 +303,16 @@ describe('MetaMask Reducers', function () { txParams: 'foo', }, ], - } + }; const state = reduceMetamask(oldState, { type: actionConstants.UPDATE_TRANSACTION_PARAMS, id: 1, value: 'bar', - }) + }); - assert.equal(state.currentNetworkTxList[0].txParams, 'bar') - }) + assert.equal(state.currentNetworkTxList[0].txParams, 'bar'); + }); it('sets blockies', function () { const state = reduceMetamask( @@ -321,10 +321,10 @@ describe('MetaMask Reducers', function () { type: actionConstants.SET_USE_BLOCKIE, value: true, }, - ) + ); - assert.equal(state.useBlockie, true) - }) + assert.equal(state.useBlockie, true); + }); it('updates an arbitrary feature flag', function () { const state = reduceMetamask( @@ -335,10 +335,10 @@ describe('MetaMask Reducers', function () { foo: true, }, }, - ) + ); - assert.equal(state.featureFlags.foo, true) - }) + assert.equal(state.featureFlags.foo, true); + }); it('close welcome screen', function () { const state = reduceMetamask( @@ -346,10 +346,10 @@ describe('MetaMask Reducers', function () { { type: actionConstants.CLOSE_WELCOME_SCREEN, }, - ) + ); - assert.equal(state.welcomeScreenSeen, true) - }) + assert.equal(state.welcomeScreenSeen, true); + }); it('sets current locale', function () { const state = reduceMetamask( @@ -358,17 +358,17 @@ describe('MetaMask Reducers', function () { type: actionConstants.SET_CURRENT_LOCALE, value: { locale: 'ge' }, }, - ) + ); - assert.equal(state.currentLocale, 'ge') - }) + assert.equal(state.currentLocale, 'ge'); + }); it('sets pending tokens ', function () { const payload = { address: '0x617b3f8050a0bd94b6b1da02b4384ee5b4df13f4', decimals: 18, symbol: 'META', - } + }; const pendingTokensState = reduceMetamask( {}, @@ -376,28 +376,28 @@ describe('MetaMask Reducers', function () { type: actionConstants.SET_PENDING_TOKENS, payload, }, - ) + ); - assert.deepEqual(pendingTokensState.pendingTokens, payload) - }) + assert.deepEqual(pendingTokensState.pendingTokens, payload); + }); it('clears pending tokens', function () { const payload = { address: '0x617b3f8050a0bd94b6b1da02b4384ee5b4df13f4', decimals: 18, symbol: 'META', - } + }; const pendingTokensState = { pendingTokens: payload, - } + }; const state = reduceMetamask(pendingTokensState, { type: actionConstants.CLEAR_PENDING_TOKENS, - }) + }); - assert.deepEqual(state.pendingTokens, {}) - }) + assert.deepEqual(state.pendingTokens, {}); + }); it('update ensResolution', function () { const state = reduceMetamask( @@ -406,11 +406,11 @@ describe('MetaMask Reducers', function () { type: actionConstants.UPDATE_SEND_ENS_RESOLUTION, payload: '0x1337', }, - ) + ); - assert.deepEqual(state.send.ensResolution, '0x1337') - assert.deepEqual(state.send.ensResolutionError, '') - }) + assert.deepEqual(state.send.ensResolution, '0x1337'); + assert.deepEqual(state.send.ensResolutionError, ''); + }); it('update ensResolutionError', function () { const state = reduceMetamask( @@ -419,9 +419,9 @@ describe('MetaMask Reducers', function () { type: actionConstants.UPDATE_SEND_ENS_RESOLUTION_ERROR, payload: 'ens name not found', }, - ) + ); - assert.deepEqual(state.send.ensResolutionError, 'ens name not found') - assert.deepEqual(state.send.ensResolution, null) - }) -}) + assert.deepEqual(state.send.ensResolutionError, 'ens name not found'); + assert.deepEqual(state.send.ensResolution, null); + }); +}); diff --git a/test/unit/ui/etherscan-prefix-for-network.spec.js b/test/unit/ui/etherscan-prefix-for-network.spec.js index 1b3ce7b34..e53c32e5e 100644 --- a/test/unit/ui/etherscan-prefix-for-network.spec.js +++ b/test/unit/ui/etherscan-prefix-for-network.spec.js @@ -1,28 +1,28 @@ -import assert from 'assert' -import { getEtherscanNetworkPrefix } from '../../../ui/lib/etherscan-prefix-for-network' +import assert from 'assert'; +import { getEtherscanNetworkPrefix } from '../../../ui/lib/etherscan-prefix-for-network'; describe('Etherscan Network Prefix', function () { it('returns empty string as default value', function () { - assert.equal(getEtherscanNetworkPrefix(), '') - }) + assert.equal(getEtherscanNetworkPrefix(), ''); + }); it('returns empty string as a prefix for networkId of 1', function () { - assert.equal(getEtherscanNetworkPrefix('1'), '') - }) + assert.equal(getEtherscanNetworkPrefix('1'), ''); + }); it('returns ropsten as prefix for networkId of 3', function () { - assert.equal(getEtherscanNetworkPrefix('3'), 'ropsten.') - }) + assert.equal(getEtherscanNetworkPrefix('3'), 'ropsten.'); + }); it('returns rinkeby as prefix for networkId of 4', function () { - assert.equal(getEtherscanNetworkPrefix('4'), 'rinkeby.') - }) + assert.equal(getEtherscanNetworkPrefix('4'), 'rinkeby.'); + }); it('returs kovan as prefix for networkId of 42', function () { - assert.equal(getEtherscanNetworkPrefix('42'), 'kovan.') - }) + assert.equal(getEtherscanNetworkPrefix('42'), 'kovan.'); + }); it('returs goerli as prefix for networkId of 5', function () { - assert.equal(getEtherscanNetworkPrefix('5'), 'goerli.') - }) -}) + assert.equal(getEtherscanNetworkPrefix('5'), 'goerli.'); + }); +}); diff --git a/ui/app/components/app/account-list-item/account-list-item.js b/ui/app/components/app/account-list-item/account-list-item.js index 362c740d0..9b0c0e38f 100644 --- a/ui/app/components/app/account-list-item/account-list-item.js +++ b/ui/app/components/app/account-list-item/account-list-item.js @@ -1,8 +1,8 @@ -import React from 'react' -import PropTypes from 'prop-types' -import { checksumAddress } from '../../../helpers/utils/util' -import Identicon from '../../ui/identicon' -import AccountMismatchWarning from '../../ui/account-mismatch-warning/account-mismatch-warning.component' +import React from 'react'; +import PropTypes from 'prop-types'; +import { checksumAddress } from '../../../helpers/utils/util'; +import Identicon from '../../ui/identicon'; +import AccountMismatchWarning from '../../ui/account-mismatch-warning/account-mismatch-warning.component'; export default function AccountListItem({ account, @@ -11,7 +11,7 @@ export default function AccountListItem({ handleClick, icon = null, }) { - const { name, address, balance } = account || {} + const { name, address, balance } = account || {}; return (
    )}
    - ) + ); } AccountListItem.propTypes = { @@ -47,4 +47,4 @@ AccountListItem.propTypes = { displayAddress: PropTypes.bool, handleClick: PropTypes.func, icon: PropTypes.node, -} +}; diff --git a/ui/app/components/app/account-list-item/index.js b/ui/app/components/app/account-list-item/index.js index 1759f6597..a129d450c 100644 --- a/ui/app/components/app/account-list-item/index.js +++ b/ui/app/components/app/account-list-item/index.js @@ -1 +1 @@ -export { default } from './account-list-item' +export { default } from './account-list-item'; diff --git a/ui/app/components/app/account-list-item/tests/account-list-item-component.test.js b/ui/app/components/app/account-list-item/tests/account-list-item-component.test.js index 5b329d1ac..558f9cebe 100644 --- a/ui/app/components/app/account-list-item/tests/account-list-item-component.test.js +++ b/ui/app/components/app/account-list-item/tests/account-list-item-component.test.js @@ -1,23 +1,23 @@ -import assert from 'assert' -import React from 'react' -import { shallow } from 'enzyme' -import sinon from 'sinon' -import * as utils from '../../../../helpers/utils/util' -import Identicon from '../../../ui/identicon' -import AccountListItem from '../account-list-item' +import assert from 'assert'; +import React from 'react'; +import { shallow } from 'enzyme'; +import sinon from 'sinon'; +import * as utils from '../../../../helpers/utils/util'; +import Identicon from '../../../ui/identicon'; +import AccountListItem from '../account-list-item'; describe('AccountListItem Component', function () { - let wrapper, propsMethodSpies, checksumAddressStub + let wrapper, propsMethodSpies, checksumAddressStub; describe('render', function () { before(function () { checksumAddressStub = sinon .stub(utils, 'checksumAddress') - .returns('mockCheckSumAddress') + .returns('mockCheckSumAddress'); propsMethodSpies = { handleClick: sinon.spy(), - } - }) + }; + }); beforeEach(function () { wrapper = shallow( } />, { context: { t: (str) => `${str}_t` } }, - ) - }) + ); + }); afterEach(function () { - propsMethodSpies.handleClick.resetHistory() - checksumAddressStub.resetHistory() - }) + propsMethodSpies.handleClick.resetHistory(); + checksumAddressStub.resetHistory(); + }); after(function () { - sinon.restore() - }) + sinon.restore(); + }); it('should render a div with the passed className', function () { - assert.strictEqual(wrapper.find('.mockClassName').length, 1) - assert(wrapper.find('.mockClassName').is('div')) - assert(wrapper.find('.mockClassName').hasClass('account-list-item')) - }) + assert.strictEqual(wrapper.find('.mockClassName').length, 1); + assert(wrapper.find('.mockClassName').is('div')); + assert(wrapper.find('.mockClassName').hasClass('account-list-item')); + }); it('should call handleClick with the expected props when the root div is clicked', function () { - const { onClick } = wrapper.find('.mockClassName').props() - assert.strictEqual(propsMethodSpies.handleClick.callCount, 0) - onClick() - assert.strictEqual(propsMethodSpies.handleClick.callCount, 1) + const { onClick } = wrapper.find('.mockClassName').props(); + assert.strictEqual(propsMethodSpies.handleClick.callCount, 0); + onClick(); + assert.strictEqual(propsMethodSpies.handleClick.callCount, 1); assert.deepStrictEqual(propsMethodSpies.handleClick.getCall(0).args, [ { address: 'mockAddress', name: 'mockName', balance: 'mockBalance' }, - ]) - }) + ]); + }); it('should have a top row div', function () { assert.strictEqual( wrapper.find('.mockClassName > .account-list-item__top-row').length, 1, - ) + ); assert( wrapper.find('.mockClassName > .account-list-item__top-row').is('div'), - ) - }) + ); + }); it('should have an identicon, name and icon in the top row', function () { const topRow = wrapper.find( '.mockClassName > .account-list-item__top-row', - ) - assert.strictEqual(topRow.find(Identicon).length, 1) + ); + assert.strictEqual(topRow.find(Identicon).length, 1); assert.strictEqual( topRow.find('.account-list-item__account-name').length, 1, - ) - assert.strictEqual(topRow.find('.account-list-item__icon').length, 1) - }) + ); + assert.strictEqual(topRow.find('.account-list-item__icon').length, 1); + }); it('should show the account name if it exists', function () { const topRow = wrapper.find( '.mockClassName > .account-list-item__top-row', - ) + ); assert.strictEqual( topRow.find('.account-list-item__account-name').text(), 'mockName', - ) - }) + ); + }); it('should show the account address if there is no name', function () { - wrapper.setProps({ account: { address: 'addressButNoName' } }) + wrapper.setProps({ account: { address: 'addressButNoName' } }); const topRow = wrapper.find( '.mockClassName > .account-list-item__top-row', - ) + ); assert.strictEqual( topRow.find('.account-list-item__account-name').text(), 'addressButNoName', - ) - }) + ); + }); it('should render the passed icon', function () { const topRow = wrapper.find( '.mockClassName > .account-list-item__top-row', - ) - assert(topRow.find('.account-list-item__icon').childAt(0).is('i')) + ); + assert(topRow.find('.account-list-item__icon').childAt(0).is('i')); assert( topRow.find('.account-list-item__icon').childAt(0).hasClass('mockIcon'), - ) - }) + ); + }); it('should not render an icon if none is passed', function () { - wrapper.setProps({ icon: null }) + wrapper.setProps({ icon: null }); const topRow = wrapper.find( '.mockClassName > .account-list-item__top-row', - ) - assert.strictEqual(topRow.find('.account-list-item__icon').length, 0) - }) + ); + assert.strictEqual(topRow.find('.account-list-item__icon').length, 0); + }); it('should render the account address as a checksumAddress if displayAddress is true and name is provided', function () { - wrapper.setProps({ displayAddress: true }) + wrapper.setProps({ displayAddress: true }); assert.strictEqual( wrapper.find('.account-list-item__account-address').length, 1, - ) + ); assert.strictEqual( wrapper.find('.account-list-item__account-address').text(), 'mockCheckSumAddress', - ) + ); assert.deepStrictEqual(checksumAddressStub.getCall(0).args, [ 'mockAddress', - ]) - }) + ]); + }); it('should not render the account address as a checksumAddress if displayAddress is false', function () { - wrapper.setProps({ displayAddress: false }) + wrapper.setProps({ displayAddress: false }); assert.strictEqual( wrapper.find('.account-list-item__account-address').length, 0, - ) - }) + ); + }); it('should not render the account address as a checksumAddress if name is not provided', function () { - wrapper.setProps({ account: { address: 'someAddressButNoName' } }) + wrapper.setProps({ account: { address: 'someAddressButNoName' } }); assert.strictEqual( wrapper.find('.account-list-item__account-address').length, 0, - ) - }) - }) -}) + ); + }); + }); +}); diff --git a/ui/app/components/app/account-menu/account-menu.component.js b/ui/app/components/app/account-menu/account-menu.component.js index f16cb41a4..4c57f4c8d 100644 --- a/ui/app/components/app/account-menu/account-menu.component.js +++ b/ui/app/components/app/account-menu/account-menu.component.js @@ -1,15 +1,15 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import { debounce } from 'lodash' -import Fuse from 'fuse.js' -import InputAdornment from '@material-ui/core/InputAdornment' -import classnames from 'classnames' -import { ENVIRONMENT_TYPE_POPUP } from '../../../../../shared/constants/app' -import { getEnvironmentType } from '../../../../../app/scripts/lib/util' -import Identicon from '../../ui/identicon' -import SiteIcon from '../../ui/site-icon' -import UserPreferencedCurrencyDisplay from '../user-preferenced-currency-display' -import { PRIMARY } from '../../../helpers/constants/common' +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import { debounce } from 'lodash'; +import Fuse from 'fuse.js'; +import InputAdornment from '@material-ui/core/InputAdornment'; +import classnames from 'classnames'; +import { ENVIRONMENT_TYPE_POPUP } from '../../../../../shared/constants/app'; +import { getEnvironmentType } from '../../../../../app/scripts/lib/util'; +import Identicon from '../../ui/identicon'; +import SiteIcon from '../../ui/site-icon'; +import UserPreferencedCurrencyDisplay from '../user-preferenced-currency-display'; +import { PRIMARY } from '../../../helpers/constants/common'; import { SETTINGS_ROUTE, ABOUT_US_ROUTE, @@ -17,16 +17,16 @@ import { IMPORT_ACCOUNT_ROUTE, CONNECT_HARDWARE_ROUTE, DEFAULT_ROUTE, -} from '../../../helpers/constants/routes' -import TextField from '../../ui/text-field' -import SearchIcon from '../../ui/search-icon' +} from '../../../helpers/constants/routes'; +import TextField from '../../ui/text-field'; +import SearchIcon from '../../ui/search-icon'; export function AccountMenuItem(props) { - const { icon, children, text, subText, className, onClick } = props + const { icon, children, text, subText, className, onClick } = props; const itemClassName = classnames('account-menu__item', className, { 'account-menu__item--clickable': Boolean(onClick), - }) + }); return children ? (
    {children} @@ -39,7 +39,7 @@ export function AccountMenuItem(props) {
    {subText}
    ) : null}
    - ) + ); } AccountMenuItem.propTypes = { @@ -49,13 +49,13 @@ AccountMenuItem.propTypes = { subText: PropTypes.node, onClick: PropTypes.func, className: PropTypes.string, -} +}; export default class AccountMenu extends Component { static contextTypes = { t: PropTypes.func, metricsEvent: PropTypes.func, - } + }; static propTypes = { shouldShowAccountsSearch: PropTypes.bool, @@ -69,14 +69,14 @@ export default class AccountMenu extends Component { toggleAccountMenu: PropTypes.func, addressConnectedDomainMap: PropTypes.object, originOfCurrentTab: PropTypes.string, - } + }; - accountsRef + accountsRef; state = { shouldShowScrollButton: false, searchQuery: '', - } + }; addressFuse = new Fuse([], { shouldSort: false, @@ -89,23 +89,23 @@ export default class AccountMenu extends Component { { name: 'name', weight: 0.5 }, { name: 'address', weight: 0.5 }, ], - }) + }); componentDidUpdate(prevProps, prevState) { - const { isAccountMenuOpen: prevIsAccountMenuOpen } = prevProps - const { searchQuery: prevSearchQuery } = prevState - const { isAccountMenuOpen } = this.props - const { searchQuery } = this.state + const { isAccountMenuOpen: prevIsAccountMenuOpen } = prevProps; + const { searchQuery: prevSearchQuery } = prevState; + const { isAccountMenuOpen } = this.props; + const { searchQuery } = this.state; if (!prevIsAccountMenuOpen && isAccountMenuOpen) { - this.setShouldShowScrollButton() - this.resetSearchQuery() + this.setShouldShowScrollButton(); + this.resetSearchQuery(); } // recalculate on each search query change // whether we can show scroll down button if (isAccountMenuOpen && prevSearchQuery !== searchQuery) { - this.setShouldShowScrollButton() + this.setShouldShowScrollButton(); } } @@ -121,7 +121,7 @@ export default class AccountMenu extends Component { > - ) + ); return [ ,
    , - ] + ]; } renderAccounts() { @@ -147,13 +147,13 @@ export default class AccountMenu extends Component { showAccountDetail, addressConnectedDomainMap, originOfCurrentTab, - } = this.props - const { searchQuery } = this.state + } = this.props; + const { searchQuery } = this.state; - let filteredIdentities = accounts + let filteredIdentities = accounts; if (searchQuery) { - this.addressFuse.setCollection(accounts) - filteredIdentities = this.addressFuse.search(searchQuery) + this.addressFuse.setCollection(accounts); + filteredIdentities = this.addressFuse.search(searchQuery); } if (filteredIdentities.length === 0) { @@ -161,22 +161,22 @@ export default class AccountMenu extends Component {

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

    - ) + ); } return filteredIdentities.map((identity) => { - const isSelected = identity.address === selectedAddress + const isSelected = identity.address === selectedAddress; - const simpleAddress = identity.address.substring(2).toLowerCase() + const simpleAddress = identity.address.substring(2).toLowerCase(); const keyring = keyrings.find((kr) => { return ( kr.accounts.includes(simpleAddress) || kr.accounts.includes(identity.address) - ) - }) - const addressDomains = addressConnectedDomainMap[identity.address] || {} - const iconAndNameForOpenDomain = addressDomains[originOfCurrentTab] + ); + }); + const addressDomains = addressConnectedDomainMap[identity.address] || {}; + const iconAndNameForOpenDomain = addressDomains[originOfCurrentTab]; return (
    @@ -216,70 +216,70 @@ export default class AccountMenu extends Component {
    ) : null}
    - ) - }) + ); + }); } renderKeyringType(keyring) { - const { t } = this.context + const { t } = this.context; // Sometimes keyrings aren't loaded yet if (!keyring) { - return null + return null; } - const { type } = keyring - let label + const { type } = keyring; + let label; switch (type) { case 'Trezor Hardware': case 'Ledger Hardware': - label = t('hardware') - break + label = t('hardware'); + break; case 'Simple Key Pair': - label = t('imported') - break + label = t('imported'); + break; default: - return null + return null; } - return
    {label}
    + return
    {label}
    ; } resetSearchQuery() { - this.setSearchQuery('') + this.setSearchQuery(''); } setSearchQuery(searchQuery) { - this.setState({ searchQuery }) + this.setState({ searchQuery }); } setShouldShowScrollButton = () => { - const { scrollTop, offsetHeight, scrollHeight } = this.accountsRef + const { scrollTop, offsetHeight, scrollHeight } = this.accountsRef; - const canScroll = scrollHeight > offsetHeight + const canScroll = scrollHeight > offsetHeight; - const atAccountListBottom = scrollTop + offsetHeight >= scrollHeight + const atAccountListBottom = scrollTop + offsetHeight >= scrollHeight; - const shouldShowScrollButton = canScroll && !atAccountListBottom + const shouldShowScrollButton = canScroll && !atAccountListBottom; - this.setState({ shouldShowScrollButton }) - } + this.setState({ shouldShowScrollButton }); + }; - onScroll = debounce(this.setShouldShowScrollButton, 25) + onScroll = debounce(this.setShouldShowScrollButton, 25); handleScrollDown = (e) => { - e.stopPropagation() + e.stopPropagation(); - const { scrollHeight } = this.accountsRef - this.accountsRef.scroll({ left: 0, top: scrollHeight, behavior: 'smooth' }) + const { scrollHeight } = this.accountsRef; + this.accountsRef.scroll({ left: 0, top: scrollHeight, behavior: 'smooth' }); - this.setShouldShowScrollButton() - } + this.setShouldShowScrollButton(); + }; renderScrollButton() { if (!this.state.shouldShowScrollButton) { - return null + return null; } return ( @@ -294,21 +294,21 @@ export default class AccountMenu extends Component { alt={this.context.t('scrollDown')} /> - ) + ); } render() { - const { t, metricsEvent } = this.context + const { t, metricsEvent } = this.context; const { shouldShowAccountsSearch, isAccountMenuOpen, toggleAccountMenu, lockMetamask, history, - } = this.props + } = this.props; if (!isAccountMenuOpen) { - return null + return null; } return ( @@ -319,8 +319,8 @@ export default class AccountMenu extends Component { - ) + ); } diff --git a/ui/app/components/app/add-token-button/index.js b/ui/app/components/app/add-token-button/index.js index 15c4fe6ca..0534cd39f 100644 --- a/ui/app/components/app/add-token-button/index.js +++ b/ui/app/components/app/add-token-button/index.js @@ -1 +1 @@ -export { default } from './add-token-button.component' +export { default } from './add-token-button.component'; diff --git a/ui/app/components/app/alerts/alerts.js b/ui/app/components/app/alerts/alerts.js index f5034073d..382c0a55e 100644 --- a/ui/app/components/app/alerts/alerts.js +++ b/ui/app/components/app/alerts/alerts.js @@ -1,32 +1,32 @@ -import React from 'react' -import { useSelector } from 'react-redux' -import PropTypes from 'prop-types' +import React from 'react'; +import { useSelector } from 'react-redux'; +import PropTypes from 'prop-types'; -import { alertIsOpen as unconnectedAccountAlertIsOpen } from '../../../ducks/alerts/unconnected-account' -import { alertIsOpen as invalidCustomNetworkAlertIsOpen } from '../../../ducks/alerts/invalid-custom-network' -import InvalidCustomNetworkAlert from './invalid-custom-network-alert' -import UnconnectedAccountAlert from './unconnected-account-alert' +import { alertIsOpen as unconnectedAccountAlertIsOpen } from '../../../ducks/alerts/unconnected-account'; +import { alertIsOpen as invalidCustomNetworkAlertIsOpen } from '../../../ducks/alerts/invalid-custom-network'; +import InvalidCustomNetworkAlert from './invalid-custom-network-alert'; +import UnconnectedAccountAlert from './unconnected-account-alert'; const Alerts = ({ history }) => { const _invalidCustomNetworkAlertIsOpen = useSelector( invalidCustomNetworkAlertIsOpen, - ) + ); const _unconnectedAccountAlertIsOpen = useSelector( unconnectedAccountAlertIsOpen, - ) + ); if (_invalidCustomNetworkAlertIsOpen) { - return + return ; } if (_unconnectedAccountAlertIsOpen) { - return + return ; } - return null -} + return null; +}; Alerts.propTypes = { history: PropTypes.object.isRequired, -} +}; -export default Alerts +export default Alerts; diff --git a/ui/app/components/app/alerts/index.js b/ui/app/components/app/alerts/index.js index b52e5d650..9b5497e58 100644 --- a/ui/app/components/app/alerts/index.js +++ b/ui/app/components/app/alerts/index.js @@ -1 +1 @@ -export { default } from './alerts' +export { default } from './alerts'; diff --git a/ui/app/components/app/alerts/invalid-custom-network-alert/index.js b/ui/app/components/app/alerts/invalid-custom-network-alert/index.js index 9227a2172..5c9fc683d 100644 --- a/ui/app/components/app/alerts/invalid-custom-network-alert/index.js +++ b/ui/app/components/app/alerts/invalid-custom-network-alert/index.js @@ -1 +1 @@ -export { default } from './invalid-custom-network-alert' +export { default } from './invalid-custom-network-alert'; diff --git a/ui/app/components/app/alerts/invalid-custom-network-alert/invalid-custom-network-alert.js b/ui/app/components/app/alerts/invalid-custom-network-alert/invalid-custom-network-alert.js index 40cad2a0f..e5c7ab8c0 100644 --- a/ui/app/components/app/alerts/invalid-custom-network-alert/invalid-custom-network-alert.js +++ b/ui/app/components/app/alerts/invalid-custom-network-alert/invalid-custom-network-alert.js @@ -1,27 +1,27 @@ -import React from 'react' -import { useDispatch, useSelector } from 'react-redux' -import PropTypes from 'prop-types' +import React from 'react'; +import { useDispatch, useSelector } from 'react-redux'; +import PropTypes from 'prop-types'; -import { ALERT_STATE } from '../../../../ducks/alerts' +import { ALERT_STATE } from '../../../../ducks/alerts'; import { dismissAlert, getAlertState, getNetworkName, -} from '../../../../ducks/alerts/invalid-custom-network' -import Popover from '../../../ui/popover' -import Button from '../../../ui/button' -import { useI18nContext } from '../../../../hooks/useI18nContext' -import { NETWORKS_ROUTE } from '../../../../helpers/constants/routes' +} from '../../../../ducks/alerts/invalid-custom-network'; +import Popover from '../../../ui/popover'; +import Button from '../../../ui/button'; +import { useI18nContext } from '../../../../hooks/useI18nContext'; +import { NETWORKS_ROUTE } from '../../../../helpers/constants/routes'; -const { ERROR, LOADING } = ALERT_STATE +const { ERROR, LOADING } = ALERT_STATE; const InvalidCustomNetworkAlert = ({ history }) => { - const t = useI18nContext() - const dispatch = useDispatch() - const alertState = useSelector(getAlertState) - const networkName = useSelector(getNetworkName) + const t = useI18nContext(); + const dispatch = useDispatch(); + const alertState = useSelector(getAlertState); + const networkName = useSelector(getNetworkName); - const onClose = () => dispatch(dismissAlert()) + const onClose = () => dispatch(dismissAlert()); const footer = ( <> @@ -42,8 +42,8 @@ const InvalidCustomNetworkAlert = ({ history }) => { - ) + ); return ( { ])}

    - ) -} + ); +}; InvalidCustomNetworkAlert.propTypes = { history: PropTypes.object.isRequired, -} +}; -export default InvalidCustomNetworkAlert +export default InvalidCustomNetworkAlert; diff --git a/ui/app/components/app/alerts/unconnected-account-alert/index.js b/ui/app/components/app/alerts/unconnected-account-alert/index.js index 495f14c33..bfa1b9362 100644 --- a/ui/app/components/app/alerts/unconnected-account-alert/index.js +++ b/ui/app/components/app/alerts/unconnected-account-alert/index.js @@ -1 +1 @@ -export { default } from './unconnected-account-alert' +export { default } from './unconnected-account-alert'; diff --git a/ui/app/components/app/alerts/unconnected-account-alert/tests/unconnected-account-alert.test.js b/ui/app/components/app/alerts/unconnected-account-alert/tests/unconnected-account-alert.test.js index d16ec36c0..701ffa163 100644 --- a/ui/app/components/app/alerts/unconnected-account-alert/tests/unconnected-account-alert.test.js +++ b/ui/app/components/app/alerts/unconnected-account-alert/tests/unconnected-account-alert.test.js @@ -1,21 +1,21 @@ -import assert from 'assert' -import React from 'react' +import assert from 'assert'; +import React from 'react'; -import sinon from 'sinon' -import thunk from 'redux-thunk' +import sinon from 'sinon'; +import thunk from 'redux-thunk'; -import { fireEvent } from '@testing-library/react' -import configureMockStore from 'redux-mock-store' +import { fireEvent } from '@testing-library/react'; +import configureMockStore from 'redux-mock-store'; -import { renderWithProvider } from '../../../../../../../test/lib/render-helpers' +import { renderWithProvider } from '../../../../../../../test/lib/render-helpers'; -import * as actions from '../../../../../store/actions' -import UnconnectedAccountAlert from '..' +import * as actions from '../../../../../store/actions'; +import UnconnectedAccountAlert from '..'; describe('Unconnected Account Alert', function () { - const network = '123' + const network = '123'; - const selectedAddress = '0xec1adf982415d2ef5ec55899b9bfb8bc0f29251b' + const selectedAddress = '0xec1adf982415d2ef5ec55899b9bfb8bc0f29251b'; const identities = { '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc': { @@ -26,7 +26,7 @@ describe('Unconnected Account Alert', function () { address: '0xec1adf982415d2ef5ec55899b9bfb8bc0f29251b', name: 'Account 2', }, - } + }; const accounts = { '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc': { @@ -37,14 +37,14 @@ describe('Unconnected Account Alert', function () { address: '0xec1adf982415d2ef5ec55899b9bfb8bc0f29251b', balance: '0x0', }, - } + }; const cachedBalances = { 123: { '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc': '0x0', '0xec1adf982415d2ef5ec55899b9bfb8bc0f29251b': '0x0', }, - } + }; const keyrings = [ { @@ -54,7 +54,7 @@ describe('Unconnected Account Alert', function () { '0xec1adf982415d2ef5ec55899b9bfb8bc0f29251b', ], }, - ] + ]; const mockState = { metamask: { @@ -102,63 +102,69 @@ describe('Unconnected Account Alert', function () { unconnectedAccount: { state: 'OPEN', }, - } + }; afterEach(function () { - sinon.restore() - }) + sinon.restore(); + }); it('checks that checkbox is checked', function () { - const store = configureMockStore()(mockState) + const store = configureMockStore()(mockState); - const { getByRole } = renderWithProvider(, store) + const { getByRole } = renderWithProvider( + , + store, + ); - const dontShowCheckbox = getByRole('checkbox') + const dontShowCheckbox = getByRole('checkbox'); - assert.strictEqual(dontShowCheckbox.checked, false) - fireEvent.click(dontShowCheckbox) - assert.strictEqual(dontShowCheckbox.checked, true) - }) + assert.strictEqual(dontShowCheckbox.checked, false); + fireEvent.click(dontShowCheckbox); + assert.strictEqual(dontShowCheckbox.checked, true); + }); it('clicks dismiss button and calls dismissAlert action', function () { - const store = configureMockStore()(mockState) + const store = configureMockStore()(mockState); - const { getByText } = renderWithProvider(, store) + const { getByText } = renderWithProvider( + , + store, + ); - const dismissButton = getByText(/dismiss/u) - fireEvent.click(dismissButton) + const dismissButton = getByText(/dismiss/u); + fireEvent.click(dismissButton); assert.strictEqual( store.getActions()[0].type, 'unconnectedAccount/dismissAlert', - ) - }) + ); + }); it('clicks Dont Show checkbox and dismiss to call disable alert request action', async function () { - sinon.stub(actions, 'setAlertEnabledness').returns(() => Promise.resolve()) + sinon.stub(actions, 'setAlertEnabledness').returns(() => Promise.resolve()); - const store = configureMockStore([thunk])(mockState) + const store = configureMockStore([thunk])(mockState); const { getByText, getByRole } = renderWithProvider( , store, - ) + ); - const dismissButton = getByText(/dismiss/u) - const dontShowCheckbox = getByRole('checkbox') + const dismissButton = getByText(/dismiss/u); + const dontShowCheckbox = getByRole('checkbox'); - fireEvent.click(dontShowCheckbox) - fireEvent.click(dismissButton) + fireEvent.click(dontShowCheckbox); + fireEvent.click(dismissButton); setImmediate(() => { assert.strictEqual( store.getActions()[0].type, 'unconnectedAccount/disableAlertRequested', - ) + ); assert.strictEqual( store.getActions()[1].type, 'unconnectedAccount/disableAlertSucceeded', - ) - }) - }) -}) + ); + }); + }); +}); diff --git a/ui/app/components/app/alerts/unconnected-account-alert/unconnected-account-alert.js b/ui/app/components/app/alerts/unconnected-account-alert/unconnected-account-alert.js index ce6e236aa..c73de3f84 100644 --- a/ui/app/components/app/alerts/unconnected-account-alert/unconnected-account-alert.js +++ b/ui/app/components/app/alerts/unconnected-account-alert/unconnected-account-alert.js @@ -1,45 +1,47 @@ -import React, { useState } from 'react' -import { useDispatch, useSelector } from 'react-redux' +import React, { useState } from 'react'; +import { useDispatch, useSelector } from 'react-redux'; -import { ALERT_STATE } from '../../../../ducks/alerts' +import { ALERT_STATE } from '../../../../ducks/alerts'; import { connectAccount, dismissAlert, dismissAndDisableAlert, getAlertState, switchToAccount, -} from '../../../../ducks/alerts/unconnected-account' +} from '../../../../ducks/alerts/unconnected-account'; import { getOriginOfCurrentTab, getOrderedConnectedAccountsForActiveTab, getSelectedAddress, getSelectedIdentity, -} from '../../../../selectors' -import { isExtensionUrl } from '../../../../helpers/utils/util' -import Popover from '../../../ui/popover' -import Button from '../../../ui/button' -import Checkbox from '../../../ui/check-box' -import Tooltip from '../../../ui/tooltip' -import ConnectedAccountsList from '../../connected-accounts-list' -import { useI18nContext } from '../../../../hooks/useI18nContext' +} from '../../../../selectors'; +import { isExtensionUrl } from '../../../../helpers/utils/util'; +import Popover from '../../../ui/popover'; +import Button from '../../../ui/button'; +import Checkbox from '../../../ui/check-box'; +import Tooltip from '../../../ui/tooltip'; +import ConnectedAccountsList from '../../connected-accounts-list'; +import { useI18nContext } from '../../../../hooks/useI18nContext'; -const { ERROR, LOADING } = ALERT_STATE +const { ERROR, LOADING } = ALERT_STATE; const UnconnectedAccountAlert = () => { - const t = useI18nContext() - const dispatch = useDispatch() - const alertState = useSelector(getAlertState) - const connectedAccounts = useSelector(getOrderedConnectedAccountsForActiveTab) - const origin = useSelector(getOriginOfCurrentTab) - const selectedIdentity = useSelector(getSelectedIdentity) - const selectedAddress = useSelector(getSelectedAddress) - const [dontShowThisAgain, setDontShowThisAgain] = useState(false) + const t = useI18nContext(); + const dispatch = useDispatch(); + const alertState = useSelector(getAlertState); + const connectedAccounts = useSelector( + getOrderedConnectedAccountsForActiveTab, + ); + const origin = useSelector(getOriginOfCurrentTab); + const selectedIdentity = useSelector(getSelectedIdentity); + const selectedAddress = useSelector(getSelectedAddress); + const [dontShowThisAgain, setDontShowThisAgain] = useState(false); const onClose = async () => { return dontShowThisAgain ? await dispatch(dismissAndDisableAlert()) - : dispatch(dismissAlert()) - } + : dispatch(dismissAlert()); + }; const footer = ( <> @@ -81,7 +83,7 @@ const UnconnectedAccountAlert = () => { - ) + ); return ( { shouldRenderListOptions={false} /> - ) -} + ); +}; -export default UnconnectedAccountAlert +export default UnconnectedAccountAlert; diff --git a/ui/app/components/app/app-header/app-header.component.js b/ui/app/components/app/app-header/app-header.component.js index c8e388880..1694362c6 100644 --- a/ui/app/components/app/app-header/app-header.component.js +++ b/ui/app/components/app/app-header/app-header.component.js @@ -1,10 +1,10 @@ -import React, { PureComponent } from 'react' -import PropTypes from 'prop-types' -import classnames from 'classnames' -import Identicon from '../../ui/identicon' -import MetaFoxLogo from '../../ui/metafox-logo' -import { DEFAULT_ROUTE } from '../../../helpers/constants/routes' -import NetworkDisplay from '../network-display' +import React, { PureComponent } from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; +import Identicon from '../../ui/identicon'; +import MetaFoxLogo from '../../ui/metafox-logo'; +import { DEFAULT_ROUTE } from '../../../helpers/constants/routes'; +import NetworkDisplay from '../network-display'; export default class AppHeader extends PureComponent { static propTypes = { @@ -20,16 +20,16 @@ export default class AppHeader extends PureComponent { disableNetworkIndicator: PropTypes.bool, isAccountMenuOpen: PropTypes.bool, onClick: PropTypes.func, - } + }; static contextTypes = { t: PropTypes.func, metricsEvent: PropTypes.func, - } + }; handleNetworkIndicatorClick(event) { - event.preventDefault() - event.stopPropagation() + event.preventDefault(); + event.stopPropagation(); const { networkDropdownOpen, @@ -37,10 +37,10 @@ export default class AppHeader extends PureComponent { hideNetworkDropdown, disabled, disableNetworkIndicator, - } = this.props + } = this.props; if (disabled || disableNetworkIndicator) { - return + return; } if (networkDropdownOpen === false) { @@ -50,10 +50,10 @@ export default class AppHeader extends PureComponent { action: 'Home', name: 'Opened Network Menu', }, - }) - showNetworkDropdown() + }); + showNetworkDropdown(); } else { - hideNetworkDropdown() + hideNetworkDropdown(); } } @@ -64,7 +64,7 @@ export default class AppHeader extends PureComponent { selectedAddress, disabled, isAccountMenuOpen, - } = this.props + } = this.props; return ( isUnlocked && ( @@ -81,15 +81,15 @@ export default class AppHeader extends PureComponent { action: 'Home', name: 'Opened Main Menu', }, - }) - toggleAccountMenu() + }); + toggleAccountMenu(); } }} > ) - ) + ); } render() { @@ -100,7 +100,7 @@ export default class AppHeader extends PureComponent { disableNetworkIndicator, disabled, onClick, - } = this.props + } = this.props; return (
    { if (onClick) { - await onClick() + await onClick(); } - history.push(DEFAULT_ROUTE) + history.push(DEFAULT_ROUTE); }} />
    @@ -134,6 +134,6 @@ export default class AppHeader extends PureComponent {
    - ) + ); } } diff --git a/ui/app/components/app/app-header/app-header.container.js b/ui/app/components/app/app-header/app-header.container.js index 955f2f320..d1751c67a 100644 --- a/ui/app/components/app/app-header/app-header.container.js +++ b/ui/app/components/app/app-header/app-header.container.js @@ -1,20 +1,20 @@ -import { connect } from 'react-redux' -import { withRouter } from 'react-router-dom' -import { compose } from 'redux' +import { connect } from 'react-redux'; +import { withRouter } from 'react-router-dom'; +import { compose } from 'redux'; -import * as actions from '../../../store/actions' -import AppHeader from './app-header.component' +import * as actions from '../../../store/actions'; +import AppHeader from './app-header.component'; const mapStateToProps = (state) => { - const { appState, metamask } = state - const { networkDropdownOpen } = appState + const { appState, metamask } = state; + const { networkDropdownOpen } = appState; const { network, provider, selectedAddress, isUnlocked, isAccountMenuOpen, - } = metamask + } = metamask; return { networkDropdownOpen, @@ -23,18 +23,18 @@ const mapStateToProps = (state) => { selectedAddress, isUnlocked, isAccountMenuOpen, - } -} + }; +}; const mapDispatchToProps = (dispatch) => { return { showNetworkDropdown: () => dispatch(actions.showNetworkDropdown()), hideNetworkDropdown: () => dispatch(actions.hideNetworkDropdown()), toggleAccountMenu: () => dispatch(actions.toggleAccountMenu()), - } -} + }; +}; export default compose( withRouter, connect(mapStateToProps, mapDispatchToProps), -)(AppHeader) +)(AppHeader); diff --git a/ui/app/components/app/app-header/index.js b/ui/app/components/app/app-header/index.js index 6de2f9c78..4fbba4306 100644 --- a/ui/app/components/app/app-header/index.js +++ b/ui/app/components/app/app-header/index.js @@ -1 +1 @@ -export { default } from './app-header.container' +export { default } from './app-header.container'; diff --git a/ui/app/components/app/app-header/tests/app-header.test.js b/ui/app/components/app/app-header/tests/app-header.test.js index c736d6549..40045defc 100644 --- a/ui/app/components/app/app-header/tests/app-header.test.js +++ b/ui/app/components/app/app-header/tests/app-header.test.js @@ -1,13 +1,13 @@ -import assert from 'assert' -import React from 'react' -import sinon from 'sinon' -import { shallow } from 'enzyme' -import MetaFoxLogo from '../../../ui/metafox-logo' -import AppHeader from '..' -import NetworkDisplay from '../../network-display' +import assert from 'assert'; +import React from 'react'; +import sinon from 'sinon'; +import { shallow } from 'enzyme'; +import MetaFoxLogo from '../../../ui/metafox-logo'; +import AppHeader from '..'; +import NetworkDisplay from '../../network-display'; describe('App Header', function () { - let wrapper + let wrapper; const props = { hideNetworkDropdown: sinon.spy(), @@ -24,7 +24,7 @@ describe('App Header', function () { networkDropdownOpen: false, isAccountMenuOpen: false, isUnlocked: true, - } + }; beforeEach(function () { wrapper = shallow(, { @@ -32,65 +32,65 @@ describe('App Header', function () { t: (str) => str, metricsEvent: () => undefined, }, - }) - }) + }); + }); afterEach(function () { - props.toggleAccountMenu.resetHistory() - }) + props.toggleAccountMenu.resetHistory(); + }); describe('App Header Logo', function () { it('routes to default route when logo is clicked', function () { - const appLogo = wrapper.find(MetaFoxLogo) - appLogo.simulate('click') - assert(props.history.push.calledOnce) - assert.strictEqual(props.history.push.getCall(0).args[0], '/') - }) - }) + const appLogo = wrapper.find(MetaFoxLogo); + appLogo.simulate('click'); + assert(props.history.push.calledOnce); + assert.strictEqual(props.history.push.getCall(0).args[0], '/'); + }); + }); describe('Network', function () { it('shows network dropdown when networkDropdownOpen is false', function () { - const network = wrapper.find(NetworkDisplay) + const network = wrapper.find(NetworkDisplay); network.simulate('click', { preventDefault: () => undefined, stopPropagation: () => undefined, - }) + }); - assert(props.showNetworkDropdown.calledOnce) - }) + assert(props.showNetworkDropdown.calledOnce); + }); it('hides network dropdown when networkDropdownOpen is true', function () { - wrapper.setProps({ networkDropdownOpen: true }) - const network = wrapper.find(NetworkDisplay) + wrapper.setProps({ networkDropdownOpen: true }); + const network = wrapper.find(NetworkDisplay); network.simulate('click', { preventDefault: () => undefined, stopPropagation: () => undefined, - }) + }); - assert(props.hideNetworkDropdown.calledOnce) - }) + assert(props.hideNetworkDropdown.calledOnce); + }); it('hides network indicator', function () { - wrapper.setProps({ hideNetworkIndicator: true }) - const network = wrapper.find({ network: 'test' }) - assert.strictEqual(network.length, 0) - }) - }) + wrapper.setProps({ hideNetworkIndicator: true }); + const network = wrapper.find({ network: 'test' }); + assert.strictEqual(network.length, 0); + }); + }); describe('Account Menu', function () { it('toggles account menu', function () { - const accountMenu = wrapper.find('.account-menu__icon') - accountMenu.simulate('click') - assert(props.toggleAccountMenu.calledOnce) - }) + const accountMenu = wrapper.find('.account-menu__icon'); + accountMenu.simulate('click'); + assert(props.toggleAccountMenu.calledOnce); + }); it('does not toggle account menu when disabled', function () { - wrapper.setProps({ disabled: true }) - const accountMenu = wrapper.find('.account-menu__icon') - accountMenu.simulate('click') - assert(props.toggleAccountMenu.notCalled) - }) - }) -}) + wrapper.setProps({ disabled: true }); + const accountMenu = wrapper.find('.account-menu__icon'); + accountMenu.simulate('click'); + assert(props.toggleAccountMenu.notCalled); + }); + }); +}); diff --git a/ui/app/components/app/asset-list-item/asset-list-item.js b/ui/app/components/app/asset-list-item/asset-list-item.js index b09fb3c3f..8672a8c8e 100644 --- a/ui/app/components/app/asset-list-item/asset-list-item.js +++ b/ui/app/components/app/asset-list-item/asset-list-item.js @@ -1,18 +1,18 @@ -import React, { useMemo } from 'react' -import PropTypes from 'prop-types' -import classnames from 'classnames' -import { useDispatch } from 'react-redux' -import { useHistory } from 'react-router-dom' -import Identicon from '../../ui/identicon' -import ListItem from '../../ui/list-item' -import Tooltip from '../../ui/tooltip' -import InfoIcon from '../../ui/icon/info-icon.component' -import Button from '../../ui/button' -import { useI18nContext } from '../../../hooks/useI18nContext' -import { useMetricEvent } from '../../../hooks/useMetricEvent' -import { updateSendToken } from '../../../store/actions' -import { SEND_ROUTE } from '../../../helpers/constants/routes' -import { SEVERITIES } from '../../../helpers/constants/design-system' +import React, { useMemo } from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; +import { useDispatch } from 'react-redux'; +import { useHistory } from 'react-router-dom'; +import Identicon from '../../ui/identicon'; +import ListItem from '../../ui/list-item'; +import Tooltip from '../../ui/tooltip'; +import InfoIcon from '../../ui/icon/info-icon.component'; +import Button from '../../ui/button'; +import { useI18nContext } from '../../../hooks/useI18nContext'; +import { useMetricEvent } from '../../../hooks/useMetricEvent'; +import { updateSendToken } from '../../../store/actions'; +import { SEND_ROUTE } from '../../../helpers/constants/routes'; +import { SEVERITIES } from '../../../helpers/constants/design-system'; const AssetListItem = ({ className, @@ -27,16 +27,16 @@ const AssetListItem = ({ primary, secondary, }) => { - const t = useI18nContext() - const dispatch = useDispatch() - const history = useHistory() + const t = useI18nContext(); + const dispatch = useDispatch(); + const history = useHistory(); const sendTokenEvent = useMetricEvent({ eventOpts: { category: 'Navigation', action: 'Home', name: 'Clicked Send: Token', }, - }) + }); const titleIcon = warning ? ( - ) : null + ) : null; const midContent = warning ? ( <>
    {warning}
    - ) : null + ) : null; const sendTokenButton = useMemo(() => { if (tokenAddress === null || tokenAddress === undefined) { - return null + return null; } return ( - ) + ); }, [ tokenSymbol, sendTokenEvent, @@ -87,7 +87,7 @@ const AssetListItem = ({ history, t, dispatch, - ]) + ]); return ( } /> - ) -} + ); +}; AssetListItem.propTypes = { className: PropTypes.string, @@ -140,7 +140,7 @@ AssetListItem.propTypes = { warning: PropTypes.node, primary: PropTypes.string, secondary: PropTypes.string, -} +}; AssetListItem.defaultProps = { className: undefined, @@ -149,6 +149,6 @@ AssetListItem.defaultProps = { tokenAddress: undefined, tokenImage: undefined, warning: undefined, -} +}; -export default AssetListItem +export default AssetListItem; diff --git a/ui/app/components/app/asset-list-item/index.js b/ui/app/components/app/asset-list-item/index.js index 48b7de3d2..9e8c6dcf2 100644 --- a/ui/app/components/app/asset-list-item/index.js +++ b/ui/app/components/app/asset-list-item/index.js @@ -1 +1 @@ -export { default } from './asset-list-item' +export { default } from './asset-list-item'; diff --git a/ui/app/components/app/asset-list/asset-list.js b/ui/app/components/app/asset-list/asset-list.js index b576e0bf3..7a817d1cb 100644 --- a/ui/app/components/app/asset-list/asset-list.js +++ b/ui/app/components/app/asset-list/asset-list.js @@ -1,51 +1,51 @@ -import React from 'react' -import PropTypes from 'prop-types' -import { useSelector } from 'react-redux' -import { useHistory } from 'react-router-dom' -import AddTokenButton from '../add-token-button' -import TokenList from '../token-list' -import { ADD_TOKEN_ROUTE } from '../../../helpers/constants/routes' -import AssetListItem from '../asset-list-item' -import { PRIMARY, SECONDARY } from '../../../helpers/constants/common' -import { useMetricEvent } from '../../../hooks/useMetricEvent' -import { useUserPreferencedCurrency } from '../../../hooks/useUserPreferencedCurrency' +import React from 'react'; +import PropTypes from 'prop-types'; +import { useSelector } from 'react-redux'; +import { useHistory } from 'react-router-dom'; +import AddTokenButton from '../add-token-button'; +import TokenList from '../token-list'; +import { ADD_TOKEN_ROUTE } from '../../../helpers/constants/routes'; +import AssetListItem from '../asset-list-item'; +import { PRIMARY, SECONDARY } from '../../../helpers/constants/common'; +import { useMetricEvent } from '../../../hooks/useMetricEvent'; +import { useUserPreferencedCurrency } from '../../../hooks/useUserPreferencedCurrency'; import { getCurrentAccountWithSendEtherInfo, getNativeCurrency, getShouldShowFiat, -} from '../../../selectors' -import { useCurrencyDisplay } from '../../../hooks/useCurrencyDisplay' +} from '../../../selectors'; +import { useCurrencyDisplay } from '../../../hooks/useCurrencyDisplay'; const AssetList = ({ onClickAsset }) => { - const history = useHistory() + const history = useHistory(); const selectedAccountBalance = useSelector( (state) => getCurrentAccountWithSendEtherInfo(state).balance, - ) - const nativeCurrency = useSelector(getNativeCurrency) - const showFiat = useSelector(getShouldShowFiat) + ); + const nativeCurrency = useSelector(getNativeCurrency); + const showFiat = useSelector(getShouldShowFiat); const selectTokenEvent = useMetricEvent({ eventOpts: { category: 'Navigation', action: 'Token Menu', name: 'Clicked Token', }, - }) + }); const addTokenEvent = useMetricEvent({ eventOpts: { category: 'Navigation', action: 'Token Menu', name: 'Clicked "Add Token"', }, - }) + }); const { currency: primaryCurrency, numberOfDecimals: primaryNumberOfDecimals, - } = useUserPreferencedCurrency(PRIMARY, { ethNumberOfDecimals: 4 }) + } = useUserPreferencedCurrency(PRIMARY, { ethNumberOfDecimals: 4 }); const { currency: secondaryCurrency, numberOfDecimals: secondaryNumberOfDecimals, - } = useUserPreferencedCurrency(SECONDARY, { ethNumberOfDecimals: 4 }) + } = useUserPreferencedCurrency(SECONDARY, { ethNumberOfDecimals: 4 }); const [, primaryCurrencyProperties] = useCurrencyDisplay( selectedAccountBalance, @@ -53,7 +53,7 @@ const AssetList = ({ onClickAsset }) => { numberOfDecimals: primaryNumberOfDecimals, currency: primaryCurrency, }, - ) + ); const [secondaryCurrencyDisplay] = useCurrencyDisplay( selectedAccountBalance, @@ -61,7 +61,7 @@ const AssetList = ({ onClickAsset }) => { numberOfDecimals: secondaryNumberOfDecimals, currency: secondaryCurrency, }, - ) + ); return ( <> @@ -74,22 +74,22 @@ const AssetList = ({ onClickAsset }) => { /> { - onClickAsset(tokenAddress) - selectTokenEvent() + onClickAsset(tokenAddress); + selectTokenEvent(); }} /> { - history.push(ADD_TOKEN_ROUTE) - addTokenEvent() + history.push(ADD_TOKEN_ROUTE); + addTokenEvent(); }} /> - ) -} + ); +}; AssetList.propTypes = { onClickAsset: PropTypes.func.isRequired, -} +}; -export default AssetList +export default AssetList; diff --git a/ui/app/components/app/asset-list/index.js b/ui/app/components/app/asset-list/index.js index 47ee5ce9f..7906ebe8e 100644 --- a/ui/app/components/app/asset-list/index.js +++ b/ui/app/components/app/asset-list/index.js @@ -1 +1 @@ -export { default } from './asset-list' +export { default } from './asset-list'; diff --git a/ui/app/components/app/confirm-page-container/confirm-detail-row/confirm-detail-row.component.js b/ui/app/components/app/confirm-page-container/confirm-detail-row/confirm-detail-row.component.js index 280c5662f..4ee4ecbd4 100644 --- a/ui/app/components/app/confirm-page-container/confirm-detail-row/confirm-detail-row.component.js +++ b/ui/app/components/app/confirm-page-container/confirm-detail-row/confirm-detail-row.component.js @@ -1,8 +1,8 @@ -import React from 'react' -import PropTypes from 'prop-types' -import classnames from 'classnames' -import UserPreferencedCurrencyDisplay from '../../user-preferenced-currency-display' -import { PRIMARY, SECONDARY } from '../../../../helpers/constants/common' +import React from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; +import UserPreferencedCurrencyDisplay from '../../user-preferenced-currency-display'; +import { PRIMARY, SECONDARY } from '../../../../helpers/constants/common'; const ConfirmDetailRow = (props) => { const { @@ -14,7 +14,7 @@ const ConfirmDetailRow = (props) => { headerText, headerTextClassName, value, - } = props + } = props; return (
    @@ -62,8 +62,8 @@ const ConfirmDetailRow = (props) => { )}
    - ) -} + ); +}; ConfirmDetailRow.propTypes = { headerText: PropTypes.string, @@ -74,6 +74,6 @@ ConfirmDetailRow.propTypes = { primaryText: PropTypes.oneOfType([PropTypes.string, PropTypes.node]), secondaryText: PropTypes.string, value: PropTypes.string, -} +}; -export default ConfirmDetailRow +export default ConfirmDetailRow; diff --git a/ui/app/components/app/confirm-page-container/confirm-detail-row/index.js b/ui/app/components/app/confirm-page-container/confirm-detail-row/index.js index 056afff04..18e608271 100644 --- a/ui/app/components/app/confirm-page-container/confirm-detail-row/index.js +++ b/ui/app/components/app/confirm-page-container/confirm-detail-row/index.js @@ -1 +1 @@ -export { default } from './confirm-detail-row.component' +export { default } from './confirm-detail-row.component'; diff --git a/ui/app/components/app/confirm-page-container/confirm-detail-row/tests/confirm-detail-row.component.test.js b/ui/app/components/app/confirm-page-container/confirm-detail-row/tests/confirm-detail-row.component.test.js index ed6ac21f8..c019f3a5b 100644 --- a/ui/app/components/app/confirm-page-container/confirm-detail-row/tests/confirm-detail-row.component.test.js +++ b/ui/app/components/app/confirm-page-container/confirm-detail-row/tests/confirm-detail-row.component.test.js @@ -1,16 +1,16 @@ -import assert from 'assert' -import React from 'react' -import { shallow } from 'enzyme' -import sinon from 'sinon' -import ConfirmDetailRow from '../confirm-detail-row.component' +import assert from 'assert'; +import React from 'react'; +import { shallow } from 'enzyme'; +import sinon from 'sinon'; +import ConfirmDetailRow from '../confirm-detail-row.component'; const propsMethodSpies = { onHeaderClick: sinon.spy(), -} +}; describe('Confirm Detail Row Component', function () { describe('render', function () { - let wrapper + let wrapper; beforeEach(function () { wrapper = shallow( @@ -25,12 +25,12 @@ describe('Confirm Detail Row Component', function () { headerText="mockHeaderText" headerTextClassName="mockHeaderClass" />, - ) - }) + ); + }); it('should render a div with a confirm-detail-row class', function () { - assert.strictEqual(wrapper.find('div.confirm-detail-row').length, 1) - }) + assert.strictEqual(wrapper.find('div.confirm-detail-row').length, 1); + }); it('should render the label as a child of the confirm-detail-row__label', function () { assert.strictEqual( @@ -39,8 +39,8 @@ describe('Confirm Detail Row Component', function () { .childAt(0) .text(), 'mockLabel', - ) - }) + ); + }); it('should render the headerText as a child of the confirm-detail-row__header-text', function () { assert.strictEqual( @@ -51,8 +51,8 @@ describe('Confirm Detail Row Component', function () { .childAt(0) .text(), 'mockHeaderText', - ) - }) + ); + }); it('should render the primaryText as a child of the confirm-detail-row__primary', function () { assert.strictEqual( @@ -61,8 +61,8 @@ describe('Confirm Detail Row Component', function () { .childAt(0) .text(), 'mockFiatText', - ) - }) + ); + }); it('should render the ethText as a child of the confirm-detail-row__secondary', function () { assert.strictEqual( @@ -71,26 +71,26 @@ describe('Confirm Detail Row Component', function () { .childAt(0) .text(), 'mockEthText', - ) - }) + ); + }); it('should set the fiatTextColor on confirm-detail-row__primary', function () { assert.strictEqual( wrapper.find('.confirm-detail-row__primary').props().style.color, 'mockColor', - ) - }) + ); + }); it('should assure the confirm-detail-row__header-text classname is correct', function () { assert.strictEqual( wrapper.find('.confirm-detail-row__header-text').props().className, 'confirm-detail-row__header-text mockHeaderClass', - ) - }) + ); + }); it('should call onHeaderClick when headerText div gets clicked', function () { - wrapper.find('.confirm-detail-row__header-text').props().onClick() - assert.ok(propsMethodSpies.onHeaderClick.calledOnce) - }) - }) -}) + wrapper.find('.confirm-detail-row__header-text').props().onClick(); + assert.ok(propsMethodSpies.onHeaderClick.calledOnce); + }); + }); +}); diff --git a/ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-content.component.js b/ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-content.component.js index d3542345e..9009f9feb 100644 --- a/ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-content.component.js +++ b/ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-content.component.js @@ -1,10 +1,10 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import classnames from 'classnames' -import { Tabs, Tab } from '../../../ui/tabs' -import ErrorMessage from '../../../ui/error-message' -import { PageContainerFooter } from '../../../ui/page-container' -import { ConfirmPageContainerSummary, ConfirmPageContainerWarning } from '.' +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; +import { Tabs, Tab } from '../../../ui/tabs'; +import ErrorMessage from '../../../ui/error-message'; +import { PageContainerFooter } from '../../../ui/page-container'; +import { ConfirmPageContainerSummary, ConfirmPageContainerWarning } from '.'; export default class ConfirmPageContainerContent extends Component { static propTypes = { @@ -31,19 +31,19 @@ export default class ConfirmPageContainerContent extends Component { disabled: PropTypes.bool, unapprovedTxCount: PropTypes.number, rejectNText: PropTypes.string, - } + }; renderContent() { - const { detailsComponent, dataComponent } = this.props + const { detailsComponent, dataComponent } = this.props; if (detailsComponent && dataComponent) { - return this.renderTabs() + return this.renderTabs(); } - return detailsComponent || dataComponent + return detailsComponent || dataComponent; } renderTabs() { - const { detailsComponent, dataComponent } = this.props + const { detailsComponent, dataComponent } = this.props; return ( @@ -54,7 +54,7 @@ export default class ConfirmPageContainerContent extends Component { {dataComponent} - ) + ); } render() { @@ -81,7 +81,7 @@ export default class ConfirmPageContainerContent extends Component { unapprovedTxCount, rejectNText, origin, - } = this.props + } = this.props; return (
    @@ -118,6 +118,6 @@ export default class ConfirmPageContainerContent extends Component { {unapprovedTxCount > 1 && {rejectNText}}
    - ) + ); } } diff --git a/ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-summary/confirm-page-container-summary.component.js b/ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-summary/confirm-page-container-summary.component.js index 49efb86e5..cd33ee357 100644 --- a/ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-summary/confirm-page-container-summary.component.js +++ b/ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-summary/confirm-page-container-summary.component.js @@ -1,7 +1,7 @@ -import React from 'react' -import PropTypes from 'prop-types' -import classnames from 'classnames' -import Identicon from '../../../../ui/identicon' +import React from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; +import Identicon from '../../../../ui/identicon'; const ConfirmPageContainerSummary = (props) => { const { @@ -15,7 +15,7 @@ const ConfirmPageContainerSummary = (props) => { nonce, assetImage, origin, - } = props + } = props; return (
    @@ -49,8 +49,8 @@ const ConfirmPageContainerSummary = (props) => {
    )} - ) -} + ); +}; ConfirmPageContainerSummary.propTypes = { action: PropTypes.string, @@ -63,6 +63,6 @@ ConfirmPageContainerSummary.propTypes = { nonce: PropTypes.string, assetImage: PropTypes.string, origin: PropTypes.string.isRequired, -} +}; -export default ConfirmPageContainerSummary +export default ConfirmPageContainerSummary; diff --git a/ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-summary/index.js b/ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-summary/index.js index ed1b28cf2..a5ddf1cdf 100644 --- a/ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-summary/index.js +++ b/ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-summary/index.js @@ -1 +1 @@ -export { default } from './confirm-page-container-summary.component' +export { default } from './confirm-page-container-summary.component'; diff --git a/ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-warning/confirm-page-container-warning.component.js b/ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-warning/confirm-page-container-warning.component.js index a79cabcd6..eef1ed09e 100644 --- a/ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-warning/confirm-page-container-warning.component.js +++ b/ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-warning/confirm-page-container-warning.component.js @@ -1,5 +1,5 @@ -import React from 'react' -import PropTypes from 'prop-types' +import React from 'react'; +import PropTypes from 'prop-types'; const ConfirmPageContainerWarning = (props) => { return ( @@ -13,11 +13,11 @@ const ConfirmPageContainerWarning = (props) => { {props.warning} - ) -} + ); +}; ConfirmPageContainerWarning.propTypes = { warning: PropTypes.string, -} +}; -export default ConfirmPageContainerWarning +export default ConfirmPageContainerWarning; diff --git a/ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-warning/index.js b/ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-warning/index.js index 6e48bd144..dce2fb7a9 100644 --- a/ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-warning/index.js +++ b/ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-warning/index.js @@ -1 +1 @@ -export { default } from './confirm-page-container-warning.component' +export { default } from './confirm-page-container-warning.component'; diff --git a/ui/app/components/app/confirm-page-container/confirm-page-container-content/index.js b/ui/app/components/app/confirm-page-container/confirm-page-container-content/index.js index 4dfd89d92..15f290dba 100644 --- a/ui/app/components/app/confirm-page-container/confirm-page-container-content/index.js +++ b/ui/app/components/app/confirm-page-container/confirm-page-container-content/index.js @@ -1,3 +1,3 @@ -export { default } from './confirm-page-container-content.component' -export { default as ConfirmPageContainerSummary } from './confirm-page-container-summary' -export { default as ConfirmPageContainerWarning } from './confirm-page-container-warning' +export { default } from './confirm-page-container-content.component'; +export { default as ConfirmPageContainerSummary } from './confirm-page-container-summary'; +export { default as ConfirmPageContainerWarning } from './confirm-page-container-warning'; diff --git a/ui/app/components/app/confirm-page-container/confirm-page-container-header/confirm-page-container-header.component.js b/ui/app/components/app/confirm-page-container/confirm-page-container-header/confirm-page-container-header.component.js index bdc6295d6..0c17f41fa 100644 --- a/ui/app/components/app/confirm-page-container/confirm-page-container-header/confirm-page-container-header.component.js +++ b/ui/app/components/app/confirm-page-container/confirm-page-container-header/confirm-page-container-header.component.js @@ -1,15 +1,15 @@ -import React from 'react' -import PropTypes from 'prop-types' +import React from 'react'; +import PropTypes from 'prop-types'; import { ENVIRONMENT_TYPE_POPUP, ENVIRONMENT_TYPE_NOTIFICATION, -} from '../../../../../../shared/constants/app' -import { getEnvironmentType } from '../../../../../../app/scripts/lib/util' -import NetworkDisplay from '../../network-display' -import Identicon from '../../../ui/identicon' -import { shortenAddress } from '../../../../helpers/utils/util' -import AccountMismatchWarning from '../../../ui/account-mismatch-warning/account-mismatch-warning.component' -import { useI18nContext } from '../../../../hooks/useI18nContext' +} from '../../../../../../shared/constants/app'; +import { getEnvironmentType } from '../../../../../../app/scripts/lib/util'; +import NetworkDisplay from '../../network-display'; +import Identicon from '../../../ui/identicon'; +import { shortenAddress } from '../../../../helpers/utils/util'; +import AccountMismatchWarning from '../../../ui/account-mismatch-warning/account-mismatch-warning.component'; +import { useI18nContext } from '../../../../hooks/useI18nContext'; export default function ConfirmPageContainerHeader({ onEdit, @@ -18,14 +18,14 @@ export default function ConfirmPageContainerHeader({ showAccountInHeader, children, }) { - const t = useI18nContext() - const windowType = getEnvironmentType() + const t = useI18nContext(); + const windowType = getEnvironmentType(); const isFullScreen = windowType !== ENVIRONMENT_TYPE_NOTIFICATION && - windowType !== ENVIRONMENT_TYPE_POPUP + windowType !== ENVIRONMENT_TYPE_POPUP; if (!showEdit && isFullScreen) { - return null + return null; } return (
    @@ -60,7 +60,7 @@ export default function ConfirmPageContainerHeader({
    {children} - ) + ); } ConfirmPageContainerHeader.propTypes = { @@ -69,4 +69,4 @@ ConfirmPageContainerHeader.propTypes = { showEdit: PropTypes.bool, onEdit: PropTypes.func, children: PropTypes.node, -} +}; diff --git a/ui/app/components/app/confirm-page-container/confirm-page-container-header/index.js b/ui/app/components/app/confirm-page-container/confirm-page-container-header/index.js index 71feb6931..b8c53f3b0 100644 --- a/ui/app/components/app/confirm-page-container/confirm-page-container-header/index.js +++ b/ui/app/components/app/confirm-page-container/confirm-page-container-header/index.js @@ -1 +1 @@ -export { default } from './confirm-page-container-header.component' +export { default } from './confirm-page-container-header.component'; diff --git a/ui/app/components/app/confirm-page-container/confirm-page-container-navigation/confirm-page-container-navigation.component.js b/ui/app/components/app/confirm-page-container/confirm-page-container-navigation/confirm-page-container-navigation.component.js index 010262b52..20e9c0ce5 100755 --- a/ui/app/components/app/confirm-page-container/confirm-page-container-navigation/confirm-page-container-navigation.component.js +++ b/ui/app/components/app/confirm-page-container/confirm-page-container-navigation/confirm-page-container-navigation.component.js @@ -1,5 +1,5 @@ -import React from 'react' -import PropTypes from 'prop-types' +import React from 'react'; +import PropTypes from 'prop-types'; const ConfirmPageContainerNavigation = (props) => { const { @@ -13,7 +13,7 @@ const ConfirmPageContainerNavigation = (props) => { lastTx, ofText, requestsWaitingText, - } = props + } = props; return (
    {
    - ) -} + ); +}; ConfirmPageContainerNavigation.propTypes = { totalTx: PropTypes.number, @@ -95,6 +95,6 @@ ConfirmPageContainerNavigation.propTypes = { lastTx: PropTypes.string, ofText: PropTypes.string, requestsWaitingText: PropTypes.string, -} +}; -export default ConfirmPageContainerNavigation +export default ConfirmPageContainerNavigation; diff --git a/ui/app/components/app/confirm-page-container/confirm-page-container-navigation/index.js b/ui/app/components/app/confirm-page-container/confirm-page-container-navigation/index.js index d97c1b447..133d52557 100755 --- a/ui/app/components/app/confirm-page-container/confirm-page-container-navigation/index.js +++ b/ui/app/components/app/confirm-page-container/confirm-page-container-navigation/index.js @@ -1 +1 @@ -export { default } from './confirm-page-container-navigation.component' +export { default } from './confirm-page-container-navigation.component'; diff --git a/ui/app/components/app/confirm-page-container/confirm-page-container.component.js b/ui/app/components/app/confirm-page-container/confirm-page-container.component.js index 623b31102..c713935f9 100644 --- a/ui/app/components/app/confirm-page-container/confirm-page-container.component.js +++ b/ui/app/components/app/confirm-page-container/confirm-page-container.component.js @@ -1,17 +1,17 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import SenderToRecipient from '../../ui/sender-to-recipient' -import { PageContainerFooter } from '../../ui/page-container' +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import SenderToRecipient from '../../ui/sender-to-recipient'; +import { PageContainerFooter } from '../../ui/page-container'; import { ConfirmPageContainerHeader, ConfirmPageContainerContent, ConfirmPageContainerNavigation, -} from '.' +} from '.'; export default class ConfirmPageContainer extends Component { static contextTypes = { t: PropTypes.func, - } + }; static propTypes = { // Header @@ -59,7 +59,7 @@ export default class ConfirmPageContainer extends Component { onCancel: PropTypes.func, onSubmit: PropTypes.func, disabled: PropTypes.bool, - } + }; render() { const { @@ -103,9 +103,9 @@ export default class ConfirmPageContainer extends Component { hideSenderToRecipient, showAccountInHeader, origin, - } = this.props + } = this.props; const renderAssetImage = - contentComponent || (!contentComponent && !identiconAddress) + contentComponent || (!contentComponent && !identiconAddress); return (
    @@ -182,6 +182,6 @@ export default class ConfirmPageContainer extends Component { )}
    - ) + ); } } diff --git a/ui/app/components/app/confirm-page-container/index.js b/ui/app/components/app/confirm-page-container/index.js index 62fc9cedc..d9bc6f5a8 100644 --- a/ui/app/components/app/confirm-page-container/index.js +++ b/ui/app/components/app/confirm-page-container/index.js @@ -1,9 +1,9 @@ -export { default } from './confirm-page-container.component' -export { default as ConfirmPageContainerHeader } from './confirm-page-container-header' -export { default as ConfirmDetailRow } from './confirm-detail-row' -export { default as ConfirmPageContainerNavigation } from './confirm-page-container-navigation' +export { default } from './confirm-page-container.component'; +export { default as ConfirmPageContainerHeader } from './confirm-page-container-header'; +export { default as ConfirmDetailRow } from './confirm-detail-row'; +export { default as ConfirmPageContainerNavigation } from './confirm-page-container-navigation'; export { default as ConfirmPageContainerContent, ConfirmPageContainerSummary, -} from './confirm-page-container-content' +} from './confirm-page-container-content'; diff --git a/ui/app/components/app/connected-accounts-list/connected-accounts-list-item/connected-accounts-list-item.component.js b/ui/app/components/app/connected-accounts-list/connected-accounts-list-item/connected-accounts-list-item.component.js index 8a1fc0852..4ec24a7b4 100644 --- a/ui/app/components/app/connected-accounts-list/connected-accounts-list-item/connected-accounts-list-item.component.js +++ b/ui/app/components/app/connected-accounts-list/connected-accounts-list-item/connected-accounts-list-item.component.js @@ -1,12 +1,12 @@ -import classnames from 'classnames' -import PropTypes from 'prop-types' -import React, { PureComponent } from 'react' -import Identicon from '../../../ui/identicon' +import classnames from 'classnames'; +import PropTypes from 'prop-types'; +import React, { PureComponent } from 'react'; +import Identicon from '../../../ui/identicon'; export default class ConnectedAccountsListItem extends PureComponent { static contextTypes = { t: PropTypes.func.isRequired, - } + }; static propTypes = { address: PropTypes.string.isRequired, @@ -15,16 +15,16 @@ export default class ConnectedAccountsListItem extends PureComponent { status: PropTypes.string, action: PropTypes.node, options: PropTypes.node, - } + }; static defaultProps = { className: null, options: null, action: null, - } + }; render() { - const { address, className, name, status, action, options } = this.props + const { address, className, name, status, action, options } = this.props; return (
    @@ -49,6 +49,6 @@ export default class ConnectedAccountsListItem extends PureComponent {
    {options} - ) + ); } } diff --git a/ui/app/components/app/connected-accounts-list/connected-accounts-list-item/index.js b/ui/app/components/app/connected-accounts-list/connected-accounts-list-item/index.js index 3fb33c23e..7543d6dc1 100644 --- a/ui/app/components/app/connected-accounts-list/connected-accounts-list-item/index.js +++ b/ui/app/components/app/connected-accounts-list/connected-accounts-list-item/index.js @@ -1 +1 @@ -export { default } from './connected-accounts-list-item.component' +export { default } from './connected-accounts-list-item.component'; diff --git a/ui/app/components/app/connected-accounts-list/connected-accounts-list-options/connected-accounts-list-options.component.js b/ui/app/components/app/connected-accounts-list/connected-accounts-list-options/connected-accounts-list-options.component.js index c647bca40..1850b11d7 100644 --- a/ui/app/components/app/connected-accounts-list/connected-accounts-list-options/connected-accounts-list-options.component.js +++ b/ui/app/components/app/connected-accounts-list/connected-accounts-list-options/connected-accounts-list-options.component.js @@ -1,6 +1,6 @@ -import PropTypes from 'prop-types' -import React, { useState } from 'react' -import { Menu } from '../../../ui/menu' +import PropTypes from 'prop-types'; +import React, { useState } from 'react'; +import { Menu } from '../../../ui/menu'; const ConnectedAccountsListOptions = ({ children, @@ -8,7 +8,7 @@ const ConnectedAccountsListOptions = ({ onHideOptions, show, }) => { - const [optionsButtonElement, setOptionsButtonElement] = useState(null) + const [optionsButtonElement, setOptionsButtonElement] = useState(null); return ( <> @@ -31,14 +31,14 @@ const ConnectedAccountsListOptions = ({ ) : null} - ) -} + ); +}; ConnectedAccountsListOptions.propTypes = { children: PropTypes.node.isRequired, onHideOptions: PropTypes.func.isRequired, onShowOptions: PropTypes.func.isRequired, show: PropTypes.bool.isRequired, -} +}; -export default ConnectedAccountsListOptions +export default ConnectedAccountsListOptions; diff --git a/ui/app/components/app/connected-accounts-list/connected-accounts-list-options/index.js b/ui/app/components/app/connected-accounts-list/connected-accounts-list-options/index.js index 6e4db3446..c876378eb 100644 --- a/ui/app/components/app/connected-accounts-list/connected-accounts-list-options/index.js +++ b/ui/app/components/app/connected-accounts-list/connected-accounts-list-options/index.js @@ -1 +1 @@ -export { default } from './connected-accounts-list-options.component' +export { default } from './connected-accounts-list-options.component'; diff --git a/ui/app/components/app/connected-accounts-list/connected-accounts-list.component.js b/ui/app/components/app/connected-accounts-list/connected-accounts-list.component.js index 501af8195..cb1fa5861 100644 --- a/ui/app/components/app/connected-accounts-list/connected-accounts-list.component.js +++ b/ui/app/components/app/connected-accounts-list/connected-accounts-list.component.js @@ -1,17 +1,17 @@ -import PropTypes from 'prop-types' -import React, { PureComponent } from 'react' -import { MenuItem } from '../../ui/menu' -import ConnectedAccountsListItem from './connected-accounts-list-item' -import ConnectedAccountsListOptions from './connected-accounts-list-options' +import PropTypes from 'prop-types'; +import React, { PureComponent } from 'react'; +import { MenuItem } from '../../ui/menu'; +import ConnectedAccountsListItem from './connected-accounts-list-item'; +import ConnectedAccountsListOptions from './connected-accounts-list-options'; export default class ConnectedAccountsList extends PureComponent { static contextTypes = { t: PropTypes.func.isRequired, - } + }; static defaultProps = { accountToConnect: null, - } + }; static propTypes = { accountToConnect: PropTypes.shape({ @@ -35,47 +35,47 @@ export default class ConnectedAccountsList extends PureComponent { `Warning: Failed prop type: '${propName}' of component '${componentName}' must be a boolean. Received: ${typeof props[ propName ]}`, - ) + ); } else if (props[propName] && !props.removePermittedAccount) { return new Error( `Warning: Failed prop type: '${propName}' of component '${componentName}' requires prop 'removePermittedAccount'.`, - ) + ); } - return undefined + return undefined; }, - } + }; state = { accountWithOptionsShown: null, - } + }; disconnectAccount = () => { - this.hideAccountOptions() - this.props.removePermittedAccount(this.state.accountWithOptionsShown) - } + this.hideAccountOptions(); + this.props.removePermittedAccount(this.state.accountWithOptionsShown); + }; switchAccount = (address) => { - this.hideAccountOptions() - this.props.setSelectedAddress(address) - } + this.hideAccountOptions(); + this.props.setSelectedAddress(address); + }; hideAccountOptions = () => { - this.setState({ accountWithOptionsShown: null }) - } + this.setState({ accountWithOptionsShown: null }); + }; showAccountOptions = (address) => { - this.setState({ accountWithOptionsShown: address }) - } + this.setState({ accountWithOptionsShown: address }); + }; renderUnconnectedAccount() { - const { accountToConnect, connectAccount } = this.props - const { t } = this.context + const { accountToConnect, connectAccount } = this.props; + const { t } = this.context; if (!accountToConnect) { - return null + return null; } - const { address, name } = accountToConnect + const { address, name } = accountToConnect; return ( } /> - ) + ); } renderListItemOptions(address) { - const { accountWithOptionsShown } = this.state - const { t } = this.context + const { accountWithOptionsShown } = this.state; + const { t } = this.context; return ( - ) + ); } renderListItemAction(address) { - const { t } = this.context + const { t } = this.context; return ( {t('switchToThisAccount')} - ) + ); } render() { @@ -132,8 +132,8 @@ export default class ConnectedAccountsList extends PureComponent { connectedAccounts, selectedAddress, shouldRenderListOptions, - } = this.props - const { t } = this.context + } = this.props; + const { t } = this.context; return ( <> @@ -157,10 +157,10 @@ export default class ConnectedAccountsList extends PureComponent { : this.renderListItemAction(address) } /> - ) + ); })} - ) + ); } } diff --git a/ui/app/components/app/connected-accounts-list/index.js b/ui/app/components/app/connected-accounts-list/index.js index ee436f58a..1df443c46 100644 --- a/ui/app/components/app/connected-accounts-list/index.js +++ b/ui/app/components/app/connected-accounts-list/index.js @@ -1 +1 @@ -export { default } from './connected-accounts-list.component' +export { default } from './connected-accounts-list.component'; diff --git a/ui/app/components/app/connected-accounts-permissions/connected-accounts-permissions.component.js b/ui/app/components/app/connected-accounts-permissions/connected-accounts-permissions.component.js index 4b6e21678..11e521c55 100644 --- a/ui/app/components/app/connected-accounts-permissions/connected-accounts-permissions.component.js +++ b/ui/app/components/app/connected-accounts-permissions/connected-accounts-permissions.component.js @@ -1,16 +1,16 @@ -import classnames from 'classnames' -import PropTypes from 'prop-types' -import React, { PureComponent } from 'react' -import CheckBox from '../../ui/check-box' +import classnames from 'classnames'; +import PropTypes from 'prop-types'; +import React, { PureComponent } from 'react'; +import CheckBox from '../../ui/check-box'; export default class ConnectedAccountsPermissions extends PureComponent { static contextTypes = { t: PropTypes.func.isRequired, - } + }; static defaultProps = { permissions: [], - } + }; static propTypes = { permissions: PropTypes.arrayOf( @@ -18,25 +18,25 @@ export default class ConnectedAccountsPermissions extends PureComponent { key: PropTypes.string.isRequired, }), ), - } + }; state = { expanded: false, - } + }; toggleExpanded = () => { this.setState((prevState) => ({ expanded: !prevState.expanded, - })) - } + })); + }; render() { - const { permissions } = this.props - const { t } = this.context - const { expanded } = this.state + const { permissions } = this.props; + const { t } = this.context; + const { expanded } = this.state; if (permissions.length === 0) { - return null + return null; } return ( @@ -81,6 +81,6 @@ export default class ConnectedAccountsPermissions extends PureComponent { - ) + ); } } diff --git a/ui/app/components/app/connected-accounts-permissions/index.js b/ui/app/components/app/connected-accounts-permissions/index.js index 6c6113c82..46bbd1ee9 100644 --- a/ui/app/components/app/connected-accounts-permissions/index.js +++ b/ui/app/components/app/connected-accounts-permissions/index.js @@ -1 +1 @@ -export { default } from './connected-accounts-permissions.component' +export { default } from './connected-accounts-permissions.component'; diff --git a/ui/app/components/app/connected-sites-list/connected-sites-list.component.js b/ui/app/components/app/connected-sites-list/connected-sites-list.component.js index 16bc23bd6..1e9513a58 100644 --- a/ui/app/components/app/connected-sites-list/connected-sites-list.component.js +++ b/ui/app/components/app/connected-sites-list/connected-sites-list.component.js @@ -1,12 +1,12 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import SiteIcon from '../../ui/site-icon' -import { stripHttpSchemes } from '../../../helpers/utils/util' +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import SiteIcon from '../../ui/site-icon'; +import { stripHttpSchemes } from '../../../helpers/utils/util'; export default class ConnectedSitesList extends Component { static contextTypes = { t: PropTypes.func, - } + }; static propTypes = { connectedDomains: PropTypes.arrayOf( @@ -19,11 +19,11 @@ export default class ConnectedSitesList extends Component { ).isRequired, onDisconnect: PropTypes.func.isRequired, domainHostCount: PropTypes.objectOf(PropTypes.number).isRequired, - } + }; render() { - const { connectedDomains, onDisconnect } = this.props - const { t } = this.context + const { connectedDomains, onDisconnect } = this.props; + const { t } = this.context; return (
    @@ -49,16 +49,16 @@ export default class ConnectedSitesList extends Component { ))}
    - ) + ); } getDomainDisplayName(domain) { if (domain.extensionId) { - return this.context.t('externalExtension') + return this.context.t('externalExtension'); } return this.props.domainHostCount[domain.host] > 1 ? domain.origin - : stripHttpSchemes(domain.origin) + : stripHttpSchemes(domain.origin); } } diff --git a/ui/app/components/app/connected-sites-list/index.js b/ui/app/components/app/connected-sites-list/index.js index 0f0a8e6f3..70dc9f763 100644 --- a/ui/app/components/app/connected-sites-list/index.js +++ b/ui/app/components/app/connected-sites-list/index.js @@ -1 +1 @@ -export { default } from './connected-sites-list.component' +export { default } from './connected-sites-list.component'; diff --git a/ui/app/components/app/connected-status-indicator/connected-status-indicator.js b/ui/app/components/app/connected-status-indicator/connected-status-indicator.js index 31cb2b137..b8596d58f 100644 --- a/ui/app/components/app/connected-status-indicator/connected-status-indicator.js +++ b/ui/app/components/app/connected-status-indicator/connected-status-indicator.js @@ -1,66 +1,68 @@ -import React from 'react' -import PropTypes from 'prop-types' -import { useSelector } from 'react-redux' -import { findKey } from 'lodash' +import React from 'react'; +import PropTypes from 'prop-types'; +import { useSelector } from 'react-redux'; +import { findKey } from 'lodash'; import { STATUS_CONNECTED, STATUS_CONNECTED_TO_ANOTHER_ACCOUNT, STATUS_NOT_CONNECTED, -} from '../../../helpers/constants/connected-sites' -import ColorIndicator from '../../ui/color-indicator' -import { COLORS } from '../../../helpers/constants/design-system' -import { useI18nContext } from '../../../hooks/useI18nContext' +} from '../../../helpers/constants/connected-sites'; +import ColorIndicator from '../../ui/color-indicator'; +import { COLORS } from '../../../helpers/constants/design-system'; +import { useI18nContext } from '../../../hooks/useI18nContext'; import { getAddressConnectedDomainMap, getOriginOfCurrentTab, getSelectedAddress, -} from '../../../selectors' +} from '../../../selectors'; export default function ConnectedStatusIndicator({ onClick }) { - const t = useI18nContext() + const t = useI18nContext(); - const selectedAddress = useSelector(getSelectedAddress) - const addressConnectedDomainMap = useSelector(getAddressConnectedDomainMap) - const originOfCurrentTab = useSelector(getOriginOfCurrentTab) + const selectedAddress = useSelector(getSelectedAddress); + const addressConnectedDomainMap = useSelector(getAddressConnectedDomainMap); + const originOfCurrentTab = useSelector(getOriginOfCurrentTab); - const selectedAddressDomainMap = addressConnectedDomainMap[selectedAddress] + const selectedAddressDomainMap = addressConnectedDomainMap[selectedAddress]; const currentTabIsConnectedToSelectedAddress = Boolean( selectedAddressDomainMap && selectedAddressDomainMap[originOfCurrentTab], - ) - let status + ); + let status; if (currentTabIsConnectedToSelectedAddress) { - status = STATUS_CONNECTED + status = STATUS_CONNECTED; } else if (findKey(addressConnectedDomainMap, originOfCurrentTab)) { - status = STATUS_CONNECTED_TO_ANOTHER_ACCOUNT + status = STATUS_CONNECTED_TO_ANOTHER_ACCOUNT; } else { - status = STATUS_NOT_CONNECTED + status = STATUS_NOT_CONNECTED; } - let indicatorType = ColorIndicator.TYPES.OUTLINE - let indicatorColor = COLORS.UI4 + let indicatorType = ColorIndicator.TYPES.OUTLINE; + let indicatorColor = COLORS.UI4; if (status === STATUS_CONNECTED) { - indicatorColor = COLORS.SUCCESS1 - indicatorType = ColorIndicator.TYPES.PARTIAL + indicatorColor = COLORS.SUCCESS1; + indicatorType = ColorIndicator.TYPES.PARTIAL; } else if (status === STATUS_CONNECTED_TO_ANOTHER_ACCOUNT) { - indicatorColor = COLORS.ALERT1 + indicatorColor = COLORS.ALERT1; } const text = - status === STATUS_CONNECTED ? t('statusConnected') : t('statusNotConnected') + status === STATUS_CONNECTED + ? t('statusConnected') + : t('statusNotConnected'); return ( - ) + ); } ConnectedStatusIndicator.defaultProps = { onClick: undefined, -} +}; ConnectedStatusIndicator.propTypes = { onClick: PropTypes.func, -} +}; diff --git a/ui/app/components/app/connected-status-indicator/index.js b/ui/app/components/app/connected-status-indicator/index.js index 4f654fae4..01c4a66ee 100644 --- a/ui/app/components/app/connected-status-indicator/index.js +++ b/ui/app/components/app/connected-status-indicator/index.js @@ -1 +1 @@ -export { default } from './connected-status-indicator' +export { default } from './connected-status-indicator'; diff --git a/ui/app/components/app/contact-list/contact-list.component.js b/ui/app/components/app/contact-list/contact-list.component.js index 3b62741e6..04e3a3abd 100644 --- a/ui/app/components/app/contact-list/contact-list.component.js +++ b/ui/app/components/app/contact-list/contact-list.component.js @@ -1,7 +1,7 @@ -import React, { PureComponent } from 'react' -import PropTypes from 'prop-types' -import Button from '../../ui/button' -import RecipientGroup from './recipient-group/recipient-group.component' +import React, { PureComponent } from 'react'; +import PropTypes from 'prop-types'; +import Button from '../../ui/button'; +import RecipientGroup from './recipient-group/recipient-group.component'; export default class ContactList extends PureComponent { static propTypes = { @@ -11,22 +11,22 @@ export default class ContactList extends PureComponent { selectRecipient: PropTypes.func, children: PropTypes.node, selectedAddress: PropTypes.string, - } + }; static contextTypes = { t: PropTypes.func, - } + }; state = { isShowingAllRecent: false, - } + }; renderRecents() { - const { t } = this.context - const { isShowingAllRecent } = this.state - const nonContacts = this.props.searchForRecents() + const { t } = this.context; + const { isShowingAllRecent } = this.state; + const nonContacts = this.props.searchForRecents(); - const showLoadMore = !isShowingAllRecent && nonContacts.length > 2 + const showLoadMore = !isShowingAllRecent && nonContacts.length > 2; return (
    @@ -46,28 +46,28 @@ export default class ContactList extends PureComponent { )}
    - ) + ); } renderAddressBook() { - const contacts = this.props.searchForContacts() + const contacts = this.props.searchForContacts(); const contactGroups = contacts.reduce((acc, contact) => { - const firstLetter = contact.name.slice(0, 1).toUpperCase() - acc[firstLetter] = acc[firstLetter] || [] - const bucket = acc[firstLetter] - bucket.push(contact) - return acc - }, {}) + const firstLetter = contact.name.slice(0, 1).toUpperCase(); + acc[firstLetter] = acc[firstLetter] || []; + const bucket = acc[firstLetter]; + bucket.push(contact); + return acc; + }, {}); return Object.entries(contactGroups) .sort(([letter1], [letter2]) => { if (letter1 > letter2) { - return 1 + return 1; } else if (letter1 === letter2) { - return 0 + return 0; } - return -1 + return -1; }) .map(([letter, groupItems]) => ( - )) + )); } renderMyAccounts() { - const myAccounts = this.props.searchForMyAccounts() + const myAccounts = this.props.searchForMyAccounts(); return ( - ) + ); } render() { @@ -98,7 +98,7 @@ export default class ContactList extends PureComponent { searchForRecents, searchForContacts, searchForMyAccounts, - } = this.props + } = this.props; return (
    @@ -107,6 +107,6 @@ export default class ContactList extends PureComponent { {searchForContacts && this.renderAddressBook()} {searchForMyAccounts && this.renderMyAccounts()}
    - ) + ); } } diff --git a/ui/app/components/app/contact-list/index.js b/ui/app/components/app/contact-list/index.js index d90c29b2b..0b7ef4615 100644 --- a/ui/app/components/app/contact-list/index.js +++ b/ui/app/components/app/contact-list/index.js @@ -1 +1 @@ -export { default } from './contact-list.component' +export { default } from './contact-list.component'; diff --git a/ui/app/components/app/contact-list/recipient-group/index.js b/ui/app/components/app/contact-list/recipient-group/index.js index 7d827523f..75eeac29a 100644 --- a/ui/app/components/app/contact-list/recipient-group/index.js +++ b/ui/app/components/app/contact-list/recipient-group/index.js @@ -1 +1 @@ -export { default } from './recipient-group.component' +export { default } from './recipient-group.component'; diff --git a/ui/app/components/app/contact-list/recipient-group/recipient-group.component.js b/ui/app/components/app/contact-list/recipient-group/recipient-group.component.js index a50b2eea3..d57854917 100644 --- a/ui/app/components/app/contact-list/recipient-group/recipient-group.component.js +++ b/ui/app/components/app/contact-list/recipient-group/recipient-group.component.js @@ -1,11 +1,11 @@ -import React from 'react' -import PropTypes from 'prop-types' -import classnames from 'classnames' -import Identicon from '../../../ui/identicon' -import { ellipsify } from '../../../../pages/send/send.utils' +import React from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; +import Identicon from '../../../ui/identicon'; +import { ellipsify } from '../../../../pages/send/send.utils'; function addressesEqual(address1, address2) { - return String(address1).toLowerCase() === String(address2).toLowerCase() + return String(address1).toLowerCase() === String(address2).toLowerCase(); } export default function RecipientGroup({ @@ -15,7 +15,7 @@ export default function RecipientGroup({ selectedAddress, }) { if (!items || !items.length) { - return null + return null; } return ( @@ -54,7 +54,7 @@ export default function RecipientGroup({ ))} - ) + ); } RecipientGroup.propTypes = { @@ -67,4 +67,4 @@ RecipientGroup.propTypes = { ), onSelect: PropTypes.func.isRequired, selectedAddress: PropTypes.string, -} +}; diff --git a/ui/app/components/app/dropdowns/components/dropdown.js b/ui/app/components/app/dropdowns/components/dropdown.js index da67c700f..0c1a7f88f 100644 --- a/ui/app/components/app/dropdowns/components/dropdown.js +++ b/ui/app/components/app/dropdowns/components/dropdown.js @@ -1,6 +1,6 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import MenuDroppo from '../../menu-droppo' +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import MenuDroppo from '../../menu-droppo'; export class Dropdown extends Component { render() { @@ -12,7 +12,7 @@ export class Dropdown extends Component { innerStyle, children, useCssTransition, - } = this.props + } = this.props; const innerStyleDefaults = { borderRadius: '4px', @@ -20,7 +20,7 @@ export class Dropdown extends Component { background: 'rgba(0, 0, 0, 0.8)', boxShadow: 'rgba(0, 0, 0, 0.15) 0px 2px 2px 2px', ...innerStyle, - } + }; return ( {children} - ) + ); } } Dropdown.defaultProps = { useCssTransition: false, -} +}; Dropdown.propTypes = { isOpen: PropTypes.bool.isRequired, @@ -60,23 +60,23 @@ Dropdown.propTypes = { innerStyle: PropTypes.object, useCssTransition: PropTypes.bool, containerClassName: PropTypes.string, -} +}; export class DropdownMenuItem extends Component { render() { - const { onClick, closeMenu, children, style } = this.props + const { onClick, closeMenu, children, style } = this.props; return (
  • { - onClick() - closeMenu() + onClick(); + closeMenu(); }} onKeyPress={(event) => { if (event.key === 'Enter') { - onClick() - closeMenu() + onClick(); + closeMenu(); } }} style={{ @@ -95,7 +95,7 @@ export class DropdownMenuItem extends Component { > {children}
  • - ) + ); } } @@ -104,4 +104,4 @@ DropdownMenuItem.propTypes = { onClick: PropTypes.func.isRequired, children: PropTypes.node, style: PropTypes.object, -} +}; diff --git a/ui/app/components/app/dropdowns/network-dropdown.js b/ui/app/components/app/dropdowns/network-dropdown.js index 4de92e718..d01c71ba9 100644 --- a/ui/app/components/app/dropdowns/network-dropdown.js +++ b/ui/app/components/app/dropdowns/network-dropdown.js @@ -1,22 +1,22 @@ -import PropTypes from 'prop-types' -import React, { Component } from 'react' -import { connect } from 'react-redux' -import { withRouter } from 'react-router-dom' -import { compose } from 'redux' -import * as actions from '../../../store/actions' -import { openAlert as displayInvalidCustomNetworkAlert } from '../../../ducks/alerts/invalid-custom-network' +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { connect } from 'react-redux'; +import { withRouter } from 'react-router-dom'; +import { compose } from 'redux'; +import * as actions from '../../../store/actions'; +import { openAlert as displayInvalidCustomNetworkAlert } from '../../../ducks/alerts/invalid-custom-network'; import { NETWORKS_ROUTE, NETWORKS_FORM_ROUTE, -} from '../../../helpers/constants/routes' -import { ENVIRONMENT_TYPE_FULLSCREEN } from '../../../../../shared/constants/app' -import { NETWORK_TYPE_RPC } from '../../../../../shared/constants/network' -import { isPrefixedFormattedHexString } from '../../../../../shared/modules/utils' -import { getEnvironmentType } from '../../../../../app/scripts/lib/util' +} from '../../../helpers/constants/routes'; +import { ENVIRONMENT_TYPE_FULLSCREEN } from '../../../../../shared/constants/app'; +import { NETWORK_TYPE_RPC } from '../../../../../shared/constants/network'; +import { isPrefixedFormattedHexString } from '../../../../../shared/modules/utils'; +import { getEnvironmentType } from '../../../../../app/scripts/lib/util'; -import ColorIndicator from '../../ui/color-indicator' -import { COLORS, SIZES } from '../../../helpers/constants/design-system' -import { Dropdown, DropdownMenuItem } from './components/dropdown' +import ColorIndicator from '../../ui/color-indicator'; +import { COLORS, SIZES } from '../../../helpers/constants/design-system'; +import { Dropdown, DropdownMenuItem } from './components/dropdown'; // classes from nodes of the toggle element. const notToggleElementClassnames = [ @@ -25,39 +25,39 @@ const notToggleElementClassnames = [ 'network-indicator', 'network-caret', 'network-component', -] +]; const DROP_DOWN_MENU_ITEM_STYLE = { fontSize: '16px', lineHeight: '20px', padding: '12px 0', -} +}; function mapStateToProps(state) { return { provider: state.metamask.provider, frequentRpcListDetail: state.metamask.frequentRpcListDetail || [], networkDropdownOpen: state.appState.networkDropdownOpen, - } + }; } function mapDispatchToProps(dispatch) { return { setProviderType: (type) => { - dispatch(actions.setProviderType(type)) + dispatch(actions.setProviderType(type)); }, setRpcTarget: (target, chainId, ticker, nickname) => { - dispatch(actions.setRpcTarget(target, chainId, ticker, nickname)) + dispatch(actions.setRpcTarget(target, chainId, ticker, nickname)); }, hideNetworkDropdown: () => dispatch(actions.hideNetworkDropdown()), setNetworksTabAddMode: (isInAddMode) => { - dispatch(actions.setNetworksTabAddMode(isInAddMode)) + dispatch(actions.setNetworksTabAddMode(isInAddMode)); }, setSelectedSettingsRpcUrl: (url) => { - dispatch(actions.setSelectedSettingsRpcUrl(url)) + dispatch(actions.setSelectedSettingsRpcUrl(url)); }, displayInvalidCustomNetworkAlert: (networkName) => { - dispatch(displayInvalidCustomNetworkAlert(networkName)) + dispatch(displayInvalidCustomNetworkAlert(networkName)); }, showConfirmDeleteNetworkModal: ({ target, onConfirm }) => { return dispatch( @@ -66,16 +66,16 @@ function mapDispatchToProps(dispatch) { target, onConfirm, }), - ) + ); }, - } + }; } class NetworkDropdown extends Component { static contextTypes = { t: PropTypes.func, metricsEvent: PropTypes.func, - } + }; static propTypes = { provider: PropTypes.shape({ @@ -94,14 +94,14 @@ class NetworkDropdown extends Component { history: PropTypes.object.isRequired, displayInvalidCustomNetworkAlert: PropTypes.func.isRequired, showConfirmDeleteNetworkModal: PropTypes.func.isRequired, - } + }; handleClick(newProviderType) { const { provider: { type: providerType }, setProviderType, - } = this.props - const { metricsEvent } = this.context + } = this.props; + const { metricsEvent } = this.context; metricsEvent({ eventOpts: { @@ -113,17 +113,17 @@ class NetworkDropdown extends Component { fromNetwork: providerType, toNetwork: newProviderType, }, - }) - setProviderType(newProviderType) + }); + setProviderType(newProviderType); } renderCustomRpcList(rpcListDetail, provider) { - const reversedRpcListDetail = rpcListDetail.slice().reverse() + const reversedRpcListDetail = rpcListDetail.slice().reverse(); return reversedRpcListDetail.map((entry) => { - const { rpcUrl, chainId, ticker = 'ETH', nickname = '' } = entry + const { rpcUrl, chainId, ticker = 'ETH', nickname = '' } = entry; const isCurrentRpcTarget = - provider.type === NETWORK_TYPE_RPC && rpcUrl === provider.rpcUrl + provider.type === NETWORK_TYPE_RPC && rpcUrl === provider.rpcUrl; return ( this.props.hideNetworkDropdown()} onClick={() => { if (isPrefixedFormattedHexString(chainId)) { - this.props.setRpcTarget(rpcUrl, chainId, ticker, nickname) + this.props.setRpcTarget(rpcUrl, chainId, ticker, nickname); } else { - this.props.displayInvalidCustomNetworkAlert(nickname || rpcUrl) + this.props.displayInvalidCustomNetworkAlert(nickname || rpcUrl); } }} style={{ @@ -165,46 +165,46 @@ class NetworkDropdown extends Component { { - e.stopPropagation() + e.stopPropagation(); this.props.showConfirmDeleteNetworkModal({ target: rpcUrl, onConfirm: () => undefined, - }) + }); }} /> )} - ) - }) + ); + }); } getNetworkName() { - const { provider } = this.props - const providerName = provider.type + const { provider } = this.props; + const providerName = provider.type; - let name + let name; if (providerName === 'mainnet') { - name = this.context.t('mainnet') + name = this.context.t('mainnet'); } else if (providerName === 'ropsten') { - name = this.context.t('ropsten') + name = this.context.t('ropsten'); } else if (providerName === 'kovan') { - name = this.context.t('kovan') + name = this.context.t('kovan'); } else if (providerName === 'rinkeby') { - name = this.context.t('rinkeby') + name = this.context.t('rinkeby'); } else if (providerName === 'goerli') { - name = this.context.t('goerli') + name = this.context.t('goerli'); } else { - name = provider.nickname || this.context.t('unknownNetwork') + name = provider.nickname || this.context.t('unknownNetwork'); } - return name + return name; } renderNetworkEntry(network) { const { provider: { type: providerType }, - } = this.props + } = this.props; return ( - ) + ); } render() { @@ -240,23 +240,23 @@ class NetworkDropdown extends Component { provider: { rpcUrl: activeNetwork }, setNetworksTabAddMode, setSelectedSettingsRpcUrl, - } = this.props - const rpcListDetail = this.props.frequentRpcListDetail - const isOpen = this.props.networkDropdownOpen + } = this.props; + const rpcListDetail = this.props.frequentRpcListDetail; + const isOpen = this.props.networkDropdownOpen; return ( { - const { classList } = event.target - const isInClassList = (className) => classList.contains(className) + const { classList } = event.target; + const isInClassList = (className) => classList.contains(className); const notToggleElementIndex = notToggleElementClassnames.findIndex( isInClassList, - ) + ); if (notToggleElementIndex === -1) { - event.stopPropagation() - this.props.hideNetworkDropdown() + event.stopPropagation(); + this.props.hideNetworkDropdown(); } }} containerClassName="network-droppo" @@ -294,9 +294,9 @@ class NetworkDropdown extends Component { getEnvironmentType() === ENVIRONMENT_TYPE_FULLSCREEN ? NETWORKS_ROUTE : NETWORKS_FORM_ROUTE, - ) - setSelectedSettingsRpcUrl('') - setNetworksTabAddMode(true) + ); + setSelectedSettingsRpcUrl(''); + setNetworksTabAddMode(true); }} style={DROP_DOWN_MENU_ITEM_STYLE} > @@ -321,11 +321,11 @@ class NetworkDropdown extends Component { - ) + ); } } export default compose( withRouter, connect(mapStateToProps, mapDispatchToProps), -)(NetworkDropdown) +)(NetworkDropdown); diff --git a/ui/app/components/app/dropdowns/simple-dropdown.js b/ui/app/components/app/dropdowns/simple-dropdown.js index a1a97a8b6..cafaa4e62 100644 --- a/ui/app/components/app/dropdowns/simple-dropdown.js +++ b/ui/app/components/app/dropdowns/simple-dropdown.js @@ -1,6 +1,6 @@ -import classnames from 'classnames' -import PropTypes from 'prop-types' -import React, { Component } from 'react' +import classnames from 'classnames'; +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; class SimpleDropdown extends Component { static propTypes = { @@ -8,41 +8,41 @@ class SimpleDropdown extends Component { placeholder: PropTypes.string, onSelect: PropTypes.func, selectedOption: PropTypes.string, - } + }; state = { isOpen: false, - } + }; getDisplayValue() { - const { selectedOption, options } = this.props - const matchesOption = (option) => option.value === selectedOption - const matchingOption = options.find(matchesOption) + const { selectedOption, options } = this.props; + const matchesOption = (option) => option.value === selectedOption; + const matchingOption = options.find(matchesOption); return matchingOption ? matchingOption.displayValue || matchingOption.value - : selectedOption + : selectedOption; } handleClose() { - this.setState({ isOpen: false }) + this.setState({ isOpen: false }); } toggleOpen() { this.setState((prevState) => ({ isOpen: !prevState.isOpen, - })) + })); } renderOptions() { - const { options, onSelect, selectedOption } = this.props + const { options, onSelect, selectedOption } = this.props; return (
    { - event.stopPropagation() - this.handleClose() + event.stopPropagation(); + this.handleClose(); }} />
    @@ -54,12 +54,12 @@ class SimpleDropdown extends Component { })} key={option.value} onClick={(event) => { - event.stopPropagation() + event.stopPropagation(); if (option.value !== selectedOption) { - onSelect(option.value) + onSelect(option.value); } - this.handleClose() + this.handleClose(); }} > {option.displayValue || option.value} @@ -67,12 +67,12 @@ class SimpleDropdown extends Component { ))}
    - ) + ); } render() { - const { placeholder } = this.props - const { isOpen } = this.state + const { placeholder } = this.props; + const { isOpen } = this.state; return (
    this.toggleOpen()}> @@ -82,8 +82,8 @@ class SimpleDropdown extends Component { {isOpen && this.renderOptions()}
    - ) + ); } } -export default SimpleDropdown +export default SimpleDropdown; diff --git a/ui/app/components/app/dropdowns/tests/dropdown.test.js b/ui/app/components/app/dropdowns/tests/dropdown.test.js index 7ceb8227c..63faf3341 100644 --- a/ui/app/components/app/dropdowns/tests/dropdown.test.js +++ b/ui/app/components/app/dropdowns/tests/dropdown.test.js @@ -1,13 +1,13 @@ -import assert from 'assert' -import React from 'react' -import sinon from 'sinon' -import { shallow } from 'enzyme' -import { DropdownMenuItem } from '../components/dropdown' +import assert from 'assert'; +import React from 'react'; +import sinon from 'sinon'; +import { shallow } from 'enzyme'; +import { DropdownMenuItem } from '../components/dropdown'; describe('Dropdown', function () { - let wrapper - const onClickSpy = sinon.spy() - const closeMenuSpy = sinon.spy() + let wrapper; + const onClickSpy = sinon.spy(); + const closeMenuSpy = sinon.spy(); beforeEach(function () { wrapper = shallow( @@ -16,20 +16,20 @@ describe('Dropdown', function () { style={{ test: 'style' }} closeMenu={closeMenuSpy} />, - ) - }) + ); + }); it('renders li with dropdown-menu-item class', function () { - assert.strictEqual(wrapper.find('li.dropdown-menu-item').length, 1) - }) + assert.strictEqual(wrapper.find('li.dropdown-menu-item').length, 1); + }); it('adds style based on props passed', function () { - assert.strictEqual(wrapper.prop('style').test, 'style') - }) + assert.strictEqual(wrapper.prop('style').test, 'style'); + }); it('simulates click event and calls onClick and closeMenu', function () { - wrapper.prop('onClick')() - assert.strictEqual(onClickSpy.callCount, 1) - assert.strictEqual(closeMenuSpy.callCount, 1) - }) -}) + wrapper.prop('onClick')(); + assert.strictEqual(onClickSpy.callCount, 1); + assert.strictEqual(closeMenuSpy.callCount, 1); + }); +}); diff --git a/ui/app/components/app/dropdowns/tests/network-dropdown.test.js b/ui/app/components/app/dropdowns/tests/network-dropdown.test.js index 50e607ac9..c7f872c6a 100644 --- a/ui/app/components/app/dropdowns/tests/network-dropdown.test.js +++ b/ui/app/components/app/dropdowns/tests/network-dropdown.test.js @@ -1,15 +1,15 @@ -import assert from 'assert' -import React from 'react' -import configureMockStore from 'redux-mock-store' -import thunk from 'redux-thunk' -import { mountWithRouter } from '../../../../../../test/lib/render-helpers' -import NetworkDropdown from '../network-dropdown' -import { DropdownMenuItem } from '../components/dropdown' -import ColorIndicator from '../../../ui/color-indicator' +import assert from 'assert'; +import React from 'react'; +import configureMockStore from 'redux-mock-store'; +import thunk from 'redux-thunk'; +import { mountWithRouter } from '../../../../../../test/lib/render-helpers'; +import NetworkDropdown from '../network-dropdown'; +import { DropdownMenuItem } from '../components/dropdown'; +import ColorIndicator from '../../../ui/color-indicator'; describe('Network Dropdown', function () { - let wrapper - const createMockStore = configureMockStore([thunk]) + let wrapper; + const createMockStore = configureMockStore([thunk]); describe('NetworkDropdown in appState in false', function () { const mockState = { @@ -22,22 +22,22 @@ describe('Network Dropdown', function () { appState: { networkDropdownOpen: false, }, - } + }; - const store = createMockStore(mockState) + const store = createMockStore(mockState); beforeEach(function () { - wrapper = mountWithRouter() - }) + wrapper = mountWithRouter(); + }); it('checks for network droppo class', function () { - assert.strictEqual(wrapper.find('.network-droppo').length, 1) - }) + assert.strictEqual(wrapper.find('.network-droppo').length, 1); + }); it('renders only one child when networkDropdown is false in state', function () { - assert.strictEqual(wrapper.children().length, 1) - }) - }) + assert.strictEqual(wrapper.children().length, 1); + }); + }); describe('NetworkDropdown in appState is true', function () { const mockState = { @@ -54,59 +54,59 @@ describe('Network Dropdown', function () { appState: { networkDropdownOpen: true, }, - } - const store = createMockStore(mockState) + }; + const store = createMockStore(mockState); beforeEach(function () { - wrapper = mountWithRouter() - }) + wrapper = mountWithRouter(); + }); it('renders 8 DropDownMenuItems ', function () { - assert.strictEqual(wrapper.find(DropdownMenuItem).length, 8) - }) + assert.strictEqual(wrapper.find(DropdownMenuItem).length, 8); + }); it('checks background color for first ColorIndicator', function () { - const colorIndicator = wrapper.find(ColorIndicator).at(0) - assert.strictEqual(colorIndicator.prop('color'), 'mainnet') - assert.strictEqual(colorIndicator.prop('borderColor'), 'mainnet') - }) + const colorIndicator = wrapper.find(ColorIndicator).at(0); + assert.strictEqual(colorIndicator.prop('color'), 'mainnet'); + assert.strictEqual(colorIndicator.prop('borderColor'), 'mainnet'); + }); it('checks background color for second ColorIndicator', function () { - const colorIndicator = wrapper.find(ColorIndicator).at(1) - assert.strictEqual(colorIndicator.prop('color'), 'ropsten') - assert.strictEqual(colorIndicator.prop('borderColor'), 'ropsten') - }) + const colorIndicator = wrapper.find(ColorIndicator).at(1); + assert.strictEqual(colorIndicator.prop('color'), 'ropsten'); + assert.strictEqual(colorIndicator.prop('borderColor'), 'ropsten'); + }); it('checks background color for third ColorIndicator', function () { - const colorIndicator = wrapper.find(ColorIndicator).at(2) - assert.strictEqual(colorIndicator.prop('color'), 'kovan') - assert.strictEqual(colorIndicator.prop('borderColor'), 'kovan') - }) + const colorIndicator = wrapper.find(ColorIndicator).at(2); + assert.strictEqual(colorIndicator.prop('color'), 'kovan'); + assert.strictEqual(colorIndicator.prop('borderColor'), 'kovan'); + }); it('checks background color for fourth ColorIndicator', function () { - const colorIndicator = wrapper.find(ColorIndicator).at(3) - assert.strictEqual(colorIndicator.prop('color'), 'rinkeby') - assert.strictEqual(colorIndicator.prop('borderColor'), 'rinkeby') - }) + const colorIndicator = wrapper.find(ColorIndicator).at(3); + assert.strictEqual(colorIndicator.prop('color'), 'rinkeby'); + assert.strictEqual(colorIndicator.prop('borderColor'), 'rinkeby'); + }); it('checks background color for fifth ColorIndicator', function () { - const colorIndicator = wrapper.find(ColorIndicator).at(4) - assert.strictEqual(colorIndicator.prop('color'), 'goerli') - assert.strictEqual(colorIndicator.prop('borderColor'), 'goerli') - }) + const colorIndicator = wrapper.find(ColorIndicator).at(4); + assert.strictEqual(colorIndicator.prop('color'), 'goerli'); + assert.strictEqual(colorIndicator.prop('borderColor'), 'goerli'); + }); it('checks background color for sixth ColorIndicator', function () { - const colorIndicator = wrapper.find(ColorIndicator).at(5) - const customNetworkGray = 'ui-2' - assert.strictEqual(colorIndicator.prop('color'), customNetworkGray) - assert.strictEqual(colorIndicator.prop('borderColor'), customNetworkGray) - }) + const colorIndicator = wrapper.find(ColorIndicator).at(5); + const customNetworkGray = 'ui-2'; + assert.strictEqual(colorIndicator.prop('color'), customNetworkGray); + assert.strictEqual(colorIndicator.prop('borderColor'), customNetworkGray); + }); it('checks dropdown for frequestRPCList from state', function () { assert.strictEqual( wrapper.find(DropdownMenuItem).at(6).text(), '✓http://localhost:7545', - ) - }) - }) -}) + ); + }); + }); +}); diff --git a/ui/app/components/app/gas-customization/advanced-gas-inputs/advanced-gas-inputs.component.js b/ui/app/components/app/gas-customization/advanced-gas-inputs/advanced-gas-inputs.component.js index a7c3270d0..e394b453a 100644 --- a/ui/app/components/app/gas-customization/advanced-gas-inputs/advanced-gas-inputs.component.js +++ b/ui/app/components/app/gas-customization/advanced-gas-inputs/advanced-gas-inputs.component.js @@ -1,14 +1,14 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import classnames from 'classnames' -import { debounce } from 'lodash' -import Tooltip from '../../../ui/tooltip' -import { MIN_GAS_LIMIT_DEC } from '../../../../pages/send/send.constants' +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; +import { debounce } from 'lodash'; +import Tooltip from '../../../ui/tooltip'; +import { MIN_GAS_LIMIT_DEC } from '../../../../pages/send/send.constants'; export default class AdvancedGasInputs extends Component { static contextTypes = { t: PropTypes.func, - } + }; static propTypes = { updateCustomGasPrice: PropTypes.func, @@ -20,55 +20,55 @@ export default class AdvancedGasInputs extends Component { isSpeedUp: PropTypes.bool, customGasLimitMessage: PropTypes.string, minimumGasLimit: PropTypes.number, - } + }; static defaultProps = { minimumGasLimit: Number(MIN_GAS_LIMIT_DEC), - } + }; constructor(props) { - super(props) + super(props); this.state = { gasPrice: this.props.customGasPrice, gasLimit: this.props.customGasLimit, - } - this.changeGasPrice = debounce(this.changeGasPrice, 500) - this.changeGasLimit = debounce(this.changeGasLimit, 500) + }; + this.changeGasPrice = debounce(this.changeGasPrice, 500); + this.changeGasLimit = debounce(this.changeGasLimit, 500); } componentDidUpdate(prevProps) { const { customGasPrice: prevCustomGasPrice, customGasLimit: prevCustomGasLimit, - } = prevProps - const { customGasPrice, customGasLimit } = this.props - const { gasPrice, gasLimit } = this.state + } = prevProps; + const { customGasPrice, customGasLimit } = this.props; + const { gasPrice, gasLimit } = this.state; if (customGasPrice !== prevCustomGasPrice && customGasPrice !== gasPrice) { - this.setState({ gasPrice: customGasPrice }) + this.setState({ gasPrice: customGasPrice }); } if (customGasLimit !== prevCustomGasLimit && customGasLimit !== gasLimit) { - this.setState({ gasLimit: customGasLimit }) + this.setState({ gasLimit: customGasLimit }); } } onChangeGasLimit = (e) => { - this.setState({ gasLimit: e.target.value }) - this.changeGasLimit({ target: { value: e.target.value } }) - } + this.setState({ gasLimit: e.target.value }); + this.changeGasLimit({ target: { value: e.target.value } }); + }; changeGasLimit = (e) => { - this.props.updateCustomGasLimit(Number(e.target.value)) - } + this.props.updateCustomGasLimit(Number(e.target.value)); + }; onChangeGasPrice = (e) => { - this.setState({ gasPrice: e.target.value }) - this.changeGasPrice({ target: { value: e.target.value } }) - } + this.setState({ gasPrice: e.target.value }); + this.changeGasPrice({ target: { value: e.target.value } }); + }; changeGasPrice = (e) => { - this.props.updateCustomGasPrice(Number(e.target.value)) - } + this.props.updateCustomGasPrice(Number(e.target.value)); + }; gasPriceError({ insufficientBalance, @@ -76,44 +76,44 @@ export default class AdvancedGasInputs extends Component { isSpeedUp, gasPrice, }) { - const { t } = this.context + const { t } = this.context; if (insufficientBalance) { return { errorText: t('insufficientBalance'), errorType: 'error', - } + }; } else if (isSpeedUp && gasPrice === 0) { return { errorText: t('zeroGasPriceOnSpeedUpError'), errorType: 'error', - } + }; } else if (!customPriceIsSafe) { return { errorText: t('gasPriceExtremelyLow'), errorType: 'warning', - } + }; } - return {} + return {}; } gasLimitError({ insufficientBalance, gasLimit, minimumGasLimit }) { - const { t } = this.context + const { t } = this.context; if (insufficientBalance) { return { errorText: t('insufficientBalance'), errorType: 'error', - } + }; } else if (gasLimit < minimumGasLimit) { return { errorText: t('gasLimitTooLowWithDynamicFee', [minimumGasLimit]), errorType: 'error', - } + }; } - return {} + return {}; } renderGasInput({ @@ -175,7 +175,7 @@ export default class AdvancedGasInputs extends Component { {errorComponent || customMessageComponent}
    - ) + ); } render() { @@ -185,8 +185,8 @@ export default class AdvancedGasInputs extends Component { isSpeedUp, customGasLimitMessage, minimumGasLimit, - } = this.props - const { gasPrice, gasLimit } = this.state + } = this.props; + const { gasPrice, gasLimit } = this.state; const { errorText: gasPriceErrorText, @@ -196,32 +196,32 @@ export default class AdvancedGasInputs extends Component { customPriceIsSafe, isSpeedUp, gasPrice, - }) + }); const gasPriceErrorComponent = gasPriceErrorType ? (
    {gasPriceErrorText}
    - ) : null + ) : null; const { errorText: gasLimitErrorText, errorType: gasLimitErrorType, - } = this.gasLimitError({ insufficientBalance, gasLimit, minimumGasLimit }) + } = this.gasLimitError({ insufficientBalance, gasLimit, minimumGasLimit }); const gasLimitErrorComponent = gasLimitErrorType ? (
    {gasLimitErrorText}
    - ) : null + ) : null; const gasLimitCustomMessageComponent = customGasLimitMessage ? (
    {customGasLimitMessage}
    - ) : null + ) : null; return (
    @@ -243,6 +243,6 @@ export default class AdvancedGasInputs extends Component { errorType: gasLimitErrorType, })}
    - ) + ); } } diff --git a/ui/app/components/app/gas-customization/advanced-gas-inputs/advanced-gas-inputs.container.js b/ui/app/components/app/gas-customization/advanced-gas-inputs/advanced-gas-inputs.container.js index 949f23fea..45cdaaa38 100644 --- a/ui/app/components/app/gas-customization/advanced-gas-inputs/advanced-gas-inputs.container.js +++ b/ui/app/components/app/gas-customization/advanced-gas-inputs/advanced-gas-inputs.container.js @@ -1,17 +1,17 @@ -import { connect } from 'react-redux' +import { connect } from 'react-redux'; import { decGWEIToHexWEI, decimalToHex, hexWEIToDecGWEI, -} from '../../../../helpers/utils/conversions.util' -import AdvancedGasInputs from './advanced-gas-inputs.component' +} from '../../../../helpers/utils/conversions.util'; +import AdvancedGasInputs from './advanced-gas-inputs.component'; function convertGasPriceForInputs(gasPriceInHexWEI) { - return Number(hexWEIToDecGWEI(gasPriceInHexWEI)) + return Number(hexWEIToDecGWEI(gasPriceInHexWEI)); } function convertGasLimitForInputs(gasLimitInHexWEI) { - return parseInt(gasLimitInHexWEI, 16) || 0 + return parseInt(gasLimitInHexWEI, 16) || 0; } const mergeProps = (stateProps, dispatchProps, ownProps) => { @@ -20,7 +20,7 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => { customGasLimit, updateCustomGasPrice, updateCustomGasLimit, - } = ownProps + } = ownProps; return { ...ownProps, ...stateProps, @@ -30,7 +30,7 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => { updateCustomGasPrice: (price) => updateCustomGasPrice(decGWEIToHexWEI(price)), updateCustomGasLimit: (limit) => updateCustomGasLimit(decimalToHex(limit)), - } -} + }; +}; -export default connect(null, null, mergeProps)(AdvancedGasInputs) +export default connect(null, null, mergeProps)(AdvancedGasInputs); diff --git a/ui/app/components/app/gas-customization/advanced-gas-inputs/index.js b/ui/app/components/app/gas-customization/advanced-gas-inputs/index.js index bd8abaa3e..e922ac634 100644 --- a/ui/app/components/app/gas-customization/advanced-gas-inputs/index.js +++ b/ui/app/components/app/gas-customization/advanced-gas-inputs/index.js @@ -1 +1 @@ -export { default } from './advanced-gas-inputs.container' +export { default } from './advanced-gas-inputs.container'; diff --git a/ui/app/components/app/gas-customization/advanced-gas-inputs/tests/advanced-gas-input-component.test.js b/ui/app/components/app/gas-customization/advanced-gas-inputs/tests/advanced-gas-input-component.test.js index 8c17f4d52..72311a322 100644 --- a/ui/app/components/app/gas-customization/advanced-gas-inputs/tests/advanced-gas-input-component.test.js +++ b/ui/app/components/app/gas-customization/advanced-gas-inputs/tests/advanced-gas-input-component.test.js @@ -1,11 +1,11 @@ -import assert from 'assert' -import React from 'react' -import sinon from 'sinon' -import { mount } from 'enzyme' -import AdvancedTabContent from '..' +import assert from 'assert'; +import React from 'react'; +import sinon from 'sinon'; +import { mount } from 'enzyme'; +import AdvancedTabContent from '..'; describe('Advanced Gas Inputs', function () { - let wrapper, clock + let wrapper, clock; const props = { updateCustomGasPrice: sinon.spy(), @@ -18,91 +18,94 @@ describe('Advanced Gas Inputs', function () { customPriceIsSafe: true, isSpeedUp: false, minimumGasLimit: 21000, - } + }; beforeEach(function () { - clock = sinon.useFakeTimers() + clock = sinon.useFakeTimers(); wrapper = mount(, { context: { t: (str) => str, }, - }) - }) + }); + }); afterEach(function () { - clock.restore() - }) + clock.restore(); + }); it('wont update gasPrice in props before debounce', function () { - const event = { target: { value: 1 } } + const event = { target: { value: 1 } }; - wrapper.find('input').at(0).simulate('change', event) - clock.tick(499) + wrapper.find('input').at(0).simulate('change', event); + clock.tick(499); - assert.strictEqual(props.updateCustomGasPrice.callCount, 0) - }) + assert.strictEqual(props.updateCustomGasPrice.callCount, 0); + }); it('simulates onChange on gas price after debounce', function () { - const event = { target: { value: 1 } } + const event = { target: { value: 1 } }; - wrapper.find('input').at(0).simulate('change', event) - clock.tick(500) + wrapper.find('input').at(0).simulate('change', event); + clock.tick(500); - assert.strictEqual(props.updateCustomGasPrice.calledOnce, true) - assert.strictEqual(props.updateCustomGasPrice.calledWith(1), true) - }) + assert.strictEqual(props.updateCustomGasPrice.calledOnce, true); + assert.strictEqual(props.updateCustomGasPrice.calledWith(1), true); + }); it('wont update gasLimit in props before debounce', function () { - const event = { target: { value: 21000 } } + const event = { target: { value: 21000 } }; - wrapper.find('input').at(1).simulate('change', event) - clock.tick(499) + wrapper.find('input').at(1).simulate('change', event); + clock.tick(499); - assert.strictEqual(props.updateCustomGasLimit.callCount, 0) - }) + assert.strictEqual(props.updateCustomGasLimit.callCount, 0); + }); it('simulates onChange on gas limit after debounce', function () { - const event = { target: { value: 21000 } } + const event = { target: { value: 21000 } }; - wrapper.find('input').at(1).simulate('change', event) - clock.tick(500) + wrapper.find('input').at(1).simulate('change', event); + clock.tick(500); - assert.strictEqual(props.updateCustomGasLimit.calledOnce, true) - assert.strictEqual(props.updateCustomGasLimit.calledWith(21000), true) - }) + assert.strictEqual(props.updateCustomGasLimit.calledOnce, true); + assert.strictEqual(props.updateCustomGasLimit.calledWith(21000), true); + }); it('errors when insufficientBalance under gas price and gas limit', function () { - wrapper.setProps({ insufficientBalance: true }) + wrapper.setProps({ insufficientBalance: true }); const renderError = wrapper.find( '.advanced-gas-inputs__gas-edit-row__error-text', - ) - assert.strictEqual(renderError.length, 2) + ); + assert.strictEqual(renderError.length, 2); - assert.strictEqual(renderError.at(0).text(), 'insufficientBalance') - assert.strictEqual(renderError.at(1).text(), 'insufficientBalance') - }) + assert.strictEqual(renderError.at(0).text(), 'insufficientBalance'); + assert.strictEqual(renderError.at(1).text(), 'insufficientBalance'); + }); it('errors zero gas price / speed up', function () { - wrapper.setProps({ isSpeedUp: true }) + wrapper.setProps({ isSpeedUp: true }); const renderError = wrapper.find( '.advanced-gas-inputs__gas-edit-row__error-text', - ) - assert.strictEqual(renderError.length, 2) + ); + assert.strictEqual(renderError.length, 2); - assert.strictEqual(renderError.at(0).text(), 'zeroGasPriceOnSpeedUpError') - assert.strictEqual(renderError.at(1).text(), 'gasLimitTooLowWithDynamicFee') - }) + assert.strictEqual(renderError.at(0).text(), 'zeroGasPriceOnSpeedUpError'); + assert.strictEqual( + renderError.at(1).text(), + 'gasLimitTooLowWithDynamicFee', + ); + }); it('warns when custom gas price is too low', function () { - wrapper.setProps({ customPriceIsSafe: false }) + wrapper.setProps({ customPriceIsSafe: false }); const renderWarning = wrapper.find( '.advanced-gas-inputs__gas-edit-row__warning-text', - ) - assert.strictEqual(renderWarning.length, 1) + ); + assert.strictEqual(renderWarning.length, 1); - assert.strictEqual(renderWarning.text(), 'gasPriceExtremelyLow') - }) -}) + assert.strictEqual(renderWarning.text(), 'gasPriceExtremelyLow'); + }); +}); diff --git a/ui/app/components/app/gas-customization/gas-modal-page-container/advanced-tab-content/advanced-tab-content.component.js b/ui/app/components/app/gas-customization/gas-modal-page-container/advanced-tab-content/advanced-tab-content.component.js index 8f2ddbc6c..f6be3bc01 100644 --- a/ui/app/components/app/gas-customization/gas-modal-page-container/advanced-tab-content/advanced-tab-content.component.js +++ b/ui/app/components/app/gas-customization/gas-modal-page-container/advanced-tab-content/advanced-tab-content.component.js @@ -1,11 +1,11 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import AdvancedGasInputs from '../../advanced-gas-inputs' +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import AdvancedGasInputs from '../../advanced-gas-inputs'; export default class AdvancedTabContent extends Component { static contextTypes = { t: PropTypes.func, - } + }; static propTypes = { updateCustomGasPrice: PropTypes.func, @@ -18,7 +18,7 @@ export default class AdvancedTabContent extends Component { isSpeedUp: PropTypes.bool, customGasLimitMessage: PropTypes.string, minimumGasLimit: PropTypes.number, - } + }; renderDataSummary(transactionFee) { return ( @@ -32,7 +32,7 @@ export default class AdvancedTabContent extends Component { - ) + ); } render() { @@ -47,7 +47,7 @@ export default class AdvancedTabContent extends Component { transactionFee, customGasLimitMessage, minimumGasLimit, - } = this.props + } = this.props; return (
    @@ -68,6 +68,6 @@ export default class AdvancedTabContent extends Component {
    - ) + ); } } diff --git a/ui/app/components/app/gas-customization/gas-modal-page-container/advanced-tab-content/index.js b/ui/app/components/app/gas-customization/gas-modal-page-container/advanced-tab-content/index.js index 492037f25..1bb49f30c 100644 --- a/ui/app/components/app/gas-customization/gas-modal-page-container/advanced-tab-content/index.js +++ b/ui/app/components/app/gas-customization/gas-modal-page-container/advanced-tab-content/index.js @@ -1 +1 @@ -export { default } from './advanced-tab-content.component' +export { default } from './advanced-tab-content.component'; diff --git a/ui/app/components/app/gas-customization/gas-modal-page-container/advanced-tab-content/tests/advanced-tab-content-component.test.js b/ui/app/components/app/gas-customization/gas-modal-page-container/advanced-tab-content/tests/advanced-tab-content-component.test.js index b33dcadee..4b1bdc21d 100644 --- a/ui/app/components/app/gas-customization/gas-modal-page-container/advanced-tab-content/tests/advanced-tab-content-component.test.js +++ b/ui/app/components/app/gas-customization/gas-modal-page-container/advanced-tab-content/tests/advanced-tab-content-component.test.js @@ -1,18 +1,18 @@ -import assert from 'assert' -import React from 'react' -import sinon from 'sinon' -import shallow from '../../../../../../../lib/shallow-with-context' -import AdvancedTabContent from '../advanced-tab-content.component' +import assert from 'assert'; +import React from 'react'; +import sinon from 'sinon'; +import shallow from '../../../../../../../lib/shallow-with-context'; +import AdvancedTabContent from '../advanced-tab-content.component'; describe('AdvancedTabContent Component', function () { - let wrapper + let wrapper; beforeEach(function () { const propsMethodSpies = { updateCustomGasPrice: sinon.spy(), updateCustomGasLimit: sinon.spy(), - } - sinon.spy(AdvancedTabContent.prototype, 'renderDataSummary') + }; + sinon.spy(AdvancedTabContent.prototype, 'renderDataSummary'); wrapper = shallow( , - ) - }) + ); + }); afterEach(function () { - sinon.restore() - }) + sinon.restore(); + }); describe('render()', function () { it('should render the advanced-tab root node', function () { - assert(wrapper.hasClass('advanced-tab')) - }) + assert(wrapper.hasClass('advanced-tab')); + }); it('should render the expected child of the advanced-tab div', function () { - const advancedTabChildren = wrapper.children() - assert.strictEqual(advancedTabChildren.length, 2) + const advancedTabChildren = wrapper.children(); + assert.strictEqual(advancedTabChildren.length, 2); assert( advancedTabChildren .at(0) .hasClass('advanced-tab__transaction-data-summary'), - ) - }) + ); + }); it('should call renderDataSummary with the expected params', function () { const renderDataSummaryArgs = AdvancedTabContent.prototype.renderDataSummary.getCall( 0, - ).args - assert.deepStrictEqual(renderDataSummaryArgs, ['$0.25']) - }) - }) + ).args; + assert.deepStrictEqual(renderDataSummaryArgs, ['$0.25']); + }); + }); describe('renderDataSummary()', function () { - let dataSummary + let dataSummary; beforeEach(function () { dataSummary = shallow( wrapper.instance().renderDataSummary('mockTotalFee'), - ) - }) + ); + }); it('should render the transaction-data-summary root node', function () { - assert(dataSummary.hasClass('advanced-tab__transaction-data-summary')) - }) + assert(dataSummary.hasClass('advanced-tab__transaction-data-summary')); + }); it('should render titles of the data', function () { - const titlesNode = dataSummary.children().at(0) + const titlesNode = dataSummary.children().at(0); assert( titlesNode.hasClass('advanced-tab__transaction-data-summary__titles'), - ) + ); assert.strictEqual( titlesNode.children().at(0).text(), 'newTransactionFee', - ) - }) + ); + }); it('should render the data', function () { - const dataNode = dataSummary.children().at(1) + const dataNode = dataSummary.children().at(1); assert( dataNode.hasClass('advanced-tab__transaction-data-summary__container'), - ) - assert.strictEqual(dataNode.children().at(0).text(), 'mockTotalFee') - }) - }) -}) + ); + assert.strictEqual(dataNode.children().at(0).text(), 'mockTotalFee'); + }); + }); +}); diff --git a/ui/app/components/app/gas-customization/gas-modal-page-container/basic-tab-content/basic-tab-content.component.js b/ui/app/components/app/gas-customization/gas-modal-page-container/basic-tab-content/basic-tab-content.component.js index 7ef85e7a4..85a06c89d 100644 --- a/ui/app/components/app/gas-customization/gas-modal-page-container/basic-tab-content/basic-tab-content.component.js +++ b/ui/app/components/app/gas-customization/gas-modal-page-container/basic-tab-content/basic-tab-content.component.js @@ -1,20 +1,20 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import Loading from '../../../../ui/loading-screen' -import GasPriceButtonGroup from '../../gas-price-button-group' +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import Loading from '../../../../ui/loading-screen'; +import GasPriceButtonGroup from '../../gas-price-button-group'; export default class BasicTabContent extends Component { static contextTypes = { t: PropTypes.func, - } + }; static propTypes = { gasPriceButtonGroupProps: PropTypes.object, - } + }; render() { - const { t } = this.context - const { gasPriceButtonGroupProps } = this.props + const { t } = this.context; + const { gasPriceButtonGroupProps } = this.props; return (
    @@ -37,6 +37,6 @@ export default class BasicTabContent extends Component { {t('acceleratingATransaction')}
    - ) + ); } } diff --git a/ui/app/components/app/gas-customization/gas-modal-page-container/basic-tab-content/index.js b/ui/app/components/app/gas-customization/gas-modal-page-container/basic-tab-content/index.js index 078d50fce..27b7eaa9d 100644 --- a/ui/app/components/app/gas-customization/gas-modal-page-container/basic-tab-content/index.js +++ b/ui/app/components/app/gas-customization/gas-modal-page-container/basic-tab-content/index.js @@ -1 +1 @@ -export { default } from './basic-tab-content.component' +export { default } from './basic-tab-content.component'; diff --git a/ui/app/components/app/gas-customization/gas-modal-page-container/basic-tab-content/tests/basic-tab-content-component.test.js b/ui/app/components/app/gas-customization/gas-modal-page-container/basic-tab-content/tests/basic-tab-content-component.test.js index ae0829db0..e0597a5a0 100644 --- a/ui/app/components/app/gas-customization/gas-modal-page-container/basic-tab-content/tests/basic-tab-content-component.test.js +++ b/ui/app/components/app/gas-customization/gas-modal-page-container/basic-tab-content/tests/basic-tab-content-component.test.js @@ -1,10 +1,10 @@ -import assert from 'assert' -import React from 'react' -import shallow from '../../../../../../../lib/shallow-with-context' -import BasicTabContent from '../basic-tab-content.component' -import GasPriceButtonGroup from '../../../gas-price-button-group' -import Loading from '../../../../../ui/loading-screen' -import { GAS_ESTIMATE_TYPES } from '../../../../../../helpers/constants/common' +import assert from 'assert'; +import React from 'react'; +import shallow from '../../../../../../../lib/shallow-with-context'; +import BasicTabContent from '../basic-tab-content.component'; +import GasPriceButtonGroup from '../../../gas-price-button-group'; +import Loading from '../../../../../ui/loading-screen'; +import { GAS_ESTIMATE_TYPES } from '../../../../../../helpers/constants/common'; const mockGasPriceButtonGroupProps = { buttonDataLoading: false, @@ -36,19 +36,19 @@ const mockGasPriceButtonGroupProps = { console.log('NewPrice: ', gasPrice), noButtonActiveByDefault: true, showCheck: true, -} +}; describe('BasicTabContent Component', function () { describe('render', function () { - let wrapper + let wrapper; beforeEach(function () { wrapper = shallow( , - ) - }) + ); + }); it('should have a title', function () { assert( @@ -56,12 +56,12 @@ describe('BasicTabContent Component', function () { .find('.basic-tab-content') .childAt(0) .hasClass('basic-tab-content__title'), - ) - }) + ); + }); it('should render a GasPriceButtonGroup compenent', function () { - assert.strictEqual(wrapper.find(GasPriceButtonGroup).length, 1) - }) + assert.strictEqual(wrapper.find(GasPriceButtonGroup).length, 1); + }); it('should pass correct props to GasPriceButtonGroup', function () { const { @@ -71,27 +71,27 @@ describe('BasicTabContent Component', function () { handleGasPriceSelection, noButtonActiveByDefault, showCheck, - } = wrapper.find(GasPriceButtonGroup).props() - assert.strictEqual(wrapper.find(GasPriceButtonGroup).length, 1) + } = wrapper.find(GasPriceButtonGroup).props(); + assert.strictEqual(wrapper.find(GasPriceButtonGroup).length, 1); assert.strictEqual( buttonDataLoading, mockGasPriceButtonGroupProps.buttonDataLoading, - ) - assert.strictEqual(className, mockGasPriceButtonGroupProps.className) + ); + assert.strictEqual(className, mockGasPriceButtonGroupProps.className); assert.strictEqual( noButtonActiveByDefault, mockGasPriceButtonGroupProps.noButtonActiveByDefault, - ) - assert.strictEqual(showCheck, mockGasPriceButtonGroupProps.showCheck) + ); + assert.strictEqual(showCheck, mockGasPriceButtonGroupProps.showCheck); assert.deepStrictEqual( gasButtonInfo, mockGasPriceButtonGroupProps.gasButtonInfo, - ) + ); assert.strictEqual( JSON.stringify(handleGasPriceSelection), JSON.stringify(mockGasPriceButtonGroupProps.handleGasPriceSelection), - ) - }) + ); + }); it('should render a loading component instead of the GasPriceButtonGroup if gasPriceButtonGroupProps.loading is true', function () { wrapper.setProps({ @@ -99,10 +99,10 @@ describe('BasicTabContent Component', function () { ...mockGasPriceButtonGroupProps, loading: true, }, - }) + }); - assert.strictEqual(wrapper.find(GasPriceButtonGroup).length, 0) - assert.strictEqual(wrapper.find(Loading).length, 1) - }) - }) -}) + assert.strictEqual(wrapper.find(GasPriceButtonGroup).length, 0); + assert.strictEqual(wrapper.find(Loading).length, 1); + }); + }); +}); diff --git a/ui/app/components/app/gas-customization/gas-modal-page-container/gas-modal-page-container.component.js b/ui/app/components/app/gas-customization/gas-modal-page-container/gas-modal-page-container.component.js index 05810f07f..4c27f9900 100644 --- a/ui/app/components/app/gas-customization/gas-modal-page-container/gas-modal-page-container.component.js +++ b/ui/app/components/app/gas-customization/gas-modal-page-container/gas-modal-page-container.component.js @@ -1,16 +1,16 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import PageContainer from '../../../ui/page-container' -import { Tabs, Tab } from '../../../ui/tabs' -import AdvancedTabContent from './advanced-tab-content' -import BasicTabContent from './basic-tab-content' +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import PageContainer from '../../../ui/page-container'; +import { Tabs, Tab } from '../../../ui/tabs'; +import AdvancedTabContent from './advanced-tab-content'; +import BasicTabContent from './basic-tab-content'; export default class GasModalPageContainer extends Component { static contextTypes = { t: PropTypes.func, metricsEvent: PropTypes.func, trackEvent: PropTypes.func, - } + }; static propTypes = { hideBasic: PropTypes.bool, @@ -35,16 +35,16 @@ export default class GasModalPageContainer extends Component { isSpeedUp: PropTypes.bool, isRetry: PropTypes.bool, disableSave: PropTypes.bool, - } + }; componentDidMount() { - this.props.fetchBasicGasEstimates() + this.props.fetchBasicGasEstimates(); } renderBasicTabContent(gasPriceButtonGroupProps) { return ( - ) + ); } renderAdvancedTabContent() { @@ -58,7 +58,7 @@ export default class GasModalPageContainer extends Component { isSpeedUp, isRetry, infoRowProps: { transactionFee }, - } = this.props + } = this.props; return ( - ) + ); } renderInfoRows(newTotalFiat, newTotalEth, sendAmount, transactionFee) { @@ -110,7 +110,7 @@ export default class GasModalPageContainer extends Component { - ) + ); } renderTabs() { @@ -118,7 +118,7 @@ export default class GasModalPageContainer extends Component { gasPriceButtonGroupProps, hideBasic, infoRowProps: { newTotalFiat, newTotalEth, sendAmount, transactionFee }, - } = this.props + } = this.props; let tabsToRender = [ { @@ -129,10 +129,10 @@ export default class GasModalPageContainer extends Component { name: this.context.t('advanced'), content: this.renderAdvancedTabContent(), }, - ] + ]; if (hideBasic) { - tabsToRender = tabsToRender.slice(1) + tabsToRender = tabsToRender.slice(1); } return ( @@ -151,7 +151,7 @@ export default class GasModalPageContainer extends Component { ))} - ) + ); } render() { @@ -162,7 +162,7 @@ export default class GasModalPageContainer extends Component { customModalGasLimitInHex, disableSave, isSpeedUp, - } = this.props + } = this.props; return (
    @@ -181,15 +181,15 @@ export default class GasModalPageContainer extends Component { action: 'Activity Log', name: 'Saved "Speed Up"', }, - }) + }); } - onSubmit(customModalGasLimitInHex, customModalGasPriceInHex) + onSubmit(customModalGasLimitInHex, customModalGasPriceInHex); }} submitText={this.context.t('save')} headerCloseText={this.context.t('close')} hideCancel />
    - ) + ); } } diff --git a/ui/app/components/app/gas-customization/gas-modal-page-container/gas-modal-page-container.container.js b/ui/app/components/app/gas-customization/gas-modal-page-container/gas-modal-page-container.container.js index cacb39b09..fc1b111b9 100644 --- a/ui/app/components/app/gas-customization/gas-modal-page-container/gas-modal-page-container.container.js +++ b/ui/app/components/app/gas-customization/gas-modal-page-container/gas-modal-page-container.container.js @@ -1,5 +1,5 @@ -import { connect } from 'react-redux' -import { addHexPrefix } from '../../../../../../app/scripts/lib/util' +import { connect } from 'react-redux'; +import { addHexPrefix } from '../../../../../../app/scripts/lib/util'; import { hideModal, setGasLimit, @@ -10,17 +10,17 @@ import { updateSendAmount, setGasTotal, updateTransaction, -} from '../../../../store/actions' +} from '../../../../store/actions'; import { setCustomGasPrice, setCustomGasLimit, resetCustomData, fetchBasicGasEstimates, -} from '../../../../ducks/gas/gas.duck' +} from '../../../../ducks/gas/gas.duck'; import { hideGasButtonGroup, updateSendErrors, -} from '../../../../ducks/send/send.duck' +} from '../../../../ducks/send/send.duck'; import { conversionRateSelector as getConversionRate, getCurrentCurrency, @@ -37,7 +37,7 @@ import { getTokenBalance, getSendMaxModeState, getAveragePriceEstimateInHexWEI, -} from '../../../../selectors' +} from '../../../../selectors'; import { addHexes, @@ -45,27 +45,27 @@ import { hexWEIToDecGWEI, getValueFromWeiHex, sumHexWEIsToRenderableFiat, -} from '../../../../helpers/utils/conversions.util' -import { formatETHFee } from '../../../../helpers/utils/formatters' +} from '../../../../helpers/utils/conversions.util'; +import { formatETHFee } from '../../../../helpers/utils/formatters'; import { calcGasTotal, isBalanceSufficient, -} from '../../../../pages/send/send.utils' -import { MIN_GAS_LIMIT_DEC } from '../../../../pages/send/send.constants' -import { calcMaxAmount } from '../../../../pages/send/send-content/send-amount-row/amount-max-button/amount-max-button.utils' -import { TRANSACTION_STATUSES } from '../../../../../../shared/constants/transaction' -import GasModalPageContainer from './gas-modal-page-container.component' +} from '../../../../pages/send/send.utils'; +import { MIN_GAS_LIMIT_DEC } from '../../../../pages/send/send.constants'; +import { calcMaxAmount } from '../../../../pages/send/send-content/send-amount-row/amount-max-button/amount-max-button.utils'; +import { TRANSACTION_STATUSES } from '../../../../../../shared/constants/transaction'; +import GasModalPageContainer from './gas-modal-page-container.component'; const mapStateToProps = (state, ownProps) => { - const { currentNetworkTxList, send } = state.metamask - const { modalState: { props: modalProps } = {} } = state.appState.modal || {} - const { txData = {} } = modalProps || {} - const { transaction = {} } = ownProps + const { currentNetworkTxList, send } = state.metamask; + const { modalState: { props: modalProps } = {} } = state.appState.modal || {}; + const { txData = {} } = modalProps || {}; + const { transaction = {} } = ownProps; const selectedTransaction = currentNetworkTxList.find( ({ id }) => id === (transaction.id || txData.id), - ) - const buttonDataLoading = getBasicGasEstimateLoadingStatus(state) - const sendToken = getSendToken(state) + ); + const buttonDataLoading = getBasicGasEstimateLoadingStatus(state); + const sendToken = getSendToken(state); // a "default" txParams is used during the send flow, since the transaction doesn't exist yet in that case const txParams = selectedTransaction?.txParams @@ -74,53 +74,53 @@ const mapStateToProps = (state, ownProps) => { gas: send.gasLimit || '0x5208', gasPrice: send.gasPrice || getAveragePriceEstimateInHexWEI(state, true), value: sendToken ? '0x0' : send.amount, - } + }; - const { gasPrice: currentGasPrice, gas: currentGasLimit, value } = txParams - const customModalGasPriceInHex = getCustomGasPrice(state) || currentGasPrice + const { gasPrice: currentGasPrice, gas: currentGasLimit, value } = txParams; + const customModalGasPriceInHex = getCustomGasPrice(state) || currentGasPrice; const customModalGasLimitInHex = - getCustomGasLimit(state) || currentGasLimit || '0x5208' + getCustomGasLimit(state) || currentGasLimit || '0x5208'; const customGasTotal = calcGasTotal( customModalGasLimitInHex, customModalGasPriceInHex, - ) + ); const gasButtonInfo = getRenderableBasicEstimateData( state, customModalGasLimitInHex, - ) + ); - const currentCurrency = getCurrentCurrency(state) - const conversionRate = getConversionRate(state) + const currentCurrency = getCurrentCurrency(state); + const conversionRate = getConversionRate(state); const newTotalFiat = sumHexWEIsToRenderableFiat( [value, customGasTotal], currentCurrency, conversionRate, - ) + ); - const { hideBasic } = state.appState.modal.modalState.props + const { hideBasic } = state.appState.modal.modalState.props; - const customGasPrice = calcCustomGasPrice(customModalGasPriceInHex) + const customGasPrice = calcCustomGasPrice(customModalGasPriceInHex); - const maxModeOn = getSendMaxModeState(state) + const maxModeOn = getSendMaxModeState(state); - const balance = getCurrentEthBalance(state) + const balance = getCurrentEthBalance(state); - const { showFiatInTestnets } = getPreferences(state) - const isMainnet = getIsMainnet(state) - const showFiat = Boolean(isMainnet || showFiatInTestnets) + const { showFiatInTestnets } = getPreferences(state); + const isMainnet = getIsMainnet(state); + const showFiat = Boolean(isMainnet || showFiatInTestnets); - const isSendTokenSet = Boolean(sendToken) + const isSendTokenSet = Boolean(sendToken); const newTotalEth = maxModeOn && !isSendTokenSet ? sumHexWEIsToRenderableEth([balance, '0x0']) - : sumHexWEIsToRenderableEth([value, customGasTotal]) + : sumHexWEIsToRenderableEth([value, customGasTotal]); const sendAmount = maxModeOn && !isSendTokenSet ? subtractHexWEIsFromRenderableEth(balance, customGasTotal) - : sumHexWEIsToRenderableEth([value, '0x0']) + : sumHexWEIsToRenderableEth([value, '0x0']); const insufficientBalance = maxModeOn ? false @@ -129,7 +129,7 @@ const mapStateToProps = (state, ownProps) => { gasTotal: customGasTotal, balance, conversionRate, - }) + }); return { hideBasic, @@ -173,47 +173,47 @@ const mapStateToProps = (state, ownProps) => { tokenBalance: getTokenBalance(state), conversionRate, value, - } -} + }; +}; const mapDispatchToProps = (dispatch) => { const updateCustomGasPrice = (newPrice) => - dispatch(setCustomGasPrice(addHexPrefix(newPrice))) + dispatch(setCustomGasPrice(addHexPrefix(newPrice))); return { cancelAndClose: () => { - dispatch(resetCustomData()) - dispatch(hideModal()) + dispatch(resetCustomData()); + dispatch(hideModal()); }, hideModal: () => dispatch(hideModal()), updateCustomGasPrice, updateCustomGasLimit: (newLimit) => dispatch(setCustomGasLimit(addHexPrefix(newLimit))), setGasData: (newLimit, newPrice) => { - dispatch(setGasLimit(newLimit)) - dispatch(setGasPrice(newPrice)) + dispatch(setGasLimit(newLimit)); + dispatch(setGasPrice(newPrice)); }, updateConfirmTxGasAndCalculate: (gasLimit, gasPrice, updatedTx) => { - updateCustomGasPrice(gasPrice) - dispatch(setCustomGasLimit(addHexPrefix(gasLimit.toString(16)))) - return dispatch(updateTransaction(updatedTx)) + updateCustomGasPrice(gasPrice); + dispatch(setCustomGasLimit(addHexPrefix(gasLimit.toString(16)))); + return dispatch(updateTransaction(updatedTx)); }, createRetryTransaction: (txId, gasPrice, gasLimit) => { - return dispatch(createRetryTransaction(txId, gasPrice, gasLimit)) + return dispatch(createRetryTransaction(txId, gasPrice, gasLimit)); }, createSpeedUpTransaction: (txId, gasPrice, gasLimit) => { - return dispatch(createSpeedUpTransaction(txId, gasPrice, gasLimit)) + return dispatch(createSpeedUpTransaction(txId, gasPrice, gasLimit)); }, hideGasButtonGroup: () => dispatch(hideGasButtonGroup()), hideSidebar: () => dispatch(hideSidebar()), fetchBasicGasEstimates: () => dispatch(fetchBasicGasEstimates()), setGasTotal: (total) => dispatch(setGasTotal(total)), setAmountToMax: (maxAmountDataObject) => { - dispatch(updateSendErrors({ amount: null })) - dispatch(updateSendAmount(calcMaxAmount(maxAmountDataObject))) + dispatch(updateSendErrors({ amount: null })); + dispatch(updateSendAmount(calcMaxAmount(maxAmountDataObject))); }, - } -} + }; +}; const mergeProps = (stateProps, dispatchProps, ownProps) => { const { @@ -232,7 +232,7 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => { tokenBalance, customGasLimit, transaction, - } = stateProps + } = stateProps; const { hideGasButtonGroup: dispatchHideGasButtonGroup, setGasData: dispatchSetGasData, @@ -244,7 +244,7 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => { hideModal: dispatchHideModal, setAmountToMax: dispatchSetAmountToMax, ...otherDispatchProps - } = dispatchProps + } = dispatchProps; return { ...stateProps, @@ -259,21 +259,21 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => { gas: gasLimit, gasPrice, }, - } - dispatchUpdateConfirmTxGasAndCalculate(gasLimit, gasPrice, updatedTx) - dispatchHideModal() + }; + dispatchUpdateConfirmTxGasAndCalculate(gasLimit, gasPrice, updatedTx); + dispatchHideModal(); } else if (isSpeedUp) { - dispatchCreateSpeedUpTransaction(txId, gasPrice, gasLimit) - dispatchHideSidebar() - dispatchCancelAndClose() + dispatchCreateSpeedUpTransaction(txId, gasPrice, gasLimit); + dispatchHideSidebar(); + dispatchCancelAndClose(); } else if (isRetry) { - dispatchCreateRetryTransaction(txId, gasPrice, gasLimit) - dispatchHideSidebar() - dispatchCancelAndClose() + dispatchCreateRetryTransaction(txId, gasPrice, gasLimit); + dispatchHideSidebar(); + dispatchCancelAndClose(); } else { - dispatchSetGasData(gasLimit, gasPrice) - dispatchHideGasButtonGroup() - dispatchCancelAndClose() + dispatchSetGasData(gasLimit, gasPrice); + dispatchHideGasButtonGroup(); + dispatchCancelAndClose(); } if (maxModeOn) { dispatchSetAmountToMax({ @@ -281,7 +281,7 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => { gasTotal: customGasTotal, sendToken, tokenBalance, - }) + }); } }, gasPriceButtonGroupProps: { @@ -290,47 +290,47 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => { otherDispatchProps.updateCustomGasPrice(gasPrice), }, cancelAndClose: () => { - dispatchCancelAndClose() + dispatchCancelAndClose(); if (isSpeedUp || isRetry) { - dispatchHideSidebar() + dispatchHideSidebar(); } }, disableSave: insufficientBalance || (isSpeedUp && customGasPrice === 0) || customGasLimit < Number(MIN_GAS_LIMIT_DEC), - } -} + }; +}; export default connect( mapStateToProps, mapDispatchToProps, mergeProps, -)(GasModalPageContainer) +)(GasModalPageContainer); function isConfirm(state) { - return Boolean(Object.keys(state.confirmTransaction.txData).length) + return Boolean(Object.keys(state.confirmTransaction.txData).length); } function calcCustomGasPrice(customGasPriceInHex) { - return Number(hexWEIToDecGWEI(customGasPriceInHex)) + return Number(hexWEIToDecGWEI(customGasPriceInHex)); } function calcCustomGasLimit(customGasLimitInHex) { - return parseInt(customGasLimitInHex, 16) + return parseInt(customGasLimitInHex, 16); } function sumHexWEIsToRenderableEth(hexWEIs) { - const hexWEIsSum = hexWEIs.filter(Boolean).reduce(addHexes) + const hexWEIsSum = hexWEIs.filter(Boolean).reduce(addHexes); return formatETHFee( getValueFromWeiHex({ value: hexWEIsSum, toCurrency: 'ETH', numberOfDecimals: 6, }), - ) + ); } function subtractHexWEIsFromRenderableEth(aHexWEI, bHexWEI) { - return formatETHFee(subtractHexWEIsToDec(aHexWEI, bHexWEI)) + return formatETHFee(subtractHexWEIsToDec(aHexWEI, bHexWEI)); } diff --git a/ui/app/components/app/gas-customization/gas-modal-page-container/index.js b/ui/app/components/app/gas-customization/gas-modal-page-container/index.js index ec0ebad22..65e2a49be 100644 --- a/ui/app/components/app/gas-customization/gas-modal-page-container/index.js +++ b/ui/app/components/app/gas-customization/gas-modal-page-container/index.js @@ -1 +1 @@ -export { default } from './gas-modal-page-container.container' +export { default } from './gas-modal-page-container.container'; diff --git a/ui/app/components/app/gas-customization/gas-modal-page-container/tests/gas-modal-page-container-component.test.js b/ui/app/components/app/gas-customization/gas-modal-page-container/tests/gas-modal-page-container-component.test.js index 8ae08274c..1fede0503 100644 --- a/ui/app/components/app/gas-customization/gas-modal-page-container/tests/gas-modal-page-container-component.test.js +++ b/ui/app/components/app/gas-customization/gas-modal-page-container/tests/gas-modal-page-container-component.test.js @@ -1,16 +1,16 @@ -import assert from 'assert' -import React from 'react' -import sinon from 'sinon' -import shallow from '../../../../../../lib/shallow-with-context' -import GasModalPageContainer from '../gas-modal-page-container.component' +import assert from 'assert'; +import React from 'react'; +import sinon from 'sinon'; +import shallow from '../../../../../../lib/shallow-with-context'; +import GasModalPageContainer from '../gas-modal-page-container.component'; -import PageContainer from '../../../../ui/page-container' +import PageContainer from '../../../../ui/page-container'; -import { Tab } from '../../../../ui/tabs' +import { Tab } from '../../../../ui/tabs'; const mockBasicGasEstimates = { average: '20', -} +}; const propsMethodSpies = { cancelAndClose: sinon.spy(), @@ -18,7 +18,7 @@ const propsMethodSpies = { fetchBasicGasEstimates: sinon .stub() .returns(Promise.resolve(mockBasicGasEstimates)), -} +}; const mockGasPriceButtonGroupProps = { buttonDataLoading: false, @@ -48,7 +48,7 @@ const mockGasPriceButtonGroupProps = { showCheck: true, newTotalFiat: 'mockNewTotalFiat', newTotalEth: 'mockNewTotalEth', -} +}; const mockInfoRowProps = { originalTotalFiat: 'mockOriginalTotalFiat', originalTotalEth: 'mockOriginalTotalEth', @@ -57,11 +57,11 @@ const mockInfoRowProps = { sendAmount: 'mockSendAmount', transactionFee: 'mockTransactionFee', extraInfoRow: { label: 'mockLabel', value: 'mockValue' }, -} +}; -const GP = GasModalPageContainer.prototype +const GP = GasModalPageContainer.prototype; describe('GasModalPageContainer Component', function () { - let wrapper + let wrapper; beforeEach(function () { wrapper = shallow( @@ -78,114 +78,114 @@ describe('GasModalPageContainer Component', function () { insufficientBalance={false} disableSave={false} />, - ) - }) + ); + }); afterEach(function () { - propsMethodSpies.cancelAndClose.resetHistory() - }) + propsMethodSpies.cancelAndClose.resetHistory(); + }); describe('componentDidMount', function () { it('should call props.fetchBasicGasEstimates', function () { - propsMethodSpies.fetchBasicGasEstimates.resetHistory() - assert.strictEqual(propsMethodSpies.fetchBasicGasEstimates.callCount, 0) - wrapper.instance().componentDidMount() - assert.strictEqual(propsMethodSpies.fetchBasicGasEstimates.callCount, 1) - }) - }) + propsMethodSpies.fetchBasicGasEstimates.resetHistory(); + assert.strictEqual(propsMethodSpies.fetchBasicGasEstimates.callCount, 0); + wrapper.instance().componentDidMount(); + assert.strictEqual(propsMethodSpies.fetchBasicGasEstimates.callCount, 1); + }); + }); describe('render', function () { it('should render a PageContainer compenent', function () { - assert.strictEqual(wrapper.find(PageContainer).length, 1) - }) + assert.strictEqual(wrapper.find(PageContainer).length, 1); + }); it('should pass correct props to PageContainer', function () { - const { title, subtitle, disabled } = wrapper.find(PageContainer).props() - assert.strictEqual(title, 'customGas') - assert.strictEqual(subtitle, 'customGasSubTitle') - assert.strictEqual(disabled, false) - }) + const { title, subtitle, disabled } = wrapper.find(PageContainer).props(); + assert.strictEqual(title, 'customGas'); + assert.strictEqual(subtitle, 'customGasSubTitle'); + assert.strictEqual(disabled, false); + }); it('should pass the correct onCancel and onClose methods to PageContainer', function () { - const { onCancel, onClose } = wrapper.find(PageContainer).props() - assert.strictEqual(propsMethodSpies.cancelAndClose.callCount, 0) - onCancel() - assert.strictEqual(propsMethodSpies.cancelAndClose.callCount, 1) - onClose() - assert.strictEqual(propsMethodSpies.cancelAndClose.callCount, 2) - }) + const { onCancel, onClose } = wrapper.find(PageContainer).props(); + assert.strictEqual(propsMethodSpies.cancelAndClose.callCount, 0); + onCancel(); + assert.strictEqual(propsMethodSpies.cancelAndClose.callCount, 1); + onClose(); + assert.strictEqual(propsMethodSpies.cancelAndClose.callCount, 2); + }); it('should pass the correct renderTabs property to PageContainer', function () { - sinon.stub(GP, 'renderTabs').returns('mockTabs') + sinon.stub(GP, 'renderTabs').returns('mockTabs'); const renderTabsWrapperTester = shallow( , { context: { t: (str1, str2) => (str2 ? str1 + str2 : str1) } }, - ) + ); const { tabsComponent } = renderTabsWrapperTester .find(PageContainer) - .props() - assert.strictEqual(tabsComponent, 'mockTabs') - GasModalPageContainer.prototype.renderTabs.restore() - }) - }) + .props(); + assert.strictEqual(tabsComponent, 'mockTabs'); + GasModalPageContainer.prototype.renderTabs.restore(); + }); + }); describe('renderTabs', function () { beforeEach(function () { - sinon.spy(GP, 'renderBasicTabContent') - sinon.spy(GP, 'renderAdvancedTabContent') - sinon.spy(GP, 'renderInfoRows') - }) + sinon.spy(GP, 'renderBasicTabContent'); + sinon.spy(GP, 'renderAdvancedTabContent'); + sinon.spy(GP, 'renderInfoRows'); + }); afterEach(function () { - GP.renderBasicTabContent.restore() - GP.renderAdvancedTabContent.restore() - GP.renderInfoRows.restore() - }) + GP.renderBasicTabContent.restore(); + GP.renderAdvancedTabContent.restore(); + GP.renderInfoRows.restore(); + }); it('should render a Tabs component with "Basic" and "Advanced" tabs', function () { - const renderTabsResult = wrapper.instance().renderTabs() - const renderedTabs = shallow(renderTabsResult) - assert.strictEqual(renderedTabs.props().className, 'tabs') + const renderTabsResult = wrapper.instance().renderTabs(); + const renderedTabs = shallow(renderTabsResult); + assert.strictEqual(renderedTabs.props().className, 'tabs'); - const tabs = renderedTabs.find(Tab) - assert.strictEqual(tabs.length, 2) + const tabs = renderedTabs.find(Tab); + assert.strictEqual(tabs.length, 2); - assert.strictEqual(tabs.at(0).props().name, 'basic') - assert.strictEqual(tabs.at(1).props().name, 'advanced') + assert.strictEqual(tabs.at(0).props().name, 'basic'); + assert.strictEqual(tabs.at(1).props().name, 'advanced'); assert.strictEqual( tabs.at(0).childAt(0).props().className, 'gas-modal-content', - ) + ); assert.strictEqual( tabs.at(1).childAt(0).props().className, 'gas-modal-content', - ) - }) + ); + }); it('should call renderInfoRows with the expected props', function () { - assert.strictEqual(GP.renderInfoRows.callCount, 0) + assert.strictEqual(GP.renderInfoRows.callCount, 0); - wrapper.instance().renderTabs() + wrapper.instance().renderTabs(); - assert.strictEqual(GP.renderInfoRows.callCount, 2) + assert.strictEqual(GP.renderInfoRows.callCount, 2); assert.deepStrictEqual(GP.renderInfoRows.getCall(0).args, [ 'mockNewTotalFiat', 'mockNewTotalEth', 'mockSendAmount', 'mockTransactionFee', - ]) + ]); assert.deepStrictEqual(GP.renderInfoRows.getCall(1).args, [ 'mockNewTotalFiat', 'mockNewTotalEth', 'mockSendAmount', 'mockTransactionFee', - ]) - }) + ]); + }); it('should not render the basic tab if hideBasic is true', function () { wrapper = shallow( @@ -203,32 +203,32 @@ describe('GasModalPageContainer Component', function () { disableSave={false} hideBasic />, - ) - const renderTabsResult = wrapper.instance().renderTabs() + ); + const renderTabsResult = wrapper.instance().renderTabs(); - const renderedTabs = shallow(renderTabsResult) - const tabs = renderedTabs.find(Tab) - assert.strictEqual(tabs.length, 1) - assert.strictEqual(tabs.at(0).props().name, 'advanced') - }) - }) + const renderedTabs = shallow(renderTabsResult); + const tabs = renderedTabs.find(Tab); + assert.strictEqual(tabs.length, 1); + assert.strictEqual(tabs.at(0).props().name, 'advanced'); + }); + }); describe('renderBasicTabContent', function () { it('should render', function () { const renderBasicTabContentResult = wrapper .instance() - .renderBasicTabContent(mockGasPriceButtonGroupProps) + .renderBasicTabContent(mockGasPriceButtonGroupProps); assert.deepStrictEqual( renderBasicTabContentResult.props.gasPriceButtonGroupProps, mockGasPriceButtonGroupProps, - ) - }) - }) + ); + }); + }); describe('renderInfoRows', function () { it('should render the info rows with the passed data', function () { - const baseClassName = 'gas-modal-content__info-row' + const baseClassName = 'gas-modal-content__info-row'; const renderedInfoRowsContainer = shallow( wrapper .instance() @@ -238,34 +238,34 @@ describe('GasModalPageContainer Component', function () { ' mockSendAmount', ' mockTransactionFee', ), - ) + ); - assert(renderedInfoRowsContainer.childAt(0).hasClass(baseClassName)) + assert(renderedInfoRowsContainer.childAt(0).hasClass(baseClassName)); - const renderedInfoRows = renderedInfoRowsContainer.childAt(0).children() - assert.strictEqual(renderedInfoRows.length, 4) - assert(renderedInfoRows.at(0).hasClass(`${baseClassName}__send-info`)) + const renderedInfoRows = renderedInfoRowsContainer.childAt(0).children(); + assert.strictEqual(renderedInfoRows.length, 4); + assert(renderedInfoRows.at(0).hasClass(`${baseClassName}__send-info`)); assert( renderedInfoRows.at(1).hasClass(`${baseClassName}__transaction-info`), - ) - assert(renderedInfoRows.at(2).hasClass(`${baseClassName}__total-info`)) + ); + assert(renderedInfoRows.at(2).hasClass(`${baseClassName}__total-info`)); assert( renderedInfoRows.at(3).hasClass(`${baseClassName}__fiat-total-info`), - ) + ); assert.strictEqual( renderedInfoRows.at(0).text(), 'sendAmount mockSendAmount', - ) + ); assert.strictEqual( renderedInfoRows.at(1).text(), 'transactionFee mockTransactionFee', - ) + ); assert.strictEqual( renderedInfoRows.at(2).text(), 'newTotal mockNewTotalEth', - ) - assert.strictEqual(renderedInfoRows.at(3).text(), 'mockNewTotalFiat') - }) - }) -}) + ); + assert.strictEqual(renderedInfoRows.at(3).text(), 'mockNewTotalFiat'); + }); + }); +}); diff --git a/ui/app/components/app/gas-customization/gas-modal-page-container/tests/gas-modal-page-container-container.test.js b/ui/app/components/app/gas-customization/gas-modal-page-container/tests/gas-modal-page-container-container.test.js index 81934468c..ac355d656 100644 --- a/ui/app/components/app/gas-customization/gas-modal-page-container/tests/gas-modal-page-container-container.test.js +++ b/ui/app/components/app/gas-customization/gas-modal-page-container/tests/gas-modal-page-container-container.test.js @@ -1,39 +1,39 @@ -import assert from 'assert' -import proxyquire from 'proxyquire' -import sinon from 'sinon' -import { TRANSACTION_STATUSES } from '../../../../../../../shared/constants/transaction' +import assert from 'assert'; +import proxyquire from 'proxyquire'; +import sinon from 'sinon'; +import { TRANSACTION_STATUSES } from '../../../../../../../shared/constants/transaction'; -let mapStateToProps -let mapDispatchToProps -let mergeProps +let mapStateToProps; +let mapDispatchToProps; +let mergeProps; const actionSpies = { hideModal: sinon.spy(), setGasLimit: sinon.spy(), setGasPrice: sinon.spy(), -} +}; const gasActionSpies = { setCustomGasPrice: sinon.spy(), setCustomGasLimit: sinon.spy(), resetCustomData: sinon.spy(), -} +}; const confirmTransactionActionSpies = { updateGasAndCalculate: sinon.spy(), -} +}; const sendActionSpies = { hideGasButtonGroup: sinon.spy(), -} +}; proxyquire('../gas-modal-page-container.container.js', { 'react-redux': { connect: (ms, md, mp) => { - mapStateToProps = ms - mapDispatchToProps = md - mergeProps = mp - return () => ({}) + mapStateToProps = ms; + mapDispatchToProps = md; + mergeProps = mp; + return () => ({}); }, }, '../../../../selectors': { @@ -50,7 +50,7 @@ proxyquire('../gas-modal-page-container.container.js', { '../../../../ducks/gas/gas.duck': gasActionSpies, '../../../../ducks/confirm-transaction/confirm-transaction.duck': confirmTransactionActionSpies, '../../../../ducks/send/send.duck': sendActionSpies, -}) +}); describe('gas-modal-page-container container', function () { describe('mapStateToProps()', function () { @@ -120,7 +120,7 @@ describe('gas-modal-page-container container', function () { }, }, }, - } + }; const baseExpectedResult = { balance: '0x0', isConfirm: true, @@ -158,8 +158,8 @@ describe('gas-modal-page-container container', function () { id: 34, }, value: '0x640000000000000', - } - const baseMockOwnProps = { transaction: { id: 34 } } + }; + const baseMockOwnProps = { transaction: { id: 34 } }; const tests = [ { mockState: baseMockState, @@ -257,109 +257,109 @@ describe('gas-modal-page-container container', function () { mockOwnProps: baseMockOwnProps, expectedResult: baseExpectedResult, }, - ] + ]; - let result + let result; tests.forEach(({ mockState, mockOwnProps, expectedResult }) => { - result = mapStateToProps(mockState, mockOwnProps) - assert.deepStrictEqual(result, expectedResult) - }) - }) - }) + result = mapStateToProps(mockState, mockOwnProps); + assert.deepStrictEqual(result, expectedResult); + }); + }); + }); describe('mapDispatchToProps()', function () { - let dispatchSpy - let mapDispatchToPropsObject + let dispatchSpy; + let mapDispatchToPropsObject; beforeEach(function () { - dispatchSpy = sinon.spy() - mapDispatchToPropsObject = mapDispatchToProps(dispatchSpy) - }) + dispatchSpy = sinon.spy(); + mapDispatchToPropsObject = mapDispatchToProps(dispatchSpy); + }); afterEach(function () { - actionSpies.hideModal.resetHistory() - gasActionSpies.setCustomGasPrice.resetHistory() - gasActionSpies.setCustomGasLimit.resetHistory() - }) + actionSpies.hideModal.resetHistory(); + gasActionSpies.setCustomGasPrice.resetHistory(); + gasActionSpies.setCustomGasLimit.resetHistory(); + }); describe('hideGasButtonGroup()', function () { it('should dispatch a hideGasButtonGroup action', function () { - mapDispatchToPropsObject.hideGasButtonGroup() - assert(dispatchSpy.calledOnce) - assert(sendActionSpies.hideGasButtonGroup.calledOnce) - }) - }) + mapDispatchToPropsObject.hideGasButtonGroup(); + assert(dispatchSpy.calledOnce); + assert(sendActionSpies.hideGasButtonGroup.calledOnce); + }); + }); describe('cancelAndClose()', function () { it('should dispatch a hideModal action', function () { - mapDispatchToPropsObject.cancelAndClose() - assert(dispatchSpy.calledTwice) - assert(actionSpies.hideModal.calledOnce) - assert(gasActionSpies.resetCustomData.calledOnce) - }) - }) + mapDispatchToPropsObject.cancelAndClose(); + assert(dispatchSpy.calledTwice); + assert(actionSpies.hideModal.calledOnce); + assert(gasActionSpies.resetCustomData.calledOnce); + }); + }); describe('updateCustomGasPrice()', function () { it('should dispatch a setCustomGasPrice action with the arg passed to updateCustomGasPrice hex prefixed', function () { - mapDispatchToPropsObject.updateCustomGasPrice('ffff') - assert(dispatchSpy.calledOnce) - assert(gasActionSpies.setCustomGasPrice.calledOnce) + mapDispatchToPropsObject.updateCustomGasPrice('ffff'); + assert(dispatchSpy.calledOnce); + assert(gasActionSpies.setCustomGasPrice.calledOnce); assert.strictEqual( gasActionSpies.setCustomGasPrice.getCall(0).args[0], '0xffff', - ) - }) + ); + }); it('should dispatch a setCustomGasPrice action', function () { - mapDispatchToPropsObject.updateCustomGasPrice('0xffff') - assert(dispatchSpy.calledOnce) - assert(gasActionSpies.setCustomGasPrice.calledOnce) + mapDispatchToPropsObject.updateCustomGasPrice('0xffff'); + assert(dispatchSpy.calledOnce); + assert(gasActionSpies.setCustomGasPrice.calledOnce); assert.strictEqual( gasActionSpies.setCustomGasPrice.getCall(0).args[0], '0xffff', - ) - }) - }) + ); + }); + }); describe('updateCustomGasLimit()', function () { it('should dispatch a setCustomGasLimit action', function () { - mapDispatchToPropsObject.updateCustomGasLimit('0x10') - assert(dispatchSpy.calledOnce) - assert(gasActionSpies.setCustomGasLimit.calledOnce) + mapDispatchToPropsObject.updateCustomGasLimit('0x10'); + assert(dispatchSpy.calledOnce); + assert(gasActionSpies.setCustomGasLimit.calledOnce); assert.strictEqual( gasActionSpies.setCustomGasLimit.getCall(0).args[0], '0x10', - ) - }) - }) + ); + }); + }); describe('setGasData()', function () { it('should dispatch a setGasPrice and setGasLimit action with the correct props', function () { - mapDispatchToPropsObject.setGasData('ffff', 'aaaa') - assert(dispatchSpy.calledTwice) - assert(actionSpies.setGasPrice.calledOnce) - assert(actionSpies.setGasLimit.calledOnce) - assert.strictEqual(actionSpies.setGasLimit.getCall(0).args[0], 'ffff') - assert.strictEqual(actionSpies.setGasPrice.getCall(0).args[0], 'aaaa') - }) - }) + mapDispatchToPropsObject.setGasData('ffff', 'aaaa'); + assert(dispatchSpy.calledTwice); + assert(actionSpies.setGasPrice.calledOnce); + assert(actionSpies.setGasLimit.calledOnce); + assert.strictEqual(actionSpies.setGasLimit.getCall(0).args[0], 'ffff'); + assert.strictEqual(actionSpies.setGasPrice.getCall(0).args[0], 'aaaa'); + }); + }); describe('updateConfirmTxGasAndCalculate()', function () { it('should dispatch a updateGasAndCalculate action with the correct props', function () { - mapDispatchToPropsObject.updateConfirmTxGasAndCalculate('ffff', 'aaaa') - assert.strictEqual(dispatchSpy.callCount, 3) - assert(actionSpies.setGasPrice.calledOnce) - assert(actionSpies.setGasLimit.calledOnce) - assert.strictEqual(actionSpies.setGasLimit.getCall(0).args[0], 'ffff') - assert.strictEqual(actionSpies.setGasPrice.getCall(0).args[0], 'aaaa') - }) - }) - }) + mapDispatchToPropsObject.updateConfirmTxGasAndCalculate('ffff', 'aaaa'); + assert.strictEqual(dispatchSpy.callCount, 3); + assert(actionSpies.setGasPrice.calledOnce); + assert(actionSpies.setGasLimit.calledOnce); + assert.strictEqual(actionSpies.setGasLimit.getCall(0).args[0], 'ffff'); + assert.strictEqual(actionSpies.setGasPrice.getCall(0).args[0], 'aaaa'); + }); + }); + }); describe('mergeProps', function () { - let stateProps - let dispatchProps - let ownProps + let stateProps; + let dispatchProps; + let ownProps; beforeEach(function () { stateProps = { @@ -370,7 +370,7 @@ describe('gas-modal-page-container container', function () { isConfirm: true, someOtherStateProp: 'baz', transaction: {}, - } + }; dispatchProps = { updateCustomGasPrice: sinon.spy(), hideGasButtonGroup: sinon.spy(), @@ -381,135 +381,135 @@ describe('gas-modal-page-container container', function () { hideSidebar: sinon.spy(), hideModal: sinon.spy(), cancelAndClose: sinon.spy(), - } - ownProps = { someOwnProp: 123 } - }) + }; + ownProps = { someOwnProp: 123 }; + }); afterEach(function () { - dispatchProps.updateCustomGasPrice.resetHistory() - dispatchProps.hideGasButtonGroup.resetHistory() - dispatchProps.setGasData.resetHistory() - dispatchProps.updateConfirmTxGasAndCalculate.resetHistory() - dispatchProps.someOtherDispatchProp.resetHistory() - dispatchProps.createSpeedUpTransaction.resetHistory() - dispatchProps.hideSidebar.resetHistory() - dispatchProps.hideModal.resetHistory() - }) + dispatchProps.updateCustomGasPrice.resetHistory(); + dispatchProps.hideGasButtonGroup.resetHistory(); + dispatchProps.setGasData.resetHistory(); + dispatchProps.updateConfirmTxGasAndCalculate.resetHistory(); + dispatchProps.someOtherDispatchProp.resetHistory(); + dispatchProps.createSpeedUpTransaction.resetHistory(); + dispatchProps.hideSidebar.resetHistory(); + dispatchProps.hideModal.resetHistory(); + }); it('should return the expected props when isConfirm is true', function () { - const result = mergeProps(stateProps, dispatchProps, ownProps) + const result = mergeProps(stateProps, dispatchProps, ownProps); - assert.strictEqual(result.isConfirm, true) - assert.strictEqual(result.someOtherStateProp, 'baz') + assert.strictEqual(result.isConfirm, true); + assert.strictEqual(result.someOtherStateProp, 'baz'); assert.strictEqual( result.gasPriceButtonGroupProps.someGasPriceButtonGroupProp, 'foo', - ) + ); assert.strictEqual( result.gasPriceButtonGroupProps.anotherGasPriceButtonGroupProp, 'bar', - ) - assert.strictEqual(result.someOwnProp, 123) + ); + assert.strictEqual(result.someOwnProp, 123); assert.strictEqual( dispatchProps.updateConfirmTxGasAndCalculate.callCount, 0, - ) - assert.strictEqual(dispatchProps.setGasData.callCount, 0) - assert.strictEqual(dispatchProps.hideGasButtonGroup.callCount, 0) - assert.strictEqual(dispatchProps.hideModal.callCount, 0) + ); + assert.strictEqual(dispatchProps.setGasData.callCount, 0); + assert.strictEqual(dispatchProps.hideGasButtonGroup.callCount, 0); + assert.strictEqual(dispatchProps.hideModal.callCount, 0); - result.onSubmit() + result.onSubmit(); assert.strictEqual( dispatchProps.updateConfirmTxGasAndCalculate.callCount, 1, - ) - assert.strictEqual(dispatchProps.setGasData.callCount, 0) - assert.strictEqual(dispatchProps.hideGasButtonGroup.callCount, 0) - assert.strictEqual(dispatchProps.hideModal.callCount, 1) + ); + assert.strictEqual(dispatchProps.setGasData.callCount, 0); + assert.strictEqual(dispatchProps.hideGasButtonGroup.callCount, 0); + assert.strictEqual(dispatchProps.hideModal.callCount, 1); - assert.strictEqual(dispatchProps.updateCustomGasPrice.callCount, 0) + assert.strictEqual(dispatchProps.updateCustomGasPrice.callCount, 0); result.gasPriceButtonGroupProps.handleGasPriceSelection({ gasPrice: '0x0', - }) - assert.strictEqual(dispatchProps.updateCustomGasPrice.callCount, 1) + }); + assert.strictEqual(dispatchProps.updateCustomGasPrice.callCount, 1); - assert.strictEqual(dispatchProps.someOtherDispatchProp.callCount, 0) - result.someOtherDispatchProp() - assert.strictEqual(dispatchProps.someOtherDispatchProp.callCount, 1) - }) + assert.strictEqual(dispatchProps.someOtherDispatchProp.callCount, 0); + result.someOtherDispatchProp(); + assert.strictEqual(dispatchProps.someOtherDispatchProp.callCount, 1); + }); it('should return the expected props when isConfirm is false', function () { const result = mergeProps( { ...stateProps, isConfirm: false }, dispatchProps, ownProps, - ) + ); - assert.strictEqual(result.isConfirm, false) - assert.strictEqual(result.someOtherStateProp, 'baz') + assert.strictEqual(result.isConfirm, false); + assert.strictEqual(result.someOtherStateProp, 'baz'); assert.strictEqual( result.gasPriceButtonGroupProps.someGasPriceButtonGroupProp, 'foo', - ) + ); assert.strictEqual( result.gasPriceButtonGroupProps.anotherGasPriceButtonGroupProp, 'bar', - ) - assert.strictEqual(result.someOwnProp, 123) + ); + assert.strictEqual(result.someOwnProp, 123); assert.strictEqual( dispatchProps.updateConfirmTxGasAndCalculate.callCount, 0, - ) - assert.strictEqual(dispatchProps.setGasData.callCount, 0) - assert.strictEqual(dispatchProps.hideGasButtonGroup.callCount, 0) - assert.strictEqual(dispatchProps.cancelAndClose.callCount, 0) + ); + assert.strictEqual(dispatchProps.setGasData.callCount, 0); + assert.strictEqual(dispatchProps.hideGasButtonGroup.callCount, 0); + assert.strictEqual(dispatchProps.cancelAndClose.callCount, 0); - result.onSubmit('mockNewLimit', 'mockNewPrice') + result.onSubmit('mockNewLimit', 'mockNewPrice'); assert.strictEqual( dispatchProps.updateConfirmTxGasAndCalculate.callCount, 0, - ) - assert.strictEqual(dispatchProps.setGasData.callCount, 1) + ); + assert.strictEqual(dispatchProps.setGasData.callCount, 1); assert.deepStrictEqual(dispatchProps.setGasData.getCall(0).args, [ 'mockNewLimit', 'mockNewPrice', - ]) - assert.strictEqual(dispatchProps.hideGasButtonGroup.callCount, 1) - assert.strictEqual(dispatchProps.cancelAndClose.callCount, 1) + ]); + assert.strictEqual(dispatchProps.hideGasButtonGroup.callCount, 1); + assert.strictEqual(dispatchProps.cancelAndClose.callCount, 1); - assert.strictEqual(dispatchProps.updateCustomGasPrice.callCount, 0) + assert.strictEqual(dispatchProps.updateCustomGasPrice.callCount, 0); result.gasPriceButtonGroupProps.handleGasPriceSelection({ gasPrice: '0x0', - }) - assert.strictEqual(dispatchProps.updateCustomGasPrice.callCount, 1) + }); + assert.strictEqual(dispatchProps.updateCustomGasPrice.callCount, 1); - assert.strictEqual(dispatchProps.someOtherDispatchProp.callCount, 0) - result.someOtherDispatchProp() - assert.strictEqual(dispatchProps.someOtherDispatchProp.callCount, 1) - }) + assert.strictEqual(dispatchProps.someOtherDispatchProp.callCount, 0); + result.someOtherDispatchProp(); + assert.strictEqual(dispatchProps.someOtherDispatchProp.callCount, 1); + }); it('should dispatch the expected actions from obSubmit when isConfirm is false and isSpeedUp is true', function () { const result = mergeProps( { ...stateProps, isSpeedUp: true, isConfirm: false }, dispatchProps, ownProps, - ) + ); - result.onSubmit() + result.onSubmit(); assert.strictEqual( dispatchProps.updateConfirmTxGasAndCalculate.callCount, 0, - ) - assert.strictEqual(dispatchProps.setGasData.callCount, 0) - assert.strictEqual(dispatchProps.hideGasButtonGroup.callCount, 0) - assert.strictEqual(dispatchProps.cancelAndClose.callCount, 1) + ); + assert.strictEqual(dispatchProps.setGasData.callCount, 0); + assert.strictEqual(dispatchProps.hideGasButtonGroup.callCount, 0); + assert.strictEqual(dispatchProps.cancelAndClose.callCount, 1); - assert.strictEqual(dispatchProps.createSpeedUpTransaction.callCount, 1) - assert.strictEqual(dispatchProps.hideSidebar.callCount, 1) - }) - }) -}) + assert.strictEqual(dispatchProps.createSpeedUpTransaction.callCount, 1); + assert.strictEqual(dispatchProps.hideSidebar.callCount, 1); + }); + }); +}); diff --git a/ui/app/components/app/gas-customization/gas-price-button-group/gas-price-button-group.component.js b/ui/app/components/app/gas-customization/gas-price-button-group/gas-price-button-group.component.js index 044df3dc5..072c59b91 100644 --- a/ui/app/components/app/gas-customization/gas-price-button-group/gas-price-button-group.component.js +++ b/ui/app/components/app/gas-customization/gas-price-button-group/gas-price-button-group.component.js @@ -1,8 +1,8 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import ButtonGroup from '../../../ui/button-group' -import Button from '../../../ui/button' -import { GAS_ESTIMATE_TYPES } from '../../../../helpers/constants/common' +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import ButtonGroup from '../../../ui/button-group'; +import Button from '../../../ui/button'; +import { GAS_ESTIMATE_TYPES } from '../../../../helpers/constants/common'; const GAS_OBJECT_PROPTYPES_SHAPE = { gasEstimateType: PropTypes.oneOf(Object.values(GAS_ESTIMATE_TYPES)) @@ -11,12 +11,12 @@ const GAS_OBJECT_PROPTYPES_SHAPE = { feeInSecondaryCurrency: PropTypes.string, timeEstimate: PropTypes.string, priceInHexWei: PropTypes.string, -} +}; export default class GasPriceButtonGroup extends Component { static contextTypes = { t: PropTypes.func, - } + }; static propTypes = { buttonDataLoading: PropTypes.bool, @@ -29,19 +29,19 @@ export default class GasPriceButtonGroup extends Component { newActiveButtonIndex: PropTypes.number, noButtonActiveByDefault: PropTypes.bool, showCheck: PropTypes.bool, - } + }; gasEstimateTypeLabel(gasEstimateType) { if (gasEstimateType === GAS_ESTIMATE_TYPES.SLOW) { - return this.context.t('slow') + return this.context.t('slow'); } else if (gasEstimateType === GAS_ESTIMATE_TYPES.AVERAGE) { - return this.context.t('average') + return this.context.t('average'); } else if (gasEstimateType === GAS_ESTIMATE_TYPES.FAST) { - return this.context.t('fast') + return this.context.t('fast'); } else if (gasEstimateType === GAS_ESTIMATE_TYPES.FASTEST) { - return this.context.t('fastest') + return this.context.t('fastest'); } - throw new Error(`Unrecognized gas estimate type: ${gasEstimateType}`) + throw new Error(`Unrecognized gas estimate type: ${gasEstimateType}`); } renderButtonContent( @@ -79,7 +79,7 @@ export default class GasPriceButtonGroup extends Component { )} - ) + ); } renderButton( @@ -106,7 +106,7 @@ export default class GasPriceButtonGroup extends Component { buttonContentPropsAndFlags, )} - ) + ); } render() { @@ -117,7 +117,7 @@ export default class GasPriceButtonGroup extends Component { noButtonActiveByDefault = false, buttonDataLoading, ...buttonPropsAndFlags - } = this.props + } = this.props; return buttonDataLoading ? (
    @@ -134,6 +134,6 @@ export default class GasPriceButtonGroup extends Component { this.renderButton(obj, buttonPropsAndFlags, index), )} - ) + ); } } diff --git a/ui/app/components/app/gas-customization/gas-price-button-group/index.js b/ui/app/components/app/gas-customization/gas-price-button-group/index.js index 775648330..23a9d8dd2 100644 --- a/ui/app/components/app/gas-customization/gas-price-button-group/index.js +++ b/ui/app/components/app/gas-customization/gas-price-button-group/index.js @@ -1 +1 @@ -export { default } from './gas-price-button-group.component' +export { default } from './gas-price-button-group.component'; diff --git a/ui/app/components/app/gas-customization/gas-price-button-group/tests/gas-price-button-group-component.test.js b/ui/app/components/app/gas-customization/gas-price-button-group/tests/gas-price-button-group-component.test.js index 966d4e115..7bf35c1a8 100644 --- a/ui/app/components/app/gas-customization/gas-price-button-group/tests/gas-price-button-group-component.test.js +++ b/ui/app/components/app/gas-customization/gas-price-button-group/tests/gas-price-button-group-component.test.js @@ -1,16 +1,16 @@ -import assert from 'assert' -import React from 'react' -import sinon from 'sinon' -import shallow from '../../../../../../lib/shallow-with-context' -import GasPriceButtonGroup from '../gas-price-button-group.component' -import { GAS_ESTIMATE_TYPES } from '../../../../../helpers/constants/common' +import assert from 'assert'; +import React from 'react'; +import sinon from 'sinon'; +import shallow from '../../../../../../lib/shallow-with-context'; +import GasPriceButtonGroup from '../gas-price-button-group.component'; +import { GAS_ESTIMATE_TYPES } from '../../../../../helpers/constants/common'; -import ButtonGroup from '../../../../ui/button-group' +import ButtonGroup from '../../../../ui/button-group'; describe('GasPriceButtonGroup Component', function () { - let mockButtonPropsAndFlags - let mockGasPriceButtonGroupProps - let wrapper + let mockButtonPropsAndFlags; + let mockGasPriceButtonGroupProps; + let wrapper; beforeEach(function () { mockGasPriceButtonGroupProps = { @@ -43,40 +43,42 @@ describe('GasPriceButtonGroup Component', function () { noButtonActiveByDefault: true, defaultActiveButtonIndex: 2, showCheck: true, - } + }; mockButtonPropsAndFlags = { className: mockGasPriceButtonGroupProps.className, handleGasPriceSelection: mockGasPriceButtonGroupProps.handleGasPriceSelection, showCheck: mockGasPriceButtonGroupProps.showCheck, - } + }; - sinon.spy(GasPriceButtonGroup.prototype, 'renderButton') - sinon.spy(GasPriceButtonGroup.prototype, 'renderButtonContent') + sinon.spy(GasPriceButtonGroup.prototype, 'renderButton'); + sinon.spy(GasPriceButtonGroup.prototype, 'renderButtonContent'); - wrapper = shallow() - }) + wrapper = shallow( + , + ); + }); afterEach(function () { - sinon.restore() - }) + sinon.restore(); + }); describe('render', function () { it('should render a ButtonGroup', function () { - assert(wrapper.is(ButtonGroup)) - }) + assert(wrapper.is(ButtonGroup)); + }); it('should render the correct props on the ButtonGroup', function () { const { className, defaultActiveButtonIndex, noButtonActiveByDefault, - } = wrapper.props() - assert.strictEqual(className, 'gas-price-button-group') - assert.strictEqual(defaultActiveButtonIndex, 2) - assert.strictEqual(noButtonActiveByDefault, true) - }) + } = wrapper.props(); + assert.strictEqual(className, 'gas-price-button-group'); + assert.strictEqual(defaultActiveButtonIndex, 2); + assert.strictEqual(noButtonActiveByDefault, true); + }); function renderButtonArgsTest(i, mockPropsAndFlags) { assert.deepStrictEqual( @@ -86,55 +88,55 @@ describe('GasPriceButtonGroup Component', function () { mockPropsAndFlags, i, ], - ) + ); } it('should call this.renderButton 3 times, with the correct args', function () { assert.strictEqual( GasPriceButtonGroup.prototype.renderButton.callCount, 3, - ) - renderButtonArgsTest(0, mockButtonPropsAndFlags) - renderButtonArgsTest(1, mockButtonPropsAndFlags) - renderButtonArgsTest(2, mockButtonPropsAndFlags) - }) + ); + renderButtonArgsTest(0, mockButtonPropsAndFlags); + renderButtonArgsTest(1, mockButtonPropsAndFlags); + renderButtonArgsTest(2, mockButtonPropsAndFlags); + }); it('should show loading if buttonDataLoading', function () { - wrapper.setProps({ buttonDataLoading: true }) - assert(wrapper.is('div')) - assert(wrapper.hasClass('gas-price-button-group__loading-container')) - assert.strictEqual(wrapper.text(), 'loading') - }) - }) + wrapper.setProps({ buttonDataLoading: true }); + assert(wrapper.is('div')); + assert(wrapper.hasClass('gas-price-button-group__loading-container')); + assert.strictEqual(wrapper.text(), 'loading'); + }); + }); describe('renderButton', function () { - let wrappedRenderButtonResult + let wrappedRenderButtonResult; beforeEach(function () { - GasPriceButtonGroup.prototype.renderButtonContent.resetHistory() + GasPriceButtonGroup.prototype.renderButtonContent.resetHistory(); const renderButtonResult = wrapper .instance() .renderButton( { ...mockGasPriceButtonGroupProps.gasButtonInfo[0] }, mockButtonPropsAndFlags, - ) - wrappedRenderButtonResult = shallow(renderButtonResult) - }) + ); + wrappedRenderButtonResult = shallow(renderButtonResult); + }); it('should render a button', function () { - assert.strictEqual(wrappedRenderButtonResult.type(), 'button') - }) + assert.strictEqual(wrappedRenderButtonResult.type(), 'button'); + }); it('should call the correct method when clicked', function () { assert.strictEqual( mockGasPriceButtonGroupProps.handleGasPriceSelection.callCount, 0, - ) - wrappedRenderButtonResult.props().onClick() + ); + wrappedRenderButtonResult.props().onClick(); assert.strictEqual( mockGasPriceButtonGroupProps.handleGasPriceSelection.callCount, 1, - ) + ); assert.deepStrictEqual( mockGasPriceButtonGroupProps.handleGasPriceSelection.getCall(0).args, [ @@ -145,21 +147,21 @@ describe('GasPriceButtonGroup Component', function () { mockGasPriceButtonGroupProps.gasButtonInfo[0].gasEstimateType, }, ], - ) - }) + ); + }); it('should call this.renderButtonContent with the correct args', function () { assert.strictEqual( GasPriceButtonGroup.prototype.renderButtonContent.callCount, 1, - ) + ); const { feeInPrimaryCurrency, feeInSecondaryCurrency, timeEstimate, gasEstimateType, - } = mockGasPriceButtonGroupProps.gasButtonInfo[0] - const { showCheck, className } = mockGasPriceButtonGroupProps + } = mockGasPriceButtonGroupProps.gasButtonInfo[0]; + const { showCheck, className } = mockGasPriceButtonGroupProps; assert.deepStrictEqual( GasPriceButtonGroup.prototype.renderButtonContent.getCall(0).args, [ @@ -174,9 +176,9 @@ describe('GasPriceButtonGroup Component', function () { className, }, ], - ) - }) - }) + ); + }); + }); describe('renderButtonContent', function () { it('should render a label if passed a gasEstimateType', function () { @@ -187,19 +189,19 @@ describe('GasPriceButtonGroup Component', function () { { className: 'someClass', }, - ) + ); const wrappedRenderButtonContentResult = shallow( renderButtonContentResult, - ) + ); assert.strictEqual( wrappedRenderButtonContentResult.childAt(0).children().length, 1, - ) + ); assert.strictEqual( wrappedRenderButtonContentResult.find('.someClass__label').text(), 'slow', - ) - }) + ); + }); it('should render a feeInPrimaryCurrency if passed a feeInPrimaryCurrency', function () { const renderButtonContentResult = GasPriceButtonGroup.prototype.renderButtonContent( @@ -209,21 +211,21 @@ describe('GasPriceButtonGroup Component', function () { { className: 'someClass', }, - ) + ); const wrappedRenderButtonContentResult = shallow( renderButtonContentResult, - ) + ); assert.strictEqual( wrappedRenderButtonContentResult.childAt(0).children().length, 1, - ) + ); assert.strictEqual( wrappedRenderButtonContentResult .find('.someClass__primary-currency') .text(), 'mockFeeInPrimaryCurrency', - ) - }) + ); + }); it('should render a feeInSecondaryCurrency if passed a feeInSecondaryCurrency', function () { const renderButtonContentResult = GasPriceButtonGroup.prototype.renderButtonContent( @@ -233,21 +235,21 @@ describe('GasPriceButtonGroup Component', function () { { className: 'someClass', }, - ) + ); const wrappedRenderButtonContentResult = shallow( renderButtonContentResult, - ) + ); assert.strictEqual( wrappedRenderButtonContentResult.childAt(0).children().length, 1, - ) + ); assert.strictEqual( wrappedRenderButtonContentResult .find('.someClass__secondary-currency') .text(), 'mockFeeInSecondaryCurrency', - ) - }) + ); + }); it('should render a timeEstimate if passed a timeEstimate', function () { const renderButtonContentResult = GasPriceButtonGroup.prototype.renderButtonContent( @@ -257,21 +259,21 @@ describe('GasPriceButtonGroup Component', function () { { className: 'someClass', }, - ) + ); const wrappedRenderButtonContentResult = shallow( renderButtonContentResult, - ) + ); assert.strictEqual( wrappedRenderButtonContentResult.childAt(0).children().length, 1, - ) + ); assert.strictEqual( wrappedRenderButtonContentResult .find('.someClass__time-estimate') .text(), 'mockTimeEstimate', - ) - }) + ); + }); it('should render a check if showCheck is true', function () { const renderButtonContentResult = GasPriceButtonGroup.prototype.renderButtonContent( @@ -280,15 +282,15 @@ describe('GasPriceButtonGroup Component', function () { className: 'someClass', showCheck: true, }, - ) + ); const wrappedRenderButtonContentResult = shallow( renderButtonContentResult, - ) + ); assert.strictEqual( wrappedRenderButtonContentResult.find('.fa-check').length, 1, - ) - }) + ); + }); it('should render all elements if all args passed', function () { const renderButtonContentResult = wrapper.instance().renderButtonContent( @@ -302,22 +304,22 @@ describe('GasPriceButtonGroup Component', function () { className: 'someClass', showCheck: true, }, - ) + ); const wrappedRenderButtonContentResult = shallow( renderButtonContentResult, - ) - assert.strictEqual(wrappedRenderButtonContentResult.children().length, 5) - }) + ); + assert.strictEqual(wrappedRenderButtonContentResult.children().length, 5); + }); it('should render no elements if all args passed', function () { const renderButtonContentResult = GasPriceButtonGroup.prototype.renderButtonContent( {}, {}, - ) + ); const wrappedRenderButtonContentResult = shallow( renderButtonContentResult, - ) - assert.strictEqual(wrappedRenderButtonContentResult.children().length, 0) - }) - }) -}) + ); + assert.strictEqual(wrappedRenderButtonContentResult.children().length, 0); + }); + }); +}); diff --git a/ui/app/components/app/gas-customization/gas-slider/gas-slider.component.js b/ui/app/components/app/gas-customization/gas-slider/gas-slider.component.js index db5c01b8b..89f4dbd36 100644 --- a/ui/app/components/app/gas-customization/gas-slider/gas-slider.component.js +++ b/ui/app/components/app/gas-customization/gas-slider/gas-slider.component.js @@ -1,5 +1,5 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; export default class GasSlider extends Component { static propTypes = { @@ -10,10 +10,10 @@ export default class GasSlider extends Component { step: PropTypes.number, max: PropTypes.number, min: PropTypes.number, - } + }; render() { - const { onChange, lowLabel, highLabel, value, step, max, min } = this.props + const { onChange, lowLabel, highLabel, value, step, max, min } = this.props; return (
    @@ -35,6 +35,6 @@ export default class GasSlider extends Component { {highLabel}
    - ) + ); } } diff --git a/ui/app/components/app/gas-customization/gas-slider/index.js b/ui/app/components/app/gas-customization/gas-slider/index.js index f1752c93f..663e57878 100644 --- a/ui/app/components/app/gas-customization/gas-slider/index.js +++ b/ui/app/components/app/gas-customization/gas-slider/index.js @@ -1 +1 @@ -export { default } from './gas-slider.component' +export { default } from './gas-slider.component'; diff --git a/ui/app/components/app/home-notification/home-notification.component.js b/ui/app/components/app/home-notification/home-notification.component.js index 0ae4d85f9..b5186db39 100644 --- a/ui/app/components/app/home-notification/home-notification.component.js +++ b/ui/app/components/app/home-notification/home-notification.component.js @@ -1,9 +1,9 @@ -import React, { useState } from 'react' -import classnames from 'classnames' -import PropTypes from 'prop-types' -import Button from '../../ui/button' -import Checkbox from '../../ui/check-box' -import Tooltip from '../../ui/tooltip' +import React, { useState } from 'react'; +import classnames from 'classnames'; +import PropTypes from 'prop-types'; +import Button from '../../ui/button'; +import Checkbox from '../../ui/check-box'; +import Tooltip from '../../ui/tooltip'; const HomeNotification = ({ acceptText, @@ -16,7 +16,7 @@ const HomeNotification = ({ onAccept, onIgnore, }) => { - const [checkboxState, setCheckBoxState] = useState(false) + const [checkboxState, setCheckBoxState] = useState(false); const checkboxElement = checkboxText && ( setCheckBoxState((checked) => !checked)} /> - ) + ); return (
    @@ -87,8 +87,8 @@ const HomeNotification = ({ ) : null}
    - ) -} + ); +}; HomeNotification.propTypes = { acceptText: PropTypes.node, @@ -100,6 +100,6 @@ HomeNotification.propTypes = { infoText: PropTypes.node, onAccept: PropTypes.func, onIgnore: PropTypes.func, -} +}; -export default HomeNotification +export default HomeNotification; diff --git a/ui/app/components/app/home-notification/index.js b/ui/app/components/app/home-notification/index.js index 918a35be2..5068da7aa 100644 --- a/ui/app/components/app/home-notification/index.js +++ b/ui/app/components/app/home-notification/index.js @@ -1 +1 @@ -export { default } from './home-notification.component' +export { default } from './home-notification.component'; diff --git a/ui/app/components/app/info-box/index.js b/ui/app/components/app/info-box/index.js index 59b0d294b..011ff8189 100644 --- a/ui/app/components/app/info-box/index.js +++ b/ui/app/components/app/info-box/index.js @@ -1,3 +1,3 @@ -import InfoBox from './info-box.component' +import InfoBox from './info-box.component'; -export default InfoBox +export default InfoBox; diff --git a/ui/app/components/app/info-box/info-box.component.js b/ui/app/components/app/info-box/info-box.component.js index 84e8c3b63..8ef9dc5f3 100644 --- a/ui/app/components/app/info-box/info-box.component.js +++ b/ui/app/components/app/info-box/info-box.component.js @@ -1,33 +1,33 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; export default class InfoBox extends Component { static contextTypes = { t: PropTypes.func, - } + }; static propTypes = { onClose: PropTypes.func, title: PropTypes.string, description: PropTypes.string, - } + }; state = { isShowing: true, - } + }; handleClose() { - const { onClose } = this.props + const { onClose } = this.props; if (onClose) { - onClose() + onClose(); } else { - this.setState({ isShowing: false }) + this.setState({ isShowing: false }); } } render() { - const { title, description } = this.props + const { title, description } = this.props; return this.state.isShowing ? (
    @@ -35,6 +35,6 @@ export default class InfoBox extends Component {
    {title}
    {description}
    - ) : null + ) : null; } } diff --git a/ui/app/components/app/info-box/tests/info-box.test.js b/ui/app/components/app/info-box/tests/info-box.test.js index 82f019e01..04c5056d5 100644 --- a/ui/app/components/app/info-box/tests/info-box.test.js +++ b/ui/app/components/app/info-box/tests/info-box.test.js @@ -1,36 +1,36 @@ -import assert from 'assert' -import React from 'react' -import sinon from 'sinon' -import { shallow } from 'enzyme' +import assert from 'assert'; +import React from 'react'; +import sinon from 'sinon'; +import { shallow } from 'enzyme'; -import InfoBox from '..' +import InfoBox from '..'; describe('InfoBox', function () { - let wrapper + let wrapper; const props = { title: 'Title', description: 'Description', onClose: sinon.spy(), - } + }; beforeEach(function () { - wrapper = shallow() - }) + wrapper = shallow(); + }); it('renders title from props', function () { - const title = wrapper.find('.info-box__title') - assert.strictEqual(title.text(), props.title) - }) + const title = wrapper.find('.info-box__title'); + assert.strictEqual(title.text(), props.title); + }); it('renders description from props', function () { - const description = wrapper.find('.info-box__description') - assert.strictEqual(description.text(), props.description) - }) + const description = wrapper.find('.info-box__description'); + assert.strictEqual(description.text(), props.description); + }); it('closes info box', function () { - const close = wrapper.find('.info-box__close') - close.simulate('click') - assert(props.onClose.calledOnce) - }) -}) + const close = wrapper.find('.info-box__close'); + close.simulate('click'); + assert(props.onClose.calledOnce); + }); +}); diff --git a/ui/app/components/app/loading-network-screen/index.js b/ui/app/components/app/loading-network-screen/index.js index 726b4b530..092184496 100644 --- a/ui/app/components/app/loading-network-screen/index.js +++ b/ui/app/components/app/loading-network-screen/index.js @@ -1 +1 @@ -export { default } from './loading-network-screen.container' +export { default } from './loading-network-screen.container'; diff --git a/ui/app/components/app/loading-network-screen/loading-network-screen.component.js b/ui/app/components/app/loading-network-screen/loading-network-screen.component.js index 3f3def230..0419aed42 100644 --- a/ui/app/components/app/loading-network-screen/loading-network-screen.component.js +++ b/ui/app/components/app/loading-network-screen/loading-network-screen.component.js @@ -1,16 +1,16 @@ -import React, { PureComponent } from 'react' -import PropTypes from 'prop-types' -import Button from '../../ui/button' -import LoadingScreen from '../../ui/loading-screen' +import React, { PureComponent } from 'react'; +import PropTypes from 'prop-types'; +import Button from '../../ui/button'; +import LoadingScreen from '../../ui/loading-screen'; export default class LoadingNetworkScreen extends PureComponent { state = { showErrorScreen: false, - } + }; static contextTypes = { t: PropTypes.func, - } + }; static propTypes = { loadingMessage: PropTypes.string, @@ -22,43 +22,47 @@ export default class LoadingNetworkScreen extends PureComponent { setProviderType: PropTypes.func, rollbackToPreviousProvider: PropTypes.func, isLoadingNetwork: PropTypes.bool, - } + }; componentDidMount = () => { this.cancelCallTimeout = setTimeout( this.cancelCall, this.props.cancelTime || 15000, - ) - } + ); + }; getConnectingLabel = function (loadingMessage) { if (loadingMessage) { - return loadingMessage + return loadingMessage; } - const { provider, providerId } = this.props - const providerName = provider.type + const { provider, providerId } = this.props; + const providerName = provider.type; - let name + let name; if (providerName === 'mainnet') { - name = this.context.t('connectingToMainnet') + name = this.context.t('connectingToMainnet'); } else if (providerName === 'ropsten') { - name = this.context.t('connectingToRopsten') + name = this.context.t('connectingToRopsten'); } else if (providerName === 'kovan') { - name = this.context.t('connectingToKovan') + name = this.context.t('connectingToKovan'); } else if (providerName === 'rinkeby') { - name = this.context.t('connectingToRinkeby') + name = this.context.t('connectingToRinkeby'); } else if (providerName === 'goerli') { - name = this.context.t('connectingToGoerli') + name = this.context.t('connectingToGoerli'); } else { - name = this.context.t('connectingTo', [providerId]) + name = this.context.t('connectingTo', [providerId]); } - return name - } + return name; + }; renderErrorScreenContent = () => { - const { showNetworkDropdown, setProviderArgs, setProviderType } = this.props + const { + showNetworkDropdown, + setProviderArgs, + setProviderType, + } = this.props; return (
    @@ -68,8 +72,8 @@ export default class LoadingNetworkScreen extends PureComponent {
    - ) - } + ); + }; cancelCall = () => { - const { isLoadingNetwork } = this.props + const { isLoadingNetwork } = this.props; if (isLoadingNetwork) { - this.setState({ showErrorScreen: true }) + this.setState({ showErrorScreen: true }); } - } + }; componentDidUpdate = (prevProps) => { - const { provider } = this.props - const { provider: prevProvider } = prevProps + const { provider } = this.props; + const { provider: prevProvider } = prevProps; if (provider.type !== prevProvider.type) { - window.clearTimeout(this.cancelCallTimeout) - this.setState({ showErrorScreen: false }) + window.clearTimeout(this.cancelCallTimeout); + this.setState({ showErrorScreen: false }); this.cancelCallTimeout = setTimeout( this.cancelCall, this.props.cancelTime || 15000, - ) + ); } - } + }; componentWillUnmount = () => { - window.clearTimeout(this.cancelCallTimeout) - } + window.clearTimeout(this.cancelCallTimeout); + }; render() { - const { rollbackToPreviousProvider } = this.props + const { rollbackToPreviousProvider } = this.props; return ( - ) + ); } } diff --git a/ui/app/components/app/loading-network-screen/loading-network-screen.container.js b/ui/app/components/app/loading-network-screen/loading-network-screen.container.js index 9dbb96b85..5ebddae61 100644 --- a/ui/app/components/app/loading-network-screen/loading-network-screen.container.js +++ b/ui/app/components/app/loading-network-screen/loading-network-screen.container.js @@ -1,18 +1,18 @@ -import { connect } from 'react-redux' -import { NETWORK_TYPE_RPC } from '../../../../../shared/constants/network' -import * as actions from '../../../store/actions' -import { getNetworkIdentifier } from '../../../selectors' -import LoadingNetworkScreen from './loading-network-screen.component' +import { connect } from 'react-redux'; +import { NETWORK_TYPE_RPC } from '../../../../../shared/constants/network'; +import * as actions from '../../../store/actions'; +import { getNetworkIdentifier } from '../../../selectors'; +import LoadingNetworkScreen from './loading-network-screen.component'; const mapStateToProps = (state) => { - const { loadingMessage } = state.appState - const { provider, network } = state.metamask - const { rpcUrl, chainId, ticker, nickname, type } = provider + const { loadingMessage } = state.appState; + const { provider, network } = state.metamask; + const { rpcUrl, chainId, ticker, nickname, type } = provider; const setProviderArgs = type === NETWORK_TYPE_RPC ? [rpcUrl, chainId, ticker, nickname] - : [provider.type] + : [provider.type]; return { isLoadingNetwork: network === 'loading', @@ -20,21 +20,21 @@ const mapStateToProps = (state) => { setProviderArgs, provider, providerId: getNetworkIdentifier(state), - } -} + }; +}; const mapDispatchToProps = (dispatch) => { return { setProviderType: (type) => { - dispatch(actions.setProviderType(type)) + dispatch(actions.setProviderType(type)); }, rollbackToPreviousProvider: () => dispatch(actions.rollbackToPreviousProvider()), showNetworkDropdown: () => dispatch(actions.showNetworkDropdown()), - } -} + }; +}; export default connect( mapStateToProps, mapDispatchToProps, -)(LoadingNetworkScreen) +)(LoadingNetworkScreen); diff --git a/ui/app/components/app/menu-bar/account-options-menu.js b/ui/app/components/app/menu-bar/account-options-menu.js index d3c9723e7..8d11bb057 100644 --- a/ui/app/components/app/menu-bar/account-options-menu.js +++ b/ui/app/components/app/menu-bar/account-options-menu.js @@ -1,63 +1,63 @@ -import React from 'react' -import PropTypes from 'prop-types' -import { useHistory } from 'react-router-dom' -import { useDispatch, useSelector } from 'react-redux' +import React from 'react'; +import PropTypes from 'prop-types'; +import { useHistory } from 'react-router-dom'; +import { useDispatch, useSelector } from 'react-redux'; -import { showModal } from '../../../store/actions' -import { CONNECTED_ROUTE } from '../../../helpers/constants/routes' -import { Menu, MenuItem } from '../../ui/menu' -import getAccountLink from '../../../../lib/account-link' +import { showModal } from '../../../store/actions'; +import { CONNECTED_ROUTE } from '../../../helpers/constants/routes'; +import { Menu, MenuItem } from '../../ui/menu'; +import getAccountLink from '../../../../lib/account-link'; import { getCurrentKeyring, getCurrentNetwork, getRpcPrefsForCurrentProvider, getSelectedIdentity, -} from '../../../selectors' -import { useI18nContext } from '../../../hooks/useI18nContext' -import { useMetricEvent } from '../../../hooks/useMetricEvent' -import { getEnvironmentType } from '../../../../../app/scripts/lib/util' -import { ENVIRONMENT_TYPE_FULLSCREEN } from '../../../../../shared/constants/app' +} from '../../../selectors'; +import { useI18nContext } from '../../../hooks/useI18nContext'; +import { useMetricEvent } from '../../../hooks/useMetricEvent'; +import { getEnvironmentType } from '../../../../../app/scripts/lib/util'; +import { ENVIRONMENT_TYPE_FULLSCREEN } from '../../../../../shared/constants/app'; export default function AccountOptionsMenu({ anchorElement, onClose }) { - const t = useI18nContext() - const dispatch = useDispatch() - const history = useHistory() + const t = useI18nContext(); + const dispatch = useDispatch(); + const history = useHistory(); const openFullscreenEvent = useMetricEvent({ eventOpts: { category: 'Navigation', action: 'Account Options', name: 'Clicked Expand View', }, - }) + }); const viewAccountDetailsEvent = useMetricEvent({ eventOpts: { category: 'Navigation', action: 'Account Options', name: 'Viewed Account Details', }, - }) + }); const viewOnEtherscanEvent = useMetricEvent({ eventOpts: { category: 'Navigation', action: 'Account Options', name: 'Clicked View on Etherscan', }, - }) + }); const openConnectedSitesEvent = useMetricEvent({ eventOpts: { category: 'Navigation', action: 'Account Options', name: 'Opened Connected Sites', }, - }) + }); - const keyring = useSelector(getCurrentKeyring) - const network = useSelector(getCurrentNetwork) - const rpcPrefs = useSelector(getRpcPrefsForCurrentProvider) - const selectedIdentity = useSelector(getSelectedIdentity) + const keyring = useSelector(getCurrentKeyring); + const network = useSelector(getCurrentNetwork); + const rpcPrefs = useSelector(getRpcPrefsForCurrentProvider); + const selectedIdentity = useSelector(getSelectedIdentity); - const { address } = selectedIdentity - const isRemovable = keyring.type !== 'HD Key Tree' + const { address } = selectedIdentity; + const isRemovable = keyring.type !== 'HD Key Tree'; return ( { - openFullscreenEvent() - global.platform.openExtensionInBrowser() - onClose() + openFullscreenEvent(); + global.platform.openExtensionInBrowser(); + onClose(); }} iconClassName="fas fa-expand-alt" > @@ -80,9 +80,9 @@ export default function AccountOptionsMenu({ anchorElement, onClose }) { { - dispatch(showModal({ name: 'ACCOUNT_DETAILS' })) - viewAccountDetailsEvent() - onClose() + dispatch(showModal({ name: 'ACCOUNT_DETAILS' })); + viewAccountDetailsEvent(); + onClose(); }} iconClassName="fas fa-qrcode" > @@ -90,11 +90,11 @@ export default function AccountOptionsMenu({ anchorElement, onClose }) { { - viewOnEtherscanEvent() + viewOnEtherscanEvent(); global.platform.openTab({ url: getAccountLink(address, network, rpcPrefs), - }) - onClose() + }); + onClose(); }} subtitle={ rpcPrefs.blockExplorerUrl ? ( @@ -110,9 +110,9 @@ export default function AccountOptionsMenu({ anchorElement, onClose }) { { - openConnectedSitesEvent() - history.push(CONNECTED_ROUTE) - onClose() + openConnectedSitesEvent(); + history.push(CONNECTED_ROUTE); + onClose(); }} iconClassName="account-options-menu__connected-sites" > @@ -127,8 +127,8 @@ export default function AccountOptionsMenu({ anchorElement, onClose }) { name: 'CONFIRM_REMOVE_ACCOUNT', identity: selectedIdentity, }), - ) - onClose() + ); + onClose(); }} iconClassName="fas fa-trash-alt" > @@ -136,14 +136,14 @@ export default function AccountOptionsMenu({ anchorElement, onClose }) { ) : null} - ) + ); } AccountOptionsMenu.propTypes = { anchorElement: PropTypes.instanceOf(window.Element), onClose: PropTypes.func.isRequired, -} +}; AccountOptionsMenu.defaultProps = { anchorElement: undefined, -} +}; diff --git a/ui/app/components/app/menu-bar/index.js b/ui/app/components/app/menu-bar/index.js index 19db09e19..7bc7913f9 100644 --- a/ui/app/components/app/menu-bar/index.js +++ b/ui/app/components/app/menu-bar/index.js @@ -1 +1 @@ -export { default } from './menu-bar' +export { default } from './menu-bar'; diff --git a/ui/app/components/app/menu-bar/menu-bar.js b/ui/app/components/app/menu-bar/menu-bar.js index f6c70a43e..7b623c2c6 100644 --- a/ui/app/components/app/menu-bar/menu-bar.js +++ b/ui/app/components/app/menu-bar/menu-bar.js @@ -1,38 +1,38 @@ -import React, { useState } from 'react' -import extension from 'extensionizer' -import { useHistory } from 'react-router-dom' -import { useSelector } from 'react-redux' -import SelectedAccount from '../selected-account' -import ConnectedStatusIndicator from '../connected-status-indicator' -import { getEnvironmentType } from '../../../../../app/scripts/lib/util' -import { ENVIRONMENT_TYPE_POPUP } from '../../../../../shared/constants/app' -import { CONNECTED_ACCOUNTS_ROUTE } from '../../../helpers/constants/routes' -import { useI18nContext } from '../../../hooks/useI18nContext' -import { useMetricEvent } from '../../../hooks/useMetricEvent' -import { getOriginOfCurrentTab } from '../../../selectors' -import AccountOptionsMenu from './account-options-menu' +import React, { useState } from 'react'; +import extension from 'extensionizer'; +import { useHistory } from 'react-router-dom'; +import { useSelector } from 'react-redux'; +import SelectedAccount from '../selected-account'; +import ConnectedStatusIndicator from '../connected-status-indicator'; +import { getEnvironmentType } from '../../../../../app/scripts/lib/util'; +import { ENVIRONMENT_TYPE_POPUP } from '../../../../../shared/constants/app'; +import { CONNECTED_ACCOUNTS_ROUTE } from '../../../helpers/constants/routes'; +import { useI18nContext } from '../../../hooks/useI18nContext'; +import { useMetricEvent } from '../../../hooks/useMetricEvent'; +import { getOriginOfCurrentTab } from '../../../selectors'; +import AccountOptionsMenu from './account-options-menu'; export default function MenuBar() { - const t = useI18nContext() + const t = useI18nContext(); const openAccountOptionsEvent = useMetricEvent({ eventOpts: { category: 'Navigation', action: 'Home', name: 'Opened Account Options', }, - }) - const history = useHistory() + }); + const history = useHistory(); const [ accountOptionsButtonElement, setAccountOptionsButtonElement, - ] = useState(null) - const [accountOptionsMenuOpen, setAccountOptionsMenuOpen] = useState(false) - const origin = useSelector(getOriginOfCurrentTab) + ] = useState(null); + const [accountOptionsMenuOpen, setAccountOptionsMenuOpen] = useState(false); + const origin = useSelector(getOriginOfCurrentTab); const showStatus = getEnvironmentType() === ENVIRONMENT_TYPE_POPUP && origin && - origin !== extension.runtime.id + origin !== extension.runtime.id; return (
    @@ -50,8 +50,8 @@ export default function MenuBar() { ref={setAccountOptionsButtonElement} title={t('accountOptions')} onClick={() => { - openAccountOptionsEvent() - setAccountOptionsMenuOpen(true) + openAccountOptionsEvent(); + setAccountOptionsMenuOpen(true); }} /> @@ -62,5 +62,5 @@ export default function MenuBar() { /> )}
    - ) + ); } diff --git a/ui/app/components/app/menu-bar/tests/menu-bar.test.js b/ui/app/components/app/menu-bar/tests/menu-bar.test.js index 9df845409..4960ef627 100644 --- a/ui/app/components/app/menu-bar/tests/menu-bar.test.js +++ b/ui/app/components/app/menu-bar/tests/menu-bar.test.js @@ -1,9 +1,9 @@ -import assert from 'assert' -import React from 'react' -import { Provider } from 'react-redux' -import configureStore from 'redux-mock-store' -import { mountWithRouter } from '../../../../../../test/lib/render-helpers' -import MenuBar from '..' +import assert from 'assert'; +import React from 'react'; +import { Provider } from 'react-redux'; +import configureStore from 'redux-mock-store'; +import { mountWithRouter } from '../../../../../../test/lib/render-helpers'; +import MenuBar from '..'; const initState = { activeTab: {}, @@ -24,38 +24,38 @@ const initState = { ], frequentRpcListDetail: [], }, -} -const mockStore = configureStore() +}; +const mockStore = configureStore(); describe('MenuBar', function () { it('opens account detail menu when account options is clicked', function () { - const store = mockStore(initState) + const store = mockStore(initState); const wrapper = mountWithRouter( , - ) - assert.ok(!wrapper.exists('AccountOptionsMenu')) - const accountOptions = wrapper.find('.menu-bar__account-options') - accountOptions.simulate('click') - wrapper.update() - assert.ok(wrapper.exists('AccountOptionsMenu')) - }) + ); + assert.ok(!wrapper.exists('AccountOptionsMenu')); + const accountOptions = wrapper.find('.menu-bar__account-options'); + accountOptions.simulate('click'); + wrapper.update(); + assert.ok(wrapper.exists('AccountOptionsMenu')); + }); it('sets accountDetailsMenuOpen to false when closed', function () { - const store = mockStore(initState) + const store = mockStore(initState); const wrapper = mountWithRouter( , - ) - const accountOptions = wrapper.find('.menu-bar__account-options') - accountOptions.simulate('click') - wrapper.update() - assert.ok(wrapper.exists('AccountOptionsMenu')) - const accountDetailsMenu = wrapper.find('AccountOptionsMenu') - accountDetailsMenu.prop('onClose')() - wrapper.update() - assert.ok(!wrapper.exists('AccountOptionsMenu')) - }) -}) + ); + const accountOptions = wrapper.find('.menu-bar__account-options'); + accountOptions.simulate('click'); + wrapper.update(); + assert.ok(wrapper.exists('AccountOptionsMenu')); + const accountDetailsMenu = wrapper.find('AccountOptionsMenu'); + accountDetailsMenu.prop('onClose')(); + wrapper.update(); + assert.ok(!wrapper.exists('AccountOptionsMenu')); + }); +}); diff --git a/ui/app/components/app/menu-droppo.js b/ui/app/components/app/menu-droppo.js index d9895ec61..6888d5d68 100644 --- a/ui/app/components/app/menu-droppo.js +++ b/ui/app/components/app/menu-droppo.js @@ -1,7 +1,7 @@ -import PropTypes from 'prop-types' -import React, { Component } from 'react' -import { findDOMNode } from 'react-dom' -import ReactCSSTransitionGroup from 'react-transition-group/CSSTransitionGroup' +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { findDOMNode } from 'react-dom'; +import ReactCSSTransitionGroup from 'react-transition-group/CSSTransitionGroup'; export default class MenuDroppoComponent extends Component { static propTypes = { @@ -14,27 +14,27 @@ export default class MenuDroppoComponent extends Component { style: PropTypes.object.isRequired, useCssTransition: PropTypes.bool, speed: PropTypes.string, - } + }; renderPrimary() { - const { isOpen } = this.props + const { isOpen } = this.props; if (!isOpen) { - return null + return null; } - const innerStyle = this.props.innerStyle || {} + const innerStyle = this.props.innerStyle || {}; return (
    {this.props.children}
    - ) + ); } globalClickOccurred = (event) => { - const { target } = event + const { target } = event; // eslint-disable-next-line react/no-find-dom-node - const container = findDOMNode(this) + const container = findDOMNode(this); if ( this.props.isOpen && @@ -42,36 +42,36 @@ export default class MenuDroppoComponent extends Component { !isDescendant(this.container, event.target) && this.props.onClickOutside ) { - this.props.onClickOutside(event) + this.props.onClickOutside(event); } - } + }; componentDidMount() { if (this && document.body) { - document.body.addEventListener('click', this.globalClickOccurred) + document.body.addEventListener('click', this.globalClickOccurred); // eslint-disable-next-line react/no-find-dom-node - const container = findDOMNode(this) - this.container = container + const container = findDOMNode(this); + this.container = container; } } componentWillUnmount() { if (this && document.body) { - document.body.removeEventListener('click', this.globalClickOccurred) + document.body.removeEventListener('click', this.globalClickOccurred); } } render() { - const { containerClassName = '', style } = this.props - const speed = this.props.speed || '300ms' - const { useCssTransition } = this.props - const zIndex = 'zIndex' in this.props ? this.props.zIndex : 0 + const { containerClassName = '', style } = this.props; + const speed = this.props.speed || '300ms'; + const { useCssTransition } = this.props; + const zIndex = 'zIndex' in this.props ? this.props.zIndex : 0; const baseStyle = { position: 'fixed', ...style, zIndex, - } + }; return (
    - ) + ); } } function isDescendant(parent, child) { - let node = child.parentNode + let node = child.parentNode; while (node !== null) { if (node === parent) { - return true + return true; } - node = node.parentNode + node = node.parentNode; } - return false + return false; } diff --git a/ui/app/components/app/metamask-template-renderer/index.js b/ui/app/components/app/metamask-template-renderer/index.js index b8028d2ce..ed838c0c4 100644 --- a/ui/app/components/app/metamask-template-renderer/index.js +++ b/ui/app/components/app/metamask-template-renderer/index.js @@ -1 +1 @@ -export { default } from './metamask-template-renderer' +export { default } from './metamask-template-renderer'; diff --git a/ui/app/components/app/metamask-template-renderer/metamask-template-renderer.js b/ui/app/components/app/metamask-template-renderer/metamask-template-renderer.js index a4af96533..30e4b6b30 100644 --- a/ui/app/components/app/metamask-template-renderer/metamask-template-renderer.js +++ b/ui/app/components/app/metamask-template-renderer/metamask-template-renderer.js @@ -1,33 +1,33 @@ -import React, { memo } from 'react' -import PropTypes from 'prop-types' -import { isEqual } from 'lodash' -import { safeComponentList } from './safe-component-list' +import React, { memo } from 'react'; +import PropTypes from 'prop-types'; +import { isEqual } from 'lodash'; +import { safeComponentList } from './safe-component-list'; function getElement(section) { - const { element } = section - const Element = safeComponentList[element] + const { element } = section; + const Element = safeComponentList[element]; if (!Element) { throw new Error( `${element} is not in the safe component list for MetaMask template renderer`, - ) + ); } - return Element + return Element; } const MetaMaskTemplateRenderer = ({ sections }) => { if (!sections) { // If sections is null eject early by returning null - return null + return null; } else if (typeof sections === 'string') { // React can render strings directly, so return the string - return sections + return sections; } else if ( sections && typeof sections === 'object' && !Array.isArray(sections) ) { // If dealing with a single entry, then render a single object without key - const Element = getElement(sections) + const Element = getElement(sections); return ( {typeof sections.children === 'object' ? ( @@ -36,7 +36,7 @@ const MetaMaskTemplateRenderer = ({ sections }) => { sections?.children )} - ) + ); } // The last case is dealing with an array of objects @@ -45,7 +45,7 @@ const MetaMaskTemplateRenderer = ({ sections }) => { {sections.reduce((allChildren, child) => { if (typeof child === 'string') { // React can render strings directly, so push them into the accumulator - allChildren.push(child) + allChildren.push(child); } else { // If the entry in array is not a string, then it must be a Section. // Sections are handled by the main function, but must @@ -53,35 +53,35 @@ const MetaMaskTemplateRenderer = ({ sections }) => { if (!child.key) { throw new Error( 'When using array syntax in MetaMask Template Language, you must specify a key for each child of the array', - ) + ); } if (typeof child?.children === 'object') { // If this child has its own children, check if children is an // object, and in that case use recursion to render. allChildren.push( , - ) + ); } else { // Otherwise render the element. - const Element = getElement(child) + const Element = getElement(child); allChildren.push( {child?.children} , - ) + ); } } - return allChildren + return allChildren; }, [])} - ) -} + ); +}; const SectionShape = { props: PropTypes.object, element: PropTypes.oneOf(Object.keys(safeComponentList)).isRequired, key: PropTypes.string, -} +}; const ValidChildren = PropTypes.oneOfType([ PropTypes.string, @@ -89,14 +89,14 @@ const ValidChildren = PropTypes.oneOfType([ PropTypes.arrayOf( PropTypes.oneOfType([PropTypes.shape(SectionShape), PropTypes.string]), ), -]) +]); -SectionShape.children = ValidChildren +SectionShape.children = ValidChildren; MetaMaskTemplateRenderer.propTypes = { sections: ValidChildren, -} +}; export default memo(MetaMaskTemplateRenderer, (prevProps, nextProps) => { - return isEqual(prevProps.sections, nextProps.sections) -}) + return isEqual(prevProps.sections, nextProps.sections); +}); diff --git a/ui/app/components/app/metamask-template-renderer/metamask-template-renderer.stories.js b/ui/app/components/app/metamask-template-renderer/metamask-template-renderer.stories.js index b0c4dc1a5..5ad8aa4ee 100644 --- a/ui/app/components/app/metamask-template-renderer/metamask-template-renderer.stories.js +++ b/ui/app/components/app/metamask-template-renderer/metamask-template-renderer.stories.js @@ -1,11 +1,11 @@ -import React from 'react' -import { object } from '@storybook/addon-knobs' -import { COLORS, TYPOGRAPHY } from '../../../helpers/constants/design-system' -import MetaMaskTemplateRenderer from '.' +import React from 'react'; +import { object } from '@storybook/addon-knobs'; +import { COLORS, TYPOGRAPHY } from '../../../helpers/constants/design-system'; +import MetaMaskTemplateRenderer from '.'; export default { title: 'MetaMask Template Renderer', -} +}; const SECTIONS = { element: 'Box', @@ -83,10 +83,10 @@ const SECTIONS = { props: { justifyContent: 'space-between', padding: [0, 4] }, }, ], -} +}; export const metaMaskTemplateRenderer = () => ( -) +); export const withInvalidElement = () => ( ( }, ])} /> -) +); diff --git a/ui/app/components/app/metamask-template-renderer/safe-component-list.js b/ui/app/components/app/metamask-template-renderer/safe-component-list.js index fea24c256..9e8c22991 100644 --- a/ui/app/components/app/metamask-template-renderer/safe-component-list.js +++ b/ui/app/components/app/metamask-template-renderer/safe-component-list.js @@ -1,10 +1,10 @@ -import Button from '../../ui/button' -import Chip from '../../ui/chip' -import DefinitionList from '../../ui/definition-list' -import TruncatedDefinitionList from '../../ui/truncated-definition-list' -import Popover from '../../ui/popover' -import Typography from '../../ui/typography' -import Box from '../../ui/box' +import Button from '../../ui/button'; +import Chip from '../../ui/chip'; +import DefinitionList from '../../ui/definition-list'; +import TruncatedDefinitionList from '../../ui/truncated-definition-list'; +import Popover from '../../ui/popover'; +import Typography from '../../ui/typography'; +import Box from '../../ui/box'; export const safeComponentList = { b: 'b', @@ -18,4 +18,4 @@ export const safeComponentList = { Button, Popover, Box, -} +}; diff --git a/ui/app/components/app/modal/index.js b/ui/app/components/app/modal/index.js index 58309abbe..18c5905f4 100644 --- a/ui/app/components/app/modal/index.js +++ b/ui/app/components/app/modal/index.js @@ -1,2 +1,2 @@ -export { default } from './modal.component' -export { default as ModalContent } from './modal-content' +export { default } from './modal.component'; +export { default as ModalContent } from './modal-content'; diff --git a/ui/app/components/app/modal/modal-content/index.js b/ui/app/components/app/modal/modal-content/index.js index 733cfb3b8..655fbb797 100644 --- a/ui/app/components/app/modal/modal-content/index.js +++ b/ui/app/components/app/modal/modal-content/index.js @@ -1 +1 @@ -export { default } from './modal-content.component' +export { default } from './modal-content.component'; diff --git a/ui/app/components/app/modal/modal-content/modal-content.component.js b/ui/app/components/app/modal/modal-content/modal-content.component.js index 8f011e18f..99f57bc03 100644 --- a/ui/app/components/app/modal/modal-content/modal-content.component.js +++ b/ui/app/components/app/modal/modal-content/modal-content.component.js @@ -1,14 +1,14 @@ -import React, { PureComponent } from 'react' -import PropTypes from 'prop-types' +import React, { PureComponent } from 'react'; +import PropTypes from 'prop-types'; export default class ModalContent extends PureComponent { static propTypes = { title: PropTypes.string, description: PropTypes.string, - } + }; render() { - const { title, description } = this.props + const { title, description } = this.props; return (
    @@ -17,6 +17,6 @@ export default class ModalContent extends PureComponent {
    {description}
    )}
    - ) + ); } } diff --git a/ui/app/components/app/modal/modal-content/tests/modal-content.component.test.js b/ui/app/components/app/modal/modal-content/tests/modal-content.component.test.js index 8056563f6..485b2f951 100644 --- a/ui/app/components/app/modal/modal-content/tests/modal-content.component.test.js +++ b/ui/app/components/app/modal/modal-content/tests/modal-content.component.test.js @@ -1,45 +1,45 @@ -import assert from 'assert' -import React from 'react' -import { shallow } from 'enzyme' -import ModalContent from '../modal-content.component' +import assert from 'assert'; +import React from 'react'; +import { shallow } from 'enzyme'; +import ModalContent from '../modal-content.component'; describe('ModalContent Component', function () { it('should render a title', function () { - const wrapper = shallow() + const wrapper = shallow(); - assert.strictEqual(wrapper.find('.modal-content__title').length, 1) + assert.strictEqual(wrapper.find('.modal-content__title').length, 1); assert.strictEqual( wrapper.find('.modal-content__title').text(), 'Modal Title', - ) - assert.strictEqual(wrapper.find('.modal-content__description').length, 0) - }) + ); + assert.strictEqual(wrapper.find('.modal-content__description').length, 0); + }); it('should render a description', function () { - const wrapper = shallow() + const wrapper = shallow(); - assert.strictEqual(wrapper.find('.modal-content__title').length, 0) - assert.strictEqual(wrapper.find('.modal-content__description').length, 1) + assert.strictEqual(wrapper.find('.modal-content__title').length, 0); + assert.strictEqual(wrapper.find('.modal-content__description').length, 1); assert.strictEqual( wrapper.find('.modal-content__description').text(), 'Modal Description', - ) - }) + ); + }); it('should render both a title and a description', function () { const wrapper = shallow( , - ) + ); - assert.strictEqual(wrapper.find('.modal-content__title').length, 1) + assert.strictEqual(wrapper.find('.modal-content__title').length, 1); assert.strictEqual( wrapper.find('.modal-content__title').text(), 'Modal Title', - ) - assert.strictEqual(wrapper.find('.modal-content__description').length, 1) + ); + assert.strictEqual(wrapper.find('.modal-content__description').length, 1); assert.strictEqual( wrapper.find('.modal-content__description').text(), 'Modal Description', - ) - }) -}) + ); + }); +}); diff --git a/ui/app/components/app/modal/modal.component.js b/ui/app/components/app/modal/modal.component.js index 57137270c..89b814610 100644 --- a/ui/app/components/app/modal/modal.component.js +++ b/ui/app/components/app/modal/modal.component.js @@ -1,7 +1,7 @@ -import React, { PureComponent } from 'react' -import PropTypes from 'prop-types' -import classnames from 'classnames' -import Button from '../../ui/button' +import React, { PureComponent } from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; +import Button from '../../ui/button'; export default class Modal extends PureComponent { static propTypes = { @@ -21,12 +21,12 @@ export default class Modal extends PureComponent { onCancel: PropTypes.func, cancelType: PropTypes.string, cancelText: PropTypes.string, - } + }; static defaultProps = { submitType: 'secondary', cancelType: 'default', - } + }; render() { const { @@ -43,7 +43,7 @@ export default class Modal extends PureComponent { contentClass, containerClass, hideFooter, - } = this.props + } = this.props; return (
    @@ -78,6 +78,6 @@ export default class Modal extends PureComponent {
    )}
    - ) + ); } } diff --git a/ui/app/components/app/modal/tests/modal.component.test.js b/ui/app/components/app/modal/tests/modal.component.test.js index a0ad195ae..8af9d394b 100644 --- a/ui/app/components/app/modal/tests/modal.component.test.js +++ b/ui/app/components/app/modal/tests/modal.component.test.js @@ -1,23 +1,23 @@ -import assert from 'assert' -import React from 'react' -import { mount, shallow } from 'enzyme' -import sinon from 'sinon' -import Modal from '../modal.component' -import Button from '../../../ui/button' +import assert from 'assert'; +import React from 'react'; +import { mount, shallow } from 'enzyme'; +import sinon from 'sinon'; +import Modal from '../modal.component'; +import Button from '../../../ui/button'; describe('Modal Component', function () { it('should render a modal with a submit button', function () { - const wrapper = shallow() + const wrapper = shallow(); - assert.strictEqual(wrapper.find('.modal-container').length, 1) - const buttons = wrapper.find(Button) - assert.strictEqual(buttons.length, 1) - assert.strictEqual(buttons.at(0).props().type, 'secondary') - }) + assert.strictEqual(wrapper.find('.modal-container').length, 1); + const buttons = wrapper.find(Button); + assert.strictEqual(buttons.length, 1); + assert.strictEqual(buttons.at(0).props().type, 'secondary'); + }); it('should render a modal with a cancel and a submit button', function () { - const handleCancel = sinon.spy() - const handleSubmit = sinon.spy() + const handleCancel = sinon.spy(); + const handleSubmit = sinon.spy(); const wrapper = shallow( , - ) + ); - const buttons = wrapper.find(Button) - assert.strictEqual(buttons.length, 2) - const cancelButton = buttons.at(0) - const submitButton = buttons.at(1) + const buttons = wrapper.find(Button); + assert.strictEqual(buttons.length, 2); + const cancelButton = buttons.at(0); + const submitButton = buttons.at(1); - assert.strictEqual(cancelButton.props().type, 'default') - assert.strictEqual(cancelButton.props().children, 'Cancel') - assert.strictEqual(handleCancel.callCount, 0) - cancelButton.simulate('click') - assert.strictEqual(handleCancel.callCount, 1) + assert.strictEqual(cancelButton.props().type, 'default'); + assert.strictEqual(cancelButton.props().children, 'Cancel'); + assert.strictEqual(handleCancel.callCount, 0); + cancelButton.simulate('click'); + assert.strictEqual(handleCancel.callCount, 1); - assert.strictEqual(submitButton.props().type, 'secondary') - assert.strictEqual(submitButton.props().children, 'Submit') - assert.strictEqual(handleSubmit.callCount, 0) - submitButton.simulate('click') - assert.strictEqual(handleSubmit.callCount, 1) - }) + assert.strictEqual(submitButton.props().type, 'secondary'); + assert.strictEqual(submitButton.props().children, 'Submit'); + assert.strictEqual(handleSubmit.callCount, 0); + submitButton.simulate('click'); + assert.strictEqual(handleSubmit.callCount, 1); + }); it('should render a modal with different button types', function () { const wrapper = shallow( @@ -55,13 +55,13 @@ describe('Modal Component', function () { submitText="Submit" submitType="confirm" />, - ) + ); - const buttons = wrapper.find(Button) - assert.strictEqual(buttons.length, 2) - assert.strictEqual(buttons.at(0).props().type, 'secondary') - assert.strictEqual(buttons.at(1).props().type, 'confirm') - }) + const buttons = wrapper.find(Button); + assert.strictEqual(buttons.length, 2); + assert.strictEqual(buttons.at(0).props().type, 'secondary'); + assert.strictEqual(buttons.at(1).props().type, 'confirm'); + }); it('should render a modal with children', function () { const wrapper = shallow( @@ -73,14 +73,14 @@ describe('Modal Component', function () { >
    , - ) + ); - assert.ok(wrapper.find('.test-class')) - }) + assert.ok(wrapper.find('.test-class')); + }); it('should render a modal with a header', function () { - const handleCancel = sinon.spy() - const handleSubmit = sinon.spy() + const handleCancel = sinon.spy(); + const handleSubmit = sinon.spy(); const wrapper = shallow( , - ) + ); - assert.ok(wrapper.find('.modal-container__header')) + assert.ok(wrapper.find('.modal-container__header')); assert.strictEqual( wrapper.find('.modal-container__header-text').text(), 'My Header', - ) - assert.strictEqual(handleCancel.callCount, 0) - assert.strictEqual(handleSubmit.callCount, 0) - wrapper.find('.modal-container__header-close').simulate('click') - assert.strictEqual(handleCancel.callCount, 1) - assert.strictEqual(handleSubmit.callCount, 0) - }) + ); + assert.strictEqual(handleCancel.callCount, 0); + assert.strictEqual(handleSubmit.callCount, 0); + wrapper.find('.modal-container__header-close').simulate('click'); + assert.strictEqual(handleCancel.callCount, 1); + assert.strictEqual(handleSubmit.callCount, 0); + }); it('should disable the submit button if submitDisabled is true', function () { - const handleCancel = sinon.spy() - const handleSubmit = sinon.spy() + const handleCancel = sinon.spy(); + const handleSubmit = sinon.spy(); const wrapper = mount( , - ) + ); - const buttons = wrapper.find(Button) - assert.strictEqual(buttons.length, 2) - const cancelButton = buttons.at(0) - const submitButton = buttons.at(1) + const buttons = wrapper.find(Button); + assert.strictEqual(buttons.length, 2); + const cancelButton = buttons.at(0); + const submitButton = buttons.at(1); - assert.strictEqual(handleCancel.callCount, 0) - cancelButton.simulate('click') - assert.strictEqual(handleCancel.callCount, 1) + assert.strictEqual(handleCancel.callCount, 0); + cancelButton.simulate('click'); + assert.strictEqual(handleCancel.callCount, 1); - assert.strictEqual(submitButton.props().disabled, true) - assert.strictEqual(handleSubmit.callCount, 0) - submitButton.simulate('click') - assert.strictEqual(handleSubmit.callCount, 0) - }) -}) + assert.strictEqual(submitButton.props().disabled, true); + assert.strictEqual(handleSubmit.callCount, 0); + submitButton.simulate('click'); + assert.strictEqual(handleSubmit.callCount, 0); + }); +}); diff --git a/ui/app/components/app/modals/account-details-modal/account-details-modal.component.js b/ui/app/components/app/modals/account-details-modal/account-details-modal.component.js index f3b6d5586..fb01b6e41 100644 --- a/ui/app/components/app/modals/account-details-modal/account-details-modal.component.js +++ b/ui/app/components/app/modals/account-details-modal/account-details-modal.component.js @@ -1,10 +1,10 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import AccountModalContainer from '../account-modal-container' -import getAccountLink from '../../../../../lib/account-link' -import QrView from '../../../ui/qr-code' -import EditableLabel from '../../../ui/editable-label' -import Button from '../../../ui/button' +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import AccountModalContainer from '../account-modal-container'; +import getAccountLink from '../../../../../lib/account-link'; +import QrView from '../../../ui/qr-code'; +import EditableLabel from '../../../ui/editable-label'; +import Button from '../../../ui/button'; export default class AccountDetailsModal extends Component { static propTypes = { @@ -14,11 +14,11 @@ export default class AccountDetailsModal extends Component { setAccountLabel: PropTypes.func, keyrings: PropTypes.array, rpcPrefs: PropTypes.object, - } + }; static contextTypes = { t: PropTypes.func, - } + }; render() { const { @@ -28,17 +28,17 @@ export default class AccountDetailsModal extends Component { setAccountLabel, keyrings, rpcPrefs, - } = this.props - const { name, address } = selectedIdentity + } = this.props; + const { name, address } = selectedIdentity; const keyring = keyrings.find((kr) => { - return kr.accounts.includes(address) - }) + return kr.accounts.includes(address); + }); - let exportPrivateKeyFeatureEnabled = true + let exportPrivateKeyFeatureEnabled = true; // This feature is disabled for hardware wallets if (keyring?.type?.search('Hardware') !== -1) { - exportPrivateKeyFeatureEnabled = false + exportPrivateKeyFeatureEnabled = false; } return ( @@ -63,7 +63,7 @@ export default class AccountDetailsModal extends Component { onClick={() => { global.platform.openTab({ url: getAccountLink(address, network, rpcPrefs), - }) + }); }} > {rpcPrefs.blockExplorerUrl @@ -83,6 +83,6 @@ export default class AccountDetailsModal extends Component { ) : null} - ) + ); } } diff --git a/ui/app/components/app/modals/account-details-modal/account-details-modal.container.js b/ui/app/components/app/modals/account-details-modal/account-details-modal.container.js index b29e99c54..8267e1a4b 100644 --- a/ui/app/components/app/modals/account-details-modal/account-details-modal.container.js +++ b/ui/app/components/app/modals/account-details-modal/account-details-modal.container.js @@ -1,10 +1,10 @@ -import { connect } from 'react-redux' -import { showModal, setAccountLabel } from '../../../../store/actions' +import { connect } from 'react-redux'; +import { showModal, setAccountLabel } from '../../../../store/actions'; import { getSelectedIdentity, getRpcPrefsForCurrentProvider, -} from '../../../../selectors' -import AccountDetailsModal from './account-details-modal.component' +} from '../../../../selectors'; +import AccountDetailsModal from './account-details-modal.component'; const mapStateToProps = (state) => { return { @@ -12,8 +12,8 @@ const mapStateToProps = (state) => { selectedIdentity: getSelectedIdentity(state), keyrings: state.metamask.keyrings, rpcPrefs: getRpcPrefsForCurrentProvider(state), - } -} + }; +}; const mapDispatchToProps = (dispatch) => { return { @@ -21,7 +21,10 @@ const mapDispatchToProps = (dispatch) => { dispatch(showModal({ name: 'EXPORT_PRIVATE_KEY' })), setAccountLabel: (address, label) => dispatch(setAccountLabel(address, label)), - } -} + }; +}; -export default connect(mapStateToProps, mapDispatchToProps)(AccountDetailsModal) +export default connect( + mapStateToProps, + mapDispatchToProps, +)(AccountDetailsModal); diff --git a/ui/app/components/app/modals/account-details-modal/index.js b/ui/app/components/app/modals/account-details-modal/index.js index 433f4d170..ccbfa1d1d 100644 --- a/ui/app/components/app/modals/account-details-modal/index.js +++ b/ui/app/components/app/modals/account-details-modal/index.js @@ -1 +1 @@ -export { default } from './account-details-modal.container' +export { default } from './account-details-modal.container'; diff --git a/ui/app/components/app/modals/account-modal-container/account-modal-container.component.js b/ui/app/components/app/modals/account-modal-container/account-modal-container.component.js index 2ad338b23..db93a2dc5 100644 --- a/ui/app/components/app/modals/account-modal-container/account-modal-container.component.js +++ b/ui/app/components/app/modals/account-modal-container/account-modal-container.component.js @@ -1,7 +1,7 @@ -import PropTypes from 'prop-types' -import React from 'react' -import classnames from 'classnames' -import Identicon from '../../../ui/identicon' +import PropTypes from 'prop-types'; +import React from 'react'; +import classnames from 'classnames'; +import Identicon from '../../../ui/identicon'; export default function AccountModalContainer(props, context) { const { @@ -11,7 +11,7 @@ export default function AccountModalContainer(props, context) { backButtonAction, hideModal, children, - } = props + } = props; return (
    - ) + ); } AccountModalContainer.contextTypes = { t: PropTypes.func, -} +}; AccountModalContainer.defaultProps = { showBackButton: false, children: null, backButtonAction: undefined, -} +}; AccountModalContainer.propTypes = { className: PropTypes.string, @@ -54,4 +54,4 @@ AccountModalContainer.propTypes = { backButtonAction: PropTypes.func, hideModal: PropTypes.func.isRequired, children: PropTypes.node, -} +}; diff --git a/ui/app/components/app/modals/account-modal-container/account-modal-container.container.js b/ui/app/components/app/modals/account-modal-container/account-modal-container.container.js index 2ad9b32ac..0fb64bf1f 100644 --- a/ui/app/components/app/modals/account-modal-container/account-modal-container.container.js +++ b/ui/app/components/app/modals/account-modal-container/account-modal-container.container.js @@ -1,23 +1,23 @@ -import { connect } from 'react-redux' -import { hideModal } from '../../../../store/actions' -import { getSelectedIdentity } from '../../../../selectors' -import AccountModalContainer from './account-modal-container.component' +import { connect } from 'react-redux'; +import { hideModal } from '../../../../store/actions'; +import { getSelectedIdentity } from '../../../../selectors'; +import AccountModalContainer from './account-modal-container.component'; function mapStateToProps(state, ownProps) { return { selectedIdentity: ownProps.selectedIdentity || getSelectedIdentity(state), - } + }; } function mapDispatchToProps(dispatch) { return { hideModal: () => { - dispatch(hideModal()) + dispatch(hideModal()); }, - } + }; } export default connect( mapStateToProps, mapDispatchToProps, -)(AccountModalContainer) +)(AccountModalContainer); diff --git a/ui/app/components/app/modals/account-modal-container/index.js b/ui/app/components/app/modals/account-modal-container/index.js index e37684b96..b79fcc79f 100644 --- a/ui/app/components/app/modals/account-modal-container/index.js +++ b/ui/app/components/app/modals/account-modal-container/index.js @@ -1 +1 @@ -export { default } from './account-modal-container.container' +export { default } from './account-modal-container.container'; diff --git a/ui/app/components/app/modals/add-to-addressbook-modal/add-to-addressbook-modal.component.js b/ui/app/components/app/modals/add-to-addressbook-modal/add-to-addressbook-modal.component.js index 03e8e0155..70661e3c7 100644 --- a/ui/app/components/app/modals/add-to-addressbook-modal/add-to-addressbook-modal.component.js +++ b/ui/app/components/app/modals/add-to-addressbook-modal/add-to-addressbook-modal.component.js @@ -1,42 +1,42 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import Button from '../../../ui/button/button.component' +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import Button from '../../../ui/button/button.component'; export default class AddToAddressBookModal extends Component { static contextTypes = { t: PropTypes.func, - } + }; static propTypes = { hideModal: PropTypes.func.isRequired, addToAddressBook: PropTypes.func.isRequired, recipient: PropTypes.string.isRequired, - } + }; state = { alias: '', - } + }; onSave = async () => { - const { recipient, addToAddressBook, hideModal } = this.props - await addToAddressBook(recipient, this.state.alias) - hideModal() - } + const { recipient, addToAddressBook, hideModal } = this.props; + await addToAddressBook(recipient, this.state.alias); + hideModal(); + }; onChange = (e) => { this.setState({ alias: e.target.value, - }) - } + }); + }; onKeyPress = async (e) => { if (e.key === 'Enter' && this.state.alias) { - this.onSave() + this.onSave(); } - } + }; render() { - const { t } = this.context + const { t } = this.context; return (
    @@ -70,6 +70,6 @@ export default class AddToAddressBookModal extends Component {
    - ) + ); } } diff --git a/ui/app/components/app/modals/add-to-addressbook-modal/add-to-addressbook-modal.container.js b/ui/app/components/app/modals/add-to-addressbook-modal/add-to-addressbook-modal.container.js index 4d041f2a9..8d220a02a 100644 --- a/ui/app/components/app/modals/add-to-addressbook-modal/add-to-addressbook-modal.container.js +++ b/ui/app/components/app/modals/add-to-addressbook-modal/add-to-addressbook-modal.container.js @@ -1,11 +1,11 @@ -import { connect } from 'react-redux' -import * as actions from '../../../../store/actions' -import AddToAddressBookModal from './add-to-addressbook-modal.component' +import { connect } from 'react-redux'; +import * as actions from '../../../../store/actions'; +import AddToAddressBookModal from './add-to-addressbook-modal.component'; function mapStateToProps(state) { return { ...(state.appState.modal.modalState.props || {}), - } + }; } function mapDispatchToProps(dispatch) { @@ -13,10 +13,10 @@ function mapDispatchToProps(dispatch) { hideModal: () => dispatch(actions.hideModal()), addToAddressBook: (recipient, nickname) => dispatch(actions.addToAddressBook(recipient, nickname)), - } + }; } export default connect( mapStateToProps, mapDispatchToProps, -)(AddToAddressBookModal) +)(AddToAddressBookModal); diff --git a/ui/app/components/app/modals/add-to-addressbook-modal/index.js b/ui/app/components/app/modals/add-to-addressbook-modal/index.js index 9ed4f018f..d35d21b10 100644 --- a/ui/app/components/app/modals/add-to-addressbook-modal/index.js +++ b/ui/app/components/app/modals/add-to-addressbook-modal/index.js @@ -1 +1 @@ -export { default } from './add-to-addressbook-modal.container' +export { default } from './add-to-addressbook-modal.container'; diff --git a/ui/app/components/app/modals/cancel-transaction/cancel-transaction-gas-fee/cancel-transaction-gas-fee.component.js b/ui/app/components/app/modals/cancel-transaction/cancel-transaction-gas-fee/cancel-transaction-gas-fee.component.js index ebcbe0d60..02583b029 100644 --- a/ui/app/components/app/modals/cancel-transaction/cancel-transaction-gas-fee/cancel-transaction-gas-fee.component.js +++ b/ui/app/components/app/modals/cancel-transaction/cancel-transaction-gas-fee/cancel-transaction-gas-fee.component.js @@ -1,15 +1,15 @@ -import React, { PureComponent } from 'react' -import PropTypes from 'prop-types' -import UserPreferencedCurrencyDisplay from '../../../user-preferenced-currency-display' -import { PRIMARY, SECONDARY } from '../../../../../helpers/constants/common' +import React, { PureComponent } from 'react'; +import PropTypes from 'prop-types'; +import UserPreferencedCurrencyDisplay from '../../../user-preferenced-currency-display'; +import { PRIMARY, SECONDARY } from '../../../../../helpers/constants/common'; export default class CancelTransaction extends PureComponent { static propTypes = { value: PropTypes.string, - } + }; render() { - const { value } = this.props + const { value } = this.props; return (
    @@ -24,6 +24,6 @@ export default class CancelTransaction extends PureComponent { type={SECONDARY} />
    - ) + ); } } diff --git a/ui/app/components/app/modals/cancel-transaction/cancel-transaction-gas-fee/index.js b/ui/app/components/app/modals/cancel-transaction/cancel-transaction-gas-fee/index.js index 1a9ae2e07..f063456bf 100644 --- a/ui/app/components/app/modals/cancel-transaction/cancel-transaction-gas-fee/index.js +++ b/ui/app/components/app/modals/cancel-transaction/cancel-transaction-gas-fee/index.js @@ -1 +1 @@ -export { default } from './cancel-transaction-gas-fee.component' +export { default } from './cancel-transaction-gas-fee.component'; diff --git a/ui/app/components/app/modals/cancel-transaction/cancel-transaction-gas-fee/tests/cancel-transaction-gas-fee.component.test.js b/ui/app/components/app/modals/cancel-transaction/cancel-transaction-gas-fee/tests/cancel-transaction-gas-fee.component.test.js index c10971110..5d4ca39e6 100644 --- a/ui/app/components/app/modals/cancel-transaction/cancel-transaction-gas-fee/tests/cancel-transaction-gas-fee.component.test.js +++ b/ui/app/components/app/modals/cancel-transaction/cancel-transaction-gas-fee/tests/cancel-transaction-gas-fee.component.test.js @@ -1,28 +1,28 @@ -import assert from 'assert' -import React from 'react' -import { shallow } from 'enzyme' -import CancelTransactionGasFee from '../cancel-transaction-gas-fee.component' -import UserPreferencedCurrencyDisplay from '../../../../user-preferenced-currency-display' +import assert from 'assert'; +import React from 'react'; +import { shallow } from 'enzyme'; +import CancelTransactionGasFee from '../cancel-transaction-gas-fee.component'; +import UserPreferencedCurrencyDisplay from '../../../../user-preferenced-currency-display'; describe('CancelTransactionGasFee Component', function () { it('should render', function () { - const wrapper = shallow() + const wrapper = shallow(); - assert.ok(wrapper) - assert.strictEqual(wrapper.find(UserPreferencedCurrencyDisplay).length, 2) - const ethDisplay = wrapper.find(UserPreferencedCurrencyDisplay).at(0) - const fiatDisplay = wrapper.find(UserPreferencedCurrencyDisplay).at(1) + assert.ok(wrapper); + assert.strictEqual(wrapper.find(UserPreferencedCurrencyDisplay).length, 2); + const ethDisplay = wrapper.find(UserPreferencedCurrencyDisplay).at(0); + const fiatDisplay = wrapper.find(UserPreferencedCurrencyDisplay).at(1); - assert.strictEqual(ethDisplay.props().value, '0x3b9aca00') + assert.strictEqual(ethDisplay.props().value, '0x3b9aca00'); assert.strictEqual( ethDisplay.props().className, 'cancel-transaction-gas-fee__eth', - ) + ); - assert.strictEqual(fiatDisplay.props().value, '0x3b9aca00') + assert.strictEqual(fiatDisplay.props().value, '0x3b9aca00'); assert.strictEqual( fiatDisplay.props().className, 'cancel-transaction-gas-fee__fiat', - ) - }) -}) + ); + }); +}); diff --git a/ui/app/components/app/modals/cancel-transaction/cancel-transaction.component.js b/ui/app/components/app/modals/cancel-transaction/cancel-transaction.component.js index 7bddafc34..d45ba6198 100644 --- a/ui/app/components/app/modals/cancel-transaction/cancel-transaction.component.js +++ b/ui/app/components/app/modals/cancel-transaction/cancel-transaction.component.js @@ -1,13 +1,13 @@ -import React, { PureComponent } from 'react' -import PropTypes from 'prop-types' -import Modal from '../../modal' -import { TRANSACTION_STATUSES } from '../../../../../../shared/constants/transaction' -import CancelTransactionGasFee from './cancel-transaction-gas-fee' +import React, { PureComponent } from 'react'; +import PropTypes from 'prop-types'; +import Modal from '../../modal'; +import { TRANSACTION_STATUSES } from '../../../../../../shared/constants/transaction'; +import CancelTransactionGasFee from './cancel-transaction-gas-fee'; export default class CancelTransaction extends PureComponent { static contextTypes = { t: PropTypes.func, - } + }; static propTypes = { createCancelTransaction: PropTypes.func, @@ -15,37 +15,37 @@ export default class CancelTransaction extends PureComponent { showTransactionConfirmedModal: PropTypes.func, transactionStatus: PropTypes.string, newGasFee: PropTypes.string, - } + }; state = { busy: false, - } + }; componentDidUpdate() { - const { transactionStatus, showTransactionConfirmedModal } = this.props + const { transactionStatus, showTransactionConfirmedModal } = this.props; if (transactionStatus !== TRANSACTION_STATUSES.SUBMITTED) { - showTransactionConfirmedModal() + showTransactionConfirmedModal(); } } handleSubmit = async () => { - const { createCancelTransaction, hideModal } = this.props + const { createCancelTransaction, hideModal } = this.props; - this.setState({ busy: true }) + this.setState({ busy: true }); - await createCancelTransaction() - this.setState({ busy: false }, () => hideModal()) - } + await createCancelTransaction(); + this.setState({ busy: false }, () => hideModal()); + }; handleCancel = () => { - this.props.hideModal() - } + this.props.hideModal(); + }; render() { - const { t } = this.context - const { newGasFee } = this.props - const { busy } = this.state + const { t } = this.context; + const { newGasFee } = this.props; + const { busy } = this.state; return ( - ) + ); } } diff --git a/ui/app/components/app/modals/cancel-transaction/cancel-transaction.container.js b/ui/app/components/app/modals/cancel-transaction/cancel-transaction.container.js index 1386c2b99..687986fa7 100644 --- a/ui/app/components/app/modals/cancel-transaction/cancel-transaction.container.js +++ b/ui/app/components/app/modals/cancel-transaction/cancel-transaction.container.js @@ -1,20 +1,20 @@ -import { connect } from 'react-redux' -import { compose } from 'redux' -import { multiplyCurrencies } from '../../../../helpers/utils/conversion-util' -import withModalProps from '../../../../helpers/higher-order-components/with-modal-props' -import { showModal, createCancelTransaction } from '../../../../store/actions' -import { getHexGasTotal } from '../../../../helpers/utils/confirm-tx.util' -import { addHexPrefix } from '../../../../../../app/scripts/lib/util' -import CancelTransaction from './cancel-transaction.component' +import { connect } from 'react-redux'; +import { compose } from 'redux'; +import { multiplyCurrencies } from '../../../../helpers/utils/conversion-util'; +import withModalProps from '../../../../helpers/higher-order-components/with-modal-props'; +import { showModal, createCancelTransaction } from '../../../../store/actions'; +import { getHexGasTotal } from '../../../../helpers/utils/confirm-tx.util'; +import { addHexPrefix } from '../../../../../../app/scripts/lib/util'; +import CancelTransaction from './cancel-transaction.component'; const mapStateToProps = (state, ownProps) => { - const { metamask } = state - const { transactionId, originalGasPrice } = ownProps - const { currentNetworkTxList } = metamask + const { metamask } = state; + const { transactionId, originalGasPrice } = ownProps; + const { currentNetworkTxList } = metamask; const transaction = currentNetworkTxList.find( ({ id }) => id === transactionId, - ) - const transactionStatus = transaction ? transaction.status : '' + ); + const transactionStatus = transaction ? transaction.status : ''; const defaultNewGasPrice = addHexPrefix( multiplyCurrencies(originalGasPrice, 1.1, { @@ -22,12 +22,12 @@ const mapStateToProps = (state, ownProps) => { multiplicandBase: 16, multiplierBase: 10, }), - ) + ); const newGasFee = getHexGasTotal({ gasPrice: defaultNewGasPrice, gasLimit: '0x5208', - }) + }); return { transactionId, @@ -35,23 +35,23 @@ const mapStateToProps = (state, ownProps) => { originalGasPrice, defaultNewGasPrice, newGasFee, - } -} + }; +}; const mapDispatchToProps = (dispatch) => { return { createCancelTransaction: (txId, customGasPrice) => { - return dispatch(createCancelTransaction(txId, customGasPrice)) + return dispatch(createCancelTransaction(txId, customGasPrice)); }, showTransactionConfirmedModal: () => dispatch(showModal({ name: 'TRANSACTION_CONFIRMED' })), - } -} + }; +}; const mergeProps = (stateProps, dispatchProps, ownProps) => { - const { transactionId, defaultNewGasPrice, ...restStateProps } = stateProps + const { transactionId, defaultNewGasPrice, ...restStateProps } = stateProps; // eslint-disable-next-line no-shadow - const { createCancelTransaction, ...restDispatchProps } = dispatchProps + const { createCancelTransaction, ...restDispatchProps } = dispatchProps; return { ...restStateProps, @@ -59,10 +59,10 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => { ...ownProps, createCancelTransaction: () => createCancelTransaction(transactionId, defaultNewGasPrice), - } -} + }; +}; export default compose( withModalProps, connect(mapStateToProps, mapDispatchToProps, mergeProps), -)(CancelTransaction) +)(CancelTransaction); diff --git a/ui/app/components/app/modals/cancel-transaction/index.js b/ui/app/components/app/modals/cancel-transaction/index.js index 7abc871ee..1c428a0a6 100644 --- a/ui/app/components/app/modals/cancel-transaction/index.js +++ b/ui/app/components/app/modals/cancel-transaction/index.js @@ -1 +1 @@ -export { default } from './cancel-transaction.container' +export { default } from './cancel-transaction.container'; diff --git a/ui/app/components/app/modals/cancel-transaction/tests/cancel-transaction.component.test.js b/ui/app/components/app/modals/cancel-transaction/tests/cancel-transaction.component.test.js index 64e08944a..9d75d3dab 100644 --- a/ui/app/components/app/modals/cancel-transaction/tests/cancel-transaction.component.test.js +++ b/ui/app/components/app/modals/cancel-transaction/tests/cancel-transaction.component.test.js @@ -1,41 +1,41 @@ -import assert from 'assert' -import React from 'react' -import { shallow } from 'enzyme' -import sinon from 'sinon' -import CancelTransaction from '../cancel-transaction.component' -import CancelTransactionGasFee from '../cancel-transaction-gas-fee' -import Modal from '../../../modal' +import assert from 'assert'; +import React from 'react'; +import { shallow } from 'enzyme'; +import sinon from 'sinon'; +import CancelTransaction from '../cancel-transaction.component'; +import CancelTransactionGasFee from '../cancel-transaction-gas-fee'; +import Modal from '../../../modal'; describe('CancelTransaction Component', function () { - const t = (key) => key + const t = (key) => key; it('should render a CancelTransaction modal', function () { const wrapper = shallow(, { context: { t }, - }) + }); - assert.ok(wrapper) - assert.strictEqual(wrapper.find(Modal).length, 1) - assert.strictEqual(wrapper.find(CancelTransactionGasFee).length, 1) + assert.ok(wrapper); + assert.strictEqual(wrapper.find(Modal).length, 1); + assert.strictEqual(wrapper.find(CancelTransactionGasFee).length, 1); assert.strictEqual( wrapper.find(CancelTransactionGasFee).props().value, '0x1319718a5000', - ) + ); assert.strictEqual( wrapper.find('.cancel-transaction__title').text(), 'cancellationGasFee', - ) + ); assert.strictEqual( wrapper.find('.cancel-transaction__description').text(), 'attemptToCancelDescription', - ) - }) + ); + }); it('should pass the correct props to the Modal component', async function () { const createCancelTransactionSpy = sinon .stub() - .callsFake(() => Promise.resolve()) - const hideModalSpy = sinon.spy() + .callsFake(() => Promise.resolve()); + const hideModalSpy = sinon.spy(); const wrapper = shallow( undefined} />, { context: { t } }, - ) + ); - assert.strictEqual(wrapper.find(Modal).length, 1) - const modalProps = wrapper.find(Modal).props() + assert.strictEqual(wrapper.find(Modal).length, 1); + const modalProps = wrapper.find(Modal).props(); - assert.strictEqual(modalProps.headerText, 'attemptToCancel') - assert.strictEqual(modalProps.submitText, 'yesLetsTry') - assert.strictEqual(modalProps.cancelText, 'nevermind') + assert.strictEqual(modalProps.headerText, 'attemptToCancel'); + assert.strictEqual(modalProps.submitText, 'yesLetsTry'); + assert.strictEqual(modalProps.cancelText, 'nevermind'); - assert.strictEqual(createCancelTransactionSpy.callCount, 0) - assert.strictEqual(hideModalSpy.callCount, 0) - await modalProps.onSubmit() - assert.strictEqual(createCancelTransactionSpy.callCount, 1) - assert.strictEqual(hideModalSpy.callCount, 1) - modalProps.onCancel() - assert.strictEqual(hideModalSpy.callCount, 2) - }) -}) + assert.strictEqual(createCancelTransactionSpy.callCount, 0); + assert.strictEqual(hideModalSpy.callCount, 0); + await modalProps.onSubmit(); + assert.strictEqual(createCancelTransactionSpy.callCount, 1); + assert.strictEqual(hideModalSpy.callCount, 1); + modalProps.onCancel(); + assert.strictEqual(hideModalSpy.callCount, 2); + }); +}); diff --git a/ui/app/components/app/modals/confirm-delete-network/confirm-delete-network.component.js b/ui/app/components/app/modals/confirm-delete-network/confirm-delete-network.component.js index a746cff08..a8be936a5 100644 --- a/ui/app/components/app/modals/confirm-delete-network/confirm-delete-network.component.js +++ b/ui/app/components/app/modals/confirm-delete-network/confirm-delete-network.component.js @@ -1,6 +1,6 @@ -import React, { PureComponent } from 'react' -import PropTypes from 'prop-types' -import Modal, { ModalContent } from '../../modal' +import React, { PureComponent } from 'react'; +import PropTypes from 'prop-types'; +import Modal, { ModalContent } from '../../modal'; export default class ConfirmDeleteNetwork extends PureComponent { static propTypes = { @@ -8,21 +8,21 @@ export default class ConfirmDeleteNetwork extends PureComponent { delRpcTarget: PropTypes.func.isRequired, onConfirm: PropTypes.func.isRequired, target: PropTypes.string.isRequired, - } + }; static contextTypes = { t: PropTypes.func, - } + }; handleDelete = () => { this.props.delRpcTarget(this.props.target).then(() => { - this.props.onConfirm() - this.props.hideModal() - }) - } + this.props.onConfirm(); + this.props.hideModal(); + }); + }; render() { - const { t } = this.context + const { t } = this.context; return ( - ) + ); } } diff --git a/ui/app/components/app/modals/confirm-delete-network/confirm-delete-network.container.js b/ui/app/components/app/modals/confirm-delete-network/confirm-delete-network.container.js index b6a5c99f5..5133e7824 100644 --- a/ui/app/components/app/modals/confirm-delete-network/confirm-delete-network.container.js +++ b/ui/app/components/app/modals/confirm-delete-network/confirm-delete-network.container.js @@ -1,16 +1,16 @@ -import { connect } from 'react-redux' -import { compose } from 'redux' -import withModalProps from '../../../../helpers/higher-order-components/with-modal-props' -import { delRpcTarget } from '../../../../store/actions' -import ConfirmDeleteNetwork from './confirm-delete-network.component' +import { connect } from 'react-redux'; +import { compose } from 'redux'; +import withModalProps from '../../../../helpers/higher-order-components/with-modal-props'; +import { delRpcTarget } from '../../../../store/actions'; +import ConfirmDeleteNetwork from './confirm-delete-network.component'; const mapDispatchToProps = (dispatch) => { return { delRpcTarget: (target) => dispatch(delRpcTarget(target)), - } -} + }; +}; export default compose( withModalProps, connect(null, mapDispatchToProps), -)(ConfirmDeleteNetwork) +)(ConfirmDeleteNetwork); diff --git a/ui/app/components/app/modals/confirm-delete-network/index.js b/ui/app/components/app/modals/confirm-delete-network/index.js index de9543eea..998f9160c 100644 --- a/ui/app/components/app/modals/confirm-delete-network/index.js +++ b/ui/app/components/app/modals/confirm-delete-network/index.js @@ -1 +1 @@ -export { default } from './confirm-delete-network.container' +export { default } from './confirm-delete-network.container'; diff --git a/ui/app/components/app/modals/confirm-delete-network/tests/confirm-delete-network.test.js b/ui/app/components/app/modals/confirm-delete-network/tests/confirm-delete-network.test.js index 7d06ef459..28d7e8214 100644 --- a/ui/app/components/app/modals/confirm-delete-network/tests/confirm-delete-network.test.js +++ b/ui/app/components/app/modals/confirm-delete-network/tests/confirm-delete-network.test.js @@ -1,58 +1,58 @@ -import assert from 'assert' -import React from 'react' -import sinon from 'sinon' -import { mount } from 'enzyme' -import ConfirmDeleteNetwork from '..' +import assert from 'assert'; +import React from 'react'; +import sinon from 'sinon'; +import { mount } from 'enzyme'; +import ConfirmDeleteNetwork from '..'; describe('Confirm Delete Network', function () { - let wrapper + let wrapper; const props = { hideModal: sinon.spy(), delRpcTarget: sinon.stub().resolves(), onConfirm: sinon.spy(), target: '', - } + }; beforeEach(function () { wrapper = mount(, { context: { t: (str) => str, }, - }) - }) + }); + }); afterEach(function () { - props.hideModal.resetHistory() - props.delRpcTarget.resetHistory() - props.onConfirm.resetHistory() - }) + props.hideModal.resetHistory(); + props.delRpcTarget.resetHistory(); + props.onConfirm.resetHistory(); + }); it('renders delete network modal title', function () { - const modalTitle = wrapper.find('.modal-content__title') - assert.strictEqual(modalTitle.text(), 'deleteNetwork') - }) + const modalTitle = wrapper.find('.modal-content__title'); + assert.strictEqual(modalTitle.text(), 'deleteNetwork'); + }); it('clicks cancel to hide modal', function () { const cancelButton = wrapper.find( '.button.btn-default.modal-container__footer-button', - ) - cancelButton.simulate('click') + ); + cancelButton.simulate('click'); - assert(props.hideModal.calledOnce) - }) + assert(props.hideModal.calledOnce); + }); it('clicks delete to delete the target and hides modal', function () { const deleteButton = wrapper.find( '.button.btn-danger.modal-container__footer-button', - ) + ); - deleteButton.simulate('click') + deleteButton.simulate('click'); setImmediate(() => { - assert(props.delRpcTarget.calledOnce) - assert(props.hideModal.calledOnce) - assert(props.onConfirm.calledOnce) - }) - }) -}) + assert(props.delRpcTarget.calledOnce); + assert(props.hideModal.calledOnce); + assert(props.onConfirm.calledOnce); + }); + }); +}); diff --git a/ui/app/components/app/modals/confirm-remove-account/confirm-remove-account.component.js b/ui/app/components/app/modals/confirm-remove-account/confirm-remove-account.component.js index 49db8697c..7c7213aa0 100644 --- a/ui/app/components/app/modals/confirm-remove-account/confirm-remove-account.component.js +++ b/ui/app/components/app/modals/confirm-remove-account/confirm-remove-account.component.js @@ -1,9 +1,9 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import Modal from '../../modal' -import { addressSummary } from '../../../../helpers/utils/util' -import Identicon from '../../../ui/identicon' -import getAccountLink from '../../../../../lib/account-link' +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import Modal from '../../modal'; +import { addressSummary } from '../../../../helpers/utils/util'; +import Identicon from '../../../ui/identicon'; +import getAccountLink from '../../../../../lib/account-link'; export default class ConfirmRemoveAccount extends Component { static propTypes = { @@ -11,24 +11,24 @@ export default class ConfirmRemoveAccount extends Component { removeAccount: PropTypes.func.isRequired, identity: PropTypes.object.isRequired, network: PropTypes.string.isRequired, - } + }; static contextTypes = { t: PropTypes.func, - } + }; handleRemove = () => { this.props .removeAccount(this.props.identity.address) - .then(() => this.props.hideModal()) - } + .then(() => this.props.hideModal()); + }; handleCancel = () => { - this.props.hideModal() - } + this.props.hideModal(); + }; renderSelectedAccount() { - const { identity } = this.props + const { identity } = this.props; return (
    @@ -61,11 +61,11 @@ export default class ConfirmRemoveAccount extends Component {
    - ) + ); } render() { - const { t } = this.context + const { t } = this.context; return ( - ) + ); } } diff --git a/ui/app/components/app/modals/confirm-remove-account/confirm-remove-account.container.js b/ui/app/components/app/modals/confirm-remove-account/confirm-remove-account.container.js index c3b54577c..61d23978c 100644 --- a/ui/app/components/app/modals/confirm-remove-account/confirm-remove-account.container.js +++ b/ui/app/components/app/modals/confirm-remove-account/confirm-remove-account.container.js @@ -1,22 +1,22 @@ -import { connect } from 'react-redux' -import { compose } from 'redux' -import withModalProps from '../../../../helpers/higher-order-components/with-modal-props' -import { removeAccount } from '../../../../store/actions' -import ConfirmRemoveAccount from './confirm-remove-account.component' +import { connect } from 'react-redux'; +import { compose } from 'redux'; +import withModalProps from '../../../../helpers/higher-order-components/with-modal-props'; +import { removeAccount } from '../../../../store/actions'; +import ConfirmRemoveAccount from './confirm-remove-account.component'; const mapStateToProps = (state) => { return { network: state.metamask.network, - } -} + }; +}; const mapDispatchToProps = (dispatch) => { return { removeAccount: (address) => dispatch(removeAccount(address)), - } -} + }; +}; export default compose( withModalProps, connect(mapStateToProps, mapDispatchToProps), -)(ConfirmRemoveAccount) +)(ConfirmRemoveAccount); diff --git a/ui/app/components/app/modals/confirm-remove-account/index.js b/ui/app/components/app/modals/confirm-remove-account/index.js index ecb5f7790..7f0156c55 100644 --- a/ui/app/components/app/modals/confirm-remove-account/index.js +++ b/ui/app/components/app/modals/confirm-remove-account/index.js @@ -1 +1 @@ -export { default } from './confirm-remove-account.container' +export { default } from './confirm-remove-account.container'; diff --git a/ui/app/components/app/modals/confirm-remove-account/tests/confirm-remove-account.test.js b/ui/app/components/app/modals/confirm-remove-account/tests/confirm-remove-account.test.js index e50b87308..f070092c2 100644 --- a/ui/app/components/app/modals/confirm-remove-account/tests/confirm-remove-account.test.js +++ b/ui/app/components/app/modals/confirm-remove-account/tests/confirm-remove-account.test.js @@ -1,18 +1,18 @@ -import assert from 'assert' -import React from 'react' -import PropTypes from 'prop-types' -import { Provider } from 'react-redux' -import sinon from 'sinon' -import configureStore from 'redux-mock-store' -import { mount } from 'enzyme' -import ConfirmRemoveAccount from '..' +import assert from 'assert'; +import React from 'react'; +import PropTypes from 'prop-types'; +import { Provider } from 'react-redux'; +import sinon from 'sinon'; +import configureStore from 'redux-mock-store'; +import { mount } from 'enzyme'; +import ConfirmRemoveAccount from '..'; describe('Confirm Remove Account', function () { - let wrapper + let wrapper; const state = { metamask: {}, - } + }; const props = { hideModal: sinon.spy(), @@ -22,10 +22,10 @@ describe('Confirm Remove Account', function () { address: '0xAddress', name: 'Account 1', }, - } + }; - const mockStore = configureStore() - const store = mockStore(state) + const mockStore = configureStore(); + const store = mockStore(state); beforeEach(function () { wrapper = mount( @@ -42,40 +42,40 @@ describe('Confirm Remove Account', function () { store: PropTypes.object, }, }, - ) - }) + ); + }); afterEach(function () { - props.hideModal.resetHistory() - }) + props.hideModal.resetHistory(); + }); it('nevermind', function () { - const nevermind = wrapper.find({ type: 'default' }) - nevermind.simulate('click') + const nevermind = wrapper.find({ type: 'default' }); + nevermind.simulate('click'); - assert(props.hideModal.calledOnce) - }) + assert(props.hideModal.calledOnce); + }); it('remove', function (done) { - const remove = wrapper.find({ type: 'secondary' }) - remove.simulate('click') + const remove = wrapper.find({ type: 'secondary' }); + remove.simulate('click'); - assert(props.removeAccount.calledOnce) + assert(props.removeAccount.calledOnce); assert.strictEqual( props.removeAccount.getCall(0).args[0], props.identity.address, - ) + ); setImmediate(() => { - assert(props.hideModal.calledOnce) - done() - }) - }) + assert(props.hideModal.calledOnce); + done(); + }); + }); it('closes', function () { - const close = wrapper.find('.modal-container__header-close') - close.simulate('click') + const close = wrapper.find('.modal-container__header-close'); + close.simulate('click'); - assert(props.hideModal.calledOnce) - }) -}) + assert(props.hideModal.calledOnce); + }); +}); diff --git a/ui/app/components/app/modals/confirm-reset-account/confirm-reset-account.component.js b/ui/app/components/app/modals/confirm-reset-account/confirm-reset-account.component.js index ba558c7fd..c4e5a9a17 100644 --- a/ui/app/components/app/modals/confirm-reset-account/confirm-reset-account.component.js +++ b/ui/app/components/app/modals/confirm-reset-account/confirm-reset-account.component.js @@ -1,23 +1,23 @@ -import React, { PureComponent } from 'react' -import PropTypes from 'prop-types' -import Modal, { ModalContent } from '../../modal' +import React, { PureComponent } from 'react'; +import PropTypes from 'prop-types'; +import Modal, { ModalContent } from '../../modal'; export default class ConfirmResetAccount extends PureComponent { static propTypes = { hideModal: PropTypes.func.isRequired, resetAccount: PropTypes.func.isRequired, - } + }; static contextTypes = { t: PropTypes.func, - } + }; handleReset = () => { - this.props.resetAccount().then(() => this.props.hideModal()) - } + this.props.resetAccount().then(() => this.props.hideModal()); + }; render() { - const { t } = this.context + const { t } = this.context; return ( - ) + ); } } diff --git a/ui/app/components/app/modals/confirm-reset-account/confirm-reset-account.container.js b/ui/app/components/app/modals/confirm-reset-account/confirm-reset-account.container.js index fcbcb9c7a..cc226b3df 100644 --- a/ui/app/components/app/modals/confirm-reset-account/confirm-reset-account.container.js +++ b/ui/app/components/app/modals/confirm-reset-account/confirm-reset-account.container.js @@ -1,16 +1,16 @@ -import { connect } from 'react-redux' -import { compose } from 'redux' -import withModalProps from '../../../../helpers/higher-order-components/with-modal-props' -import { resetAccount } from '../../../../store/actions' -import ConfirmResetAccount from './confirm-reset-account.component' +import { connect } from 'react-redux'; +import { compose } from 'redux'; +import withModalProps from '../../../../helpers/higher-order-components/with-modal-props'; +import { resetAccount } from '../../../../store/actions'; +import ConfirmResetAccount from './confirm-reset-account.component'; const mapDispatchToProps = (dispatch) => { return { resetAccount: () => dispatch(resetAccount()), - } -} + }; +}; export default compose( withModalProps, connect(null, mapDispatchToProps), -)(ConfirmResetAccount) +)(ConfirmResetAccount); diff --git a/ui/app/components/app/modals/confirm-reset-account/index.js b/ui/app/components/app/modals/confirm-reset-account/index.js index ca4d9c5bf..e38b61560 100644 --- a/ui/app/components/app/modals/confirm-reset-account/index.js +++ b/ui/app/components/app/modals/confirm-reset-account/index.js @@ -1 +1 @@ -export { default } from './confirm-reset-account.container' +export { default } from './confirm-reset-account.container'; diff --git a/ui/app/components/app/modals/confirm-reset-account/tests/confirm-reset-account.test.js b/ui/app/components/app/modals/confirm-reset-account/tests/confirm-reset-account.test.js index fad3a609a..38af4a5a3 100644 --- a/ui/app/components/app/modals/confirm-reset-account/tests/confirm-reset-account.test.js +++ b/ui/app/components/app/modals/confirm-reset-account/tests/confirm-reset-account.test.js @@ -1,46 +1,46 @@ -import assert from 'assert' -import React from 'react' -import sinon from 'sinon' -import { mount } from 'enzyme' -import ConfirmResetAccount from '..' +import assert from 'assert'; +import React from 'react'; +import sinon from 'sinon'; +import { mount } from 'enzyme'; +import ConfirmResetAccount from '..'; describe('Confirm Reset Account', function () { - let wrapper + let wrapper; const props = { hideModal: sinon.spy(), resetAccount: sinon.stub().resolves(), - } + }; beforeEach(function () { wrapper = mount(, { context: { t: (str) => str, }, - }) - }) + }); + }); afterEach(function () { - props.hideModal.resetHistory() - }) + props.hideModal.resetHistory(); + }); it('hides modal when nevermind button is clicked', function () { const nevermind = wrapper.find( '.btn-default.modal-container__footer-button', - ) - nevermind.simulate('click') + ); + nevermind.simulate('click'); - assert(props.hideModal.calledOnce) - }) + assert(props.hideModal.calledOnce); + }); it('resets account and hides modal when reset button is clicked', function (done) { - const reset = wrapper.find('.btn-danger.modal-container__footer-button') - reset.simulate('click') + const reset = wrapper.find('.btn-danger.modal-container__footer-button'); + reset.simulate('click'); setImmediate(() => { - assert(props.resetAccount.calledOnce) - assert(props.hideModal.calledOnce) - done() - }) - }) -}) + assert(props.resetAccount.calledOnce); + assert(props.hideModal.calledOnce); + done(); + }); + }); +}); diff --git a/ui/app/components/app/modals/deposit-ether-modal/deposit-ether-modal.component.js b/ui/app/components/app/modals/deposit-ether-modal/deposit-ether-modal.component.js index a0043a539..59522154c 100644 --- a/ui/app/components/app/modals/deposit-ether-modal/deposit-ether-modal.component.js +++ b/ui/app/components/app/modals/deposit-ether-modal/deposit-ether-modal.component.js @@ -1,13 +1,13 @@ -import PropTypes from 'prop-types' -import React, { Component } from 'react' -import { getNetworkDisplayName } from '../../../../../../app/scripts/controllers/network/util' -import Button from '../../../ui/button' +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { getNetworkDisplayName } from '../../../../../../app/scripts/controllers/network/util'; +import Button from '../../../ui/button'; export default class DepositEtherModal extends Component { static contextTypes = { t: PropTypes.func, metricsEvent: PropTypes.func.isRequired, - } + }; static propTypes = { network: PropTypes.string.isRequired, @@ -17,17 +17,17 @@ export default class DepositEtherModal extends Component { hideWarning: PropTypes.func.isRequired, hideModal: PropTypes.func.isRequired, showAccountDetailModal: PropTypes.func.isRequired, - } + }; faucetRowText = (networkName) => { - return this.context.t('getEtherFromFaucet', [networkName]) - } + return this.context.t('getEtherFromFaucet', [networkName]); + }; goToAccountDetailsModal = () => { - this.props.hideWarning() - this.props.hideModal() - this.props.showAccountDetailModal() - } + this.props.hideWarning(); + this.props.hideModal(); + this.props.showAccountDetailModal(); + }; renderRow({ logo, @@ -43,7 +43,7 @@ export default class DepositEtherModal extends Component { showBackButton, }) { if (hide) { - return null + return null; } return ( @@ -82,14 +82,14 @@ export default class DepositEtherModal extends Component { )} - ) + ); } render() { - const { network, toWyre, address, toFaucet } = this.props + const { network, toWyre, address, toFaucet } = this.props; - const isTestNetwork = ['3', '4', '5', '42'].find((n) => n === network) - const networkName = getNetworkDisplayName(network) + const isTestNetwork = ['3', '4', '5', '42'].find((n) => n === network); + const networkName = getNetworkDisplayName(network); return (
    @@ -103,8 +103,8 @@ export default class DepositEtherModal extends Component {
    { - this.props.hideWarning() - this.props.hideModal() + this.props.hideWarning(); + this.props.hideModal(); }} />
    @@ -130,8 +130,8 @@ export default class DepositEtherModal extends Component { action: 'Deposit Ether', name: 'Click buy Ether via Wyre', }, - }) - toWyre(address) + }); + toWyre(address); }, hide: isTestNetwork, })} @@ -163,6 +163,6 @@ export default class DepositEtherModal extends Component {
    - ) + ); } } diff --git a/ui/app/components/app/modals/deposit-ether-modal/deposit-ether-modal.container.js b/ui/app/components/app/modals/deposit-ether-modal/deposit-ether-modal.container.js index abee66e48..8e324c5b2 100644 --- a/ui/app/components/app/modals/deposit-ether-modal/deposit-ether-modal.container.js +++ b/ui/app/components/app/modals/deposit-ether-modal/deposit-ether-modal.container.js @@ -1,35 +1,35 @@ -import { connect } from 'react-redux' +import { connect } from 'react-redux'; import { buyEth, hideModal, showModal, hideWarning, -} from '../../../../store/actions' -import DepositEtherModal from './deposit-ether-modal.component' +} from '../../../../store/actions'; +import DepositEtherModal from './deposit-ether-modal.component'; function mapStateToProps(state) { return { network: state.metamask.network, address: state.metamask.selectedAddress, - } + }; } function mapDispatchToProps(dispatch) { return { toWyre: (address) => { - dispatch(buyEth({ service: 'wyre', address })) + dispatch(buyEth({ service: 'wyre', address })); }, hideModal: () => { - dispatch(hideModal()) + dispatch(hideModal()); }, hideWarning: () => { - dispatch(hideWarning()) + dispatch(hideWarning()); }, showAccountDetailModal: () => { - dispatch(showModal({ name: 'ACCOUNT_DETAILS' })) + dispatch(showModal({ name: 'ACCOUNT_DETAILS' })); }, toFaucet: (network) => dispatch(buyEth({ network })), - } + }; } -export default connect(mapStateToProps, mapDispatchToProps)(DepositEtherModal) +export default connect(mapStateToProps, mapDispatchToProps)(DepositEtherModal); diff --git a/ui/app/components/app/modals/deposit-ether-modal/index.js b/ui/app/components/app/modals/deposit-ether-modal/index.js index 01a262a73..02f355cb0 100644 --- a/ui/app/components/app/modals/deposit-ether-modal/index.js +++ b/ui/app/components/app/modals/deposit-ether-modal/index.js @@ -1 +1 @@ -export { default } from './deposit-ether-modal.container' +export { default } from './deposit-ether-modal.container'; diff --git a/ui/app/components/app/modals/edit-approval-permission/edit-approval-permission.component.js b/ui/app/components/app/modals/edit-approval-permission/edit-approval-permission.component.js index e4a2bba6a..2e100353f 100644 --- a/ui/app/components/app/modals/edit-approval-permission/edit-approval-permission.component.js +++ b/ui/app/components/app/modals/edit-approval-permission/edit-approval-permission.component.js @@ -1,14 +1,14 @@ -import React, { PureComponent } from 'react' -import PropTypes from 'prop-types' -import log from 'loglevel' -import classnames from 'classnames' -import BigNumber from 'bignumber.js' -import Modal from '../../modal' -import Identicon from '../../../ui/identicon' -import TextField from '../../../ui/text-field' -import { calcTokenAmount } from '../../../../helpers/utils/token-util' +import React, { PureComponent } from 'react'; +import PropTypes from 'prop-types'; +import log from 'loglevel'; +import classnames from 'classnames'; +import BigNumber from 'bignumber.js'; +import Modal from '../../modal'; +import Identicon from '../../../ui/identicon'; +import TextField from '../../../ui/text-field'; +import { calcTokenAmount } from '../../../../helpers/utils/token-util'; -const MAX_UNSIGNED_256_INT = new BigNumber(2).pow(256).minus(1).toString(10) +const MAX_UNSIGNED_256_INT = new BigNumber(2).pow(256).minus(1).toString(10); export default class EditApprovalPermission extends PureComponent { static propTypes = { @@ -22,20 +22,20 @@ export default class EditApprovalPermission extends PureComponent { setCustomAmount: PropTypes.func, origin: PropTypes.string.isRequired, requiredMinimum: PropTypes.instanceOf(BigNumber), - } + }; static contextTypes = { t: PropTypes.func, - } + }; state = { // This is used as a TextField value, which should be a string. customSpendLimit: this.props.customTokenAmount || '', selectedOptionIsUnlimited: !this.props.customTokenAmount, - } + }; renderModalContent(error) { - const { t } = this.context + const { t } = this.context; const { hideModal, selectedIdentity, @@ -44,9 +44,9 @@ export default class EditApprovalPermission extends PureComponent { tokenBalance, customTokenAmount, origin, - } = this.props - const { name, address } = selectedIdentity || {} - const { selectedOptionIsUnlimited } = this.state + } = this.props; + const { name, address } = selectedIdentity || {}; + const { selectedOptionIsUnlimited } = this.state; return (
    @@ -154,9 +154,9 @@ export default class EditApprovalPermission extends PureComponent { customTokenAmount || tokenAmount, )} ${tokenSymbol}`} onChange={(event) => { - this.setState({ customSpendLimit: event.target.value }) + this.setState({ customSpendLimit: event.target.value }); if (selectedOptionIsUnlimited) { - this.setState({ selectedOptionIsUnlimited: false }) + this.setState({ selectedOptionIsUnlimited: false }); } }} fullWidth @@ -169,61 +169,61 @@ export default class EditApprovalPermission extends PureComponent {
    - ) + ); } validateSpendLimit() { - const { t } = this.context - const { decimals, requiredMinimum } = this.props - const { selectedOptionIsUnlimited, customSpendLimit } = this.state + const { t } = this.context; + const { decimals, requiredMinimum } = this.props; + const { selectedOptionIsUnlimited, customSpendLimit } = this.state; if (selectedOptionIsUnlimited || !customSpendLimit) { - return undefined + return undefined; } - let customSpendLimitNumber + let customSpendLimitNumber; try { - customSpendLimitNumber = new BigNumber(customSpendLimit) + customSpendLimitNumber = new BigNumber(customSpendLimit); } catch (error) { - log.debug(`Error converting '${customSpendLimit}' to BigNumber:`, error) - return t('spendLimitInvalid') + log.debug(`Error converting '${customSpendLimit}' to BigNumber:`, error); + return t('spendLimitInvalid'); } if (customSpendLimitNumber.isNegative()) { - return t('spendLimitInvalid') + return t('spendLimitInvalid'); } - const maxTokenAmount = calcTokenAmount(MAX_UNSIGNED_256_INT, decimals) + const maxTokenAmount = calcTokenAmount(MAX_UNSIGNED_256_INT, decimals); if (customSpendLimitNumber.greaterThan(maxTokenAmount)) { - return t('spendLimitTooLarge') + return t('spendLimitTooLarge'); } if ( requiredMinimum !== undefined && customSpendLimitNumber.lessThan(requiredMinimum) ) { - return t('spendLimitInsufficient') + return t('spendLimitInsufficient'); } - return undefined + return undefined; } render() { - const { t } = this.context - const { setCustomAmount, hideModal, customTokenAmount } = this.props - const { selectedOptionIsUnlimited, customSpendLimit } = this.state + const { t } = this.context; + const { setCustomAmount, hideModal, customTokenAmount } = this.props; + const { selectedOptionIsUnlimited, customSpendLimit } = this.state; - const error = this.validateSpendLimit() + const error = this.validateSpendLimit(); const disabled = Boolean( (customSpendLimit === customTokenAmount && !selectedOptionIsUnlimited) || error, - ) + ); return ( { - setCustomAmount(selectedOptionIsUnlimited ? '' : customSpendLimit) - hideModal() + setCustomAmount(selectedOptionIsUnlimited ? '' : customSpendLimit); + hideModal(); }} submitText={t('save')} submitType="primary" @@ -233,6 +233,6 @@ export default class EditApprovalPermission extends PureComponent { > {this.renderModalContent(error)} - ) + ); } } diff --git a/ui/app/components/app/modals/edit-approval-permission/edit-approval-permission.container.js b/ui/app/components/app/modals/edit-approval-permission/edit-approval-permission.container.js index 671d99cf6..4a3777c72 100644 --- a/ui/app/components/app/modals/edit-approval-permission/edit-approval-permission.container.js +++ b/ui/app/components/app/modals/edit-approval-permission/edit-approval-permission.container.js @@ -1,18 +1,18 @@ -import { connect } from 'react-redux' -import { compose } from 'redux' -import withModalProps from '../../../../helpers/higher-order-components/with-modal-props' -import { getSelectedIdentity } from '../../../../selectors' -import EditApprovalPermission from './edit-approval-permission.component' +import { connect } from 'react-redux'; +import { compose } from 'redux'; +import withModalProps from '../../../../helpers/higher-order-components/with-modal-props'; +import { getSelectedIdentity } from '../../../../selectors'; +import EditApprovalPermission from './edit-approval-permission.component'; const mapStateToProps = (state) => { - const modalStateProps = state.appState.modal.modalState.props || {} + const modalStateProps = state.appState.modal.modalState.props || {}; return { selectedIdentity: getSelectedIdentity(state), ...modalStateProps, - } -} + }; +}; export default compose( withModalProps, connect(mapStateToProps), -)(EditApprovalPermission) +)(EditApprovalPermission); diff --git a/ui/app/components/app/modals/edit-approval-permission/index.js b/ui/app/components/app/modals/edit-approval-permission/index.js index 3f50d3e99..ac4ff0926 100644 --- a/ui/app/components/app/modals/edit-approval-permission/index.js +++ b/ui/app/components/app/modals/edit-approval-permission/index.js @@ -1 +1 @@ -export { default } from './edit-approval-permission.container' +export { default } from './edit-approval-permission.container'; diff --git a/ui/app/components/app/modals/export-private-key-modal/export-private-key-modal.component.js b/ui/app/components/app/modals/export-private-key-modal/export-private-key-modal.component.js index 5b976765d..6ac5219b3 100644 --- a/ui/app/components/app/modals/export-private-key-modal/export-private-key-modal.component.js +++ b/ui/app/components/app/modals/export-private-key-modal/export-private-key-modal.component.js @@ -1,23 +1,23 @@ -import log from 'loglevel' -import PropTypes from 'prop-types' -import React, { Component } from 'react' +import log from 'loglevel'; +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; -import { stripHexPrefix } from 'ethereumjs-util' -import copyToClipboard from 'copy-to-clipboard' -import { checksumAddress } from '../../../../helpers/utils/util' -import ReadOnlyInput from '../../../ui/readonly-input' -import Button from '../../../ui/button' -import AccountModalContainer from '../account-modal-container' +import { stripHexPrefix } from 'ethereumjs-util'; +import copyToClipboard from 'copy-to-clipboard'; +import { checksumAddress } from '../../../../helpers/utils/util'; +import ReadOnlyInput from '../../../ui/readonly-input'; +import Button from '../../../ui/button'; +import AccountModalContainer from '../account-modal-container'; export default class ExportPrivateKeyModal extends Component { static contextTypes = { t: PropTypes.func, - } + }; static defaultProps = { warning: null, previousModalState: null, - } + }; static propTypes = { exportAccount: PropTypes.func.isRequired, @@ -28,21 +28,21 @@ export default class ExportPrivateKeyModal extends Component { hideWarning: PropTypes.func.isRequired, clearAccountDetails: PropTypes.func.isRequired, previousModalState: PropTypes.string, - } + }; state = { password: '', privateKey: null, showWarning: true, - } + }; componentWillUnmount() { - this.props.clearAccountDetails() - this.props.hideWarning() + this.props.clearAccountDetails(); + this.props.hideWarning(); } exportAccountAndGetPrivateKey = (password, address) => { - const { exportAccount } = this.props + const { exportAccount } = this.props; exportAccount(password, address) .then((privateKey) => @@ -51,8 +51,8 @@ export default class ExportPrivateKeyModal extends Component { showWarning: false, }), ) - .catch((e) => log.error(e)) - } + .catch((e) => log.error(e)); + }; renderPasswordLabel(privateKey) { return ( @@ -61,11 +61,11 @@ export default class ExportPrivateKeyModal extends Component { ? this.context.t('copyPrivateKey') : this.context.t('typePassword')} - ) + ); } renderPasswordInput(privateKey) { - const plainKey = privateKey && stripHexPrefix(privateKey) + const plainKey = privateKey && stripHexPrefix(privateKey); if (!privateKey) { return ( @@ -74,7 +74,7 @@ export default class ExportPrivateKeyModal extends Component { className="export-private-key-modal__password-input" onChange={(event) => this.setState({ password: event.target.value })} /> - ) + ); } return ( @@ -85,7 +85,7 @@ export default class ExportPrivateKeyModal extends Component { value={plainKey} onClick={() => copyToClipboard(plainKey)} /> - ) + ); } renderButtons(privateKey, address, hideModal) { @@ -124,7 +124,7 @@ export default class ExportPrivateKeyModal extends Component { )} - ) + ); } render() { @@ -134,10 +134,10 @@ export default class ExportPrivateKeyModal extends Component { showAccountDetailModal, hideModal, previousModalState, - } = this.props - const { name, address } = selectedIdentity + } = this.props; + const { name, address } = selectedIdentity; - const { privateKey, showWarning } = this.state + const { privateKey, showWarning } = this.state; return ( {this.renderButtons(privateKey, address, hideModal)} - ) + ); } } diff --git a/ui/app/components/app/modals/export-private-key-modal/export-private-key-modal.container.js b/ui/app/components/app/modals/export-private-key-modal/export-private-key-modal.container.js index 59a0252a1..6dd8acd92 100644 --- a/ui/app/components/app/modals/export-private-key-modal/export-private-key-modal.container.js +++ b/ui/app/components/app/modals/export-private-key-modal/export-private-key-modal.container.js @@ -1,48 +1,48 @@ -import { connect } from 'react-redux' +import { connect } from 'react-redux'; import { exportAccount, hideWarning, showModal, hideModal, clearAccountDetails, -} from '../../../../store/actions' -import { getSelectedIdentity } from '../../../../selectors' -import ExportPrivateKeyModal from './export-private-key-modal.component' +} from '../../../../store/actions'; +import { getSelectedIdentity } from '../../../../selectors'; +import ExportPrivateKeyModal from './export-private-key-modal.component'; function mapStateToPropsFactory() { - let selectedIdentity = null + let selectedIdentity = null; return function mapStateToProps(state) { // We should **not** change the identity displayed here even if it changes from underneath us. // If we do, we will be showing the user one private key and a **different** address and name. // Note that the selected identity **will** change from underneath us when we unlock the keyring // which is the expected behavior that we are side-stepping. - selectedIdentity = selectedIdentity || getSelectedIdentity(state) + selectedIdentity = selectedIdentity || getSelectedIdentity(state); return { warning: state.appState.warning, privateKey: state.appState.accountDetail.privateKey, selectedIdentity, previousModalState: state.appState.modal.previousModalState.name, - } - } + }; + }; } function mapDispatchToProps(dispatch) { return { exportAccount: (password, address) => { return dispatch(exportAccount(password, address)).then((res) => { - dispatch(hideWarning()) - return res - }) + dispatch(hideWarning()); + return res; + }); }, showAccountDetailModal: () => dispatch(showModal({ name: 'ACCOUNT_DETAILS' })), hideModal: () => dispatch(hideModal()), hideWarning: () => dispatch(hideWarning()), clearAccountDetails: () => dispatch(clearAccountDetails()), - } + }; } export default connect( mapStateToPropsFactory, mapDispatchToProps, -)(ExportPrivateKeyModal) +)(ExportPrivateKeyModal); diff --git a/ui/app/components/app/modals/export-private-key-modal/index.js b/ui/app/components/app/modals/export-private-key-modal/index.js index 996c995ca..ffba2f7e8 100644 --- a/ui/app/components/app/modals/export-private-key-modal/index.js +++ b/ui/app/components/app/modals/export-private-key-modal/index.js @@ -1 +1 @@ -export { default } from './export-private-key-modal.container' +export { default } from './export-private-key-modal.container'; diff --git a/ui/app/components/app/modals/fade-modal.js b/ui/app/components/app/modals/fade-modal.js index 0b4edeb43..e8c371f8d 100644 --- a/ui/app/components/app/modals/fade-modal.js +++ b/ui/app/components/app/modals/fade-modal.js @@ -1,46 +1,46 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; -let index = 0 -let extraSheet +let index = 0; +let extraSheet; const insertRule = (css) => { if (!extraSheet) { // First time, create an extra stylesheet for adding rules - extraSheet = document.createElement('style') - document.getElementsByTagName('head')[0].appendChild(extraSheet) + extraSheet = document.createElement('style'); + document.getElementsByTagName('head')[0].appendChild(extraSheet); // Keep reference to actual StyleSheet object (`styleSheet` for IE < 9) - extraSheet = extraSheet.sheet || extraSheet.styleSheet + extraSheet = extraSheet.sheet || extraSheet.styleSheet; } - extraSheet.insertRule(css, (extraSheet.cssRules || extraSheet.rules).length) + extraSheet.insertRule(css, (extraSheet.cssRules || extraSheet.rules).length); - return extraSheet -} + return extraSheet; +}; const insertKeyframesRule = (keyframes) => { // random name // eslint-disable-next-line no-plusplus - const name = `anim_${++index}${Number(new Date())}` - let css = `@keyframes ${name} {` + const name = `anim_${++index}${Number(new Date())}`; + let css = `@keyframes ${name} {`; Object.keys(keyframes).forEach((key) => { - css += `${key} {` + css += `${key} {`; Object.keys(keyframes[key]).forEach((property) => { - const part = `:${keyframes[key][property]};` - css += property + part - }) + const part = `:${keyframes[key][property]};`; + css += property + part; + }); - css += '}' - }) + css += '}'; + }); - css += '}' + css += '}'; - insertRule(css) + insertRule(css); - return name -} + return name; +}; const animation = { show: { @@ -83,41 +83,41 @@ const animation = { opacity: 0, }, }), -} +}; -const endEvents = ['transitionend', 'animationend'] +const endEvents = ['transitionend', 'animationend']; function addEventListener(node, eventName, eventListener) { - node.addEventListener(eventName, eventListener, false) + node.addEventListener(eventName, eventListener, false); } function removeEventListener(node, eventName, eventListener) { - node.removeEventListener(eventName, eventListener, false) + node.removeEventListener(eventName, eventListener, false); } const removeEndEventListener = (node, eventListener) => { if (endEvents.length === 0) { - return + return; } endEvents.forEach(function (endEvent) { - removeEventListener(node, endEvent, eventListener) - }) -} + removeEventListener(node, endEvent, eventListener); + }); +}; const addEndEventListener = (node, eventListener) => { if (endEvents.length === 0) { // If CSS transitions are not supported, trigger an "end animation" // event immediately. - window.setTimeout(eventListener, 0) - return + window.setTimeout(eventListener, 0); + return; } endEvents.forEach(function (endEvent) { - addEventListener(node, endEvent, eventListener) - }) -} + addEventListener(node, endEvent, eventListener); + }); +}; class FadeModal extends Component { - content = null + content = null; static propTypes = { backdrop: PropTypes.bool, @@ -129,7 +129,7 @@ class FadeModal extends Component { onShow: PropTypes.func, onHide: PropTypes.func, children: PropTypes.node, - } + }; static defaultProps = { onShow: () => undefined, @@ -141,43 +141,43 @@ class FadeModal extends Component { backdropStyle: {}, contentStyle: {}, children: [], - } + }; state = { willHide: true, hidden: true, - } + }; addTransitionListener = (node, handle) => { if (node) { const endListener = function (e) { if (e && e.target !== node) { - return + return; } - removeEndEventListener(node, endListener) - handle() - } - addEndEventListener(node, endListener) + removeEndEventListener(node, endListener); + handle(); + }; + addEndEventListener(node, endListener); } - } + }; handleBackdropClick = () => { if (this.props.closeOnClick) { - this.hide() + this.hide(); } - } + }; hasHidden = () => { - return this.state.hidden - } + return this.state.hidden; + }; render() { if (this.state.hidden) { - return null + return null; } - const { willHide } = this.state - const { modalStyle } = this.props + const { willHide } = this.state; + const { modalStyle } = this.props; const backdropStyle = { animationName: willHide ? animation.hideBackdropAnimation @@ -185,7 +185,7 @@ class FadeModal extends Component { animationTimingFunction: (willHide ? animation.hide : animation.show) .animationTimingFunction, ...this.props.backdropStyle, - } + }; const contentStyle = { animationDuration: (willHide ? animation.hide : animation.show) .animationDuration, @@ -195,7 +195,7 @@ class FadeModal extends Component { animationTimingFunction: (willHide ? animation.hide : animation.show) .animationTimingFunction, ...this.props.contentStyle, - } + }; const backdrop = this.props.backdrop ? (
    - ) : undefined + ) : undefined; if (willHide) { - this.addTransitionListener(this.content, this.leave) + this.addTransitionListener(this.content, this.leave); } return ( @@ -223,72 +223,72 @@ class FadeModal extends Component {
    {backdrop} - ) + ); } leave = () => { this.setState({ hidden: true, - }) - this.props.onHide(this.state.hideSource) - } + }); + this.props.onHide(this.state.hideSource); + }; enter = () => { - this.props.onShow() - } + this.props.onShow(); + }; show = () => { if (!this.state.hidden) { - return + return; } this.setState({ willHide: false, hidden: false, - }) + }); setTimeout( function () { - this.addTransitionListener(this.content, this.enter) + this.addTransitionListener(this.content, this.enter); }.bind(this), 0, - ) - } + ); + }; hide = () => { if (this.hasHidden()) { - return + return; } this.setState({ willHide: true, - }) - } + }); + }; listenKeyboard = (event) => { if (typeof this.props.keyboard === 'function') { - this.props.keyboard(event) + this.props.keyboard(event); } else { - this.closeOnEsc(event) + this.closeOnEsc(event); } - } + }; closeOnEsc = (event) => { if ( this.props.keyboard && (event.key === 'Escape' || event.keyCode === 27) ) { - this.hide() + this.hide(); } - } + }; UNSAFE_componentDidMount = () => { - window.addEventListener('keydown', this.listenKeyboard, true) - } + window.addEventListener('keydown', this.listenKeyboard, true); + }; UNSAFE_componentWillUnmount = () => { - window.removeEventListener('keydown', this.listenKeyboard, true) - } + window.removeEventListener('keydown', this.listenKeyboard, true); + }; } -export default FadeModal +export default FadeModal; diff --git a/ui/app/components/app/modals/hide-token-confirmation-modal/hide-token-confirmation-modal.js b/ui/app/components/app/modals/hide-token-confirmation-modal/hide-token-confirmation-modal.js index 592528038..f8bdc5546 100644 --- a/ui/app/components/app/modals/hide-token-confirmation-modal/hide-token-confirmation-modal.js +++ b/ui/app/components/app/modals/hide-token-confirmation-modal/hide-token-confirmation-modal.js @@ -1,15 +1,15 @@ -import PropTypes from 'prop-types' -import React, { Component } from 'react' -import { connect } from 'react-redux' -import * as actions from '../../../../store/actions' -import Identicon from '../../../ui/identicon' -import Button from '../../../ui/button' +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { connect } from 'react-redux'; +import * as actions from '../../../../store/actions'; +import Identicon from '../../../ui/identicon'; +import Button from '../../../ui/button'; function mapStateToProps(state) { return { token: state.appState.modal.modalState.props.token, assetImages: state.metamask.assetImages, - } + }; } function mapDispatchToProps(dispatch) { @@ -17,16 +17,16 @@ function mapDispatchToProps(dispatch) { hideModal: () => dispatch(actions.hideModal()), hideToken: (address) => { dispatch(actions.removeToken(address)).then(() => { - dispatch(actions.hideModal()) - }) + dispatch(actions.hideModal()); + }); }, - } + }; } class HideTokenConfirmationModal extends Component { static contextTypes = { t: PropTypes.func, - } + }; static propTypes = { hideToken: PropTypes.func.isRequired, @@ -36,14 +36,14 @@ class HideTokenConfirmationModal extends Component { symbol: PropTypes.string, address: PropTypes.string, }), - } + }; - state = {} + state = {}; render() { - const { token, hideToken, hideModal, assetImages } = this.props - const { symbol, address } = token - const image = assetImages[address] + const { token, hideToken, hideModal, assetImages } = this.props; + const { symbol, address } = token; + const image = assetImages[address]; return (
    @@ -81,11 +81,11 @@ class HideTokenConfirmationModal extends Component {
    - ) + ); } } export default connect( mapStateToProps, mapDispatchToProps, -)(HideTokenConfirmationModal) +)(HideTokenConfirmationModal); diff --git a/ui/app/components/app/modals/hide-token-confirmation-modal/index.js b/ui/app/components/app/modals/hide-token-confirmation-modal/index.js index 31e866398..d9f281c39 100644 --- a/ui/app/components/app/modals/hide-token-confirmation-modal/index.js +++ b/ui/app/components/app/modals/hide-token-confirmation-modal/index.js @@ -1 +1 @@ -export { default } from './hide-token-confirmation-modal' +export { default } from './hide-token-confirmation-modal'; diff --git a/ui/app/components/app/modals/index.js b/ui/app/components/app/modals/index.js index 9667e0d32..6d93ef89e 100644 --- a/ui/app/components/app/modals/index.js +++ b/ui/app/components/app/modals/index.js @@ -1,3 +1,3 @@ -import Modal from './modal' +import Modal from './modal'; -export { Modal } +export { Modal }; diff --git a/ui/app/components/app/modals/loading-network-error/index.js b/ui/app/components/app/modals/loading-network-error/index.js index b3737458a..634a5a6d0 100644 --- a/ui/app/components/app/modals/loading-network-error/index.js +++ b/ui/app/components/app/modals/loading-network-error/index.js @@ -1 +1 @@ -export { default } from './loading-network-error.container' +export { default } from './loading-network-error.container'; diff --git a/ui/app/components/app/modals/loading-network-error/loading-network-error.component.js b/ui/app/components/app/modals/loading-network-error/loading-network-error.component.js index 9f5d1ad07..0b473f5f4 100644 --- a/ui/app/components/app/modals/loading-network-error/loading-network-error.component.js +++ b/ui/app/components/app/modals/loading-network-error/loading-network-error.component.js @@ -1,24 +1,24 @@ -import React from 'react' -import PropTypes from 'prop-types' -import Modal, { ModalContent } from '../../modal' +import React from 'react'; +import PropTypes from 'prop-types'; +import Modal, { ModalContent } from '../../modal'; const LoadingNetworkError = (props, context) => { - const { t } = context - const { hideModal } = props + const { t } = context; + const { hideModal } = props; return ( hideModal()} submitText={t('tryAgain')}> - ) -} + ); +}; LoadingNetworkError.contextTypes = { t: PropTypes.func, -} +}; LoadingNetworkError.propTypes = { hideModal: PropTypes.func, -} +}; -export default LoadingNetworkError +export default LoadingNetworkError; diff --git a/ui/app/components/app/modals/loading-network-error/loading-network-error.container.js b/ui/app/components/app/modals/loading-network-error/loading-network-error.container.js index 765cdf9c5..4206717a1 100644 --- a/ui/app/components/app/modals/loading-network-error/loading-network-error.container.js +++ b/ui/app/components/app/modals/loading-network-error/loading-network-error.container.js @@ -1,4 +1,4 @@ -import withModalProps from '../../../../helpers/higher-order-components/with-modal-props' -import LoadingNetworkError from './loading-network-error.component' +import withModalProps from '../../../../helpers/higher-order-components/with-modal-props'; +import LoadingNetworkError from './loading-network-error.component'; -export default withModalProps(LoadingNetworkError) +export default withModalProps(LoadingNetworkError); diff --git a/ui/app/components/app/modals/metametrics-opt-in-modal/index.js b/ui/app/components/app/modals/metametrics-opt-in-modal/index.js index 47f946757..e41006182 100644 --- a/ui/app/components/app/modals/metametrics-opt-in-modal/index.js +++ b/ui/app/components/app/modals/metametrics-opt-in-modal/index.js @@ -1 +1 @@ -export { default } from './metametrics-opt-in-modal.container' +export { default } from './metametrics-opt-in-modal.container'; diff --git a/ui/app/components/app/modals/metametrics-opt-in-modal/metametrics-opt-in-modal.component.js b/ui/app/components/app/modals/metametrics-opt-in-modal/metametrics-opt-in-modal.component.js index 6fbdb54c3..833d8b49d 100644 --- a/ui/app/components/app/modals/metametrics-opt-in-modal/metametrics-opt-in-modal.component.js +++ b/ui/app/components/app/modals/metametrics-opt-in-modal/metametrics-opt-in-modal.component.js @@ -1,22 +1,22 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import MetaFoxLogo from '../../../ui/metafox-logo' -import PageContainerFooter from '../../../ui/page-container/page-container-footer' +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import MetaFoxLogo from '../../../ui/metafox-logo'; +import PageContainerFooter from '../../../ui/page-container/page-container-footer'; export default class MetaMetricsOptInModal extends Component { static propTypes = { setParticipateInMetaMetrics: PropTypes.func, hideModal: PropTypes.func, - } + }; static contextTypes = { metricsEvent: PropTypes.func, t: PropTypes.func, - } + }; render() { - const { metricsEvent, t } = this.context - const { setParticipateInMetaMetrics, hideModal } = this.props + const { metricsEvent, t } = this.context; + const { setParticipateInMetaMetrics, hideModal } = this.props; return (
    @@ -115,9 +115,9 @@ export default class MetaMetricsOptInModal extends Component { { excludeMetaMetricsId: true, }, - ) - hideModal() - }) + ); + hideModal(); + }); }} cancelText={t('noThanks')} hideCancel={false} @@ -130,9 +130,9 @@ export default class MetaMetricsOptInModal extends Component { name: 'Metrics Opt In', }, isOptIn: true, - }) - hideModal() - }) + }); + hideModal(); + }); }} submitText={t('affirmAgree')} submitButtonType="confirm" @@ -141,6 +141,6 @@ export default class MetaMetricsOptInModal extends Component {
    - ) + ); } } diff --git a/ui/app/components/app/modals/metametrics-opt-in-modal/metametrics-opt-in-modal.container.js b/ui/app/components/app/modals/metametrics-opt-in-modal/metametrics-opt-in-modal.container.js index bb1322903..e55247787 100644 --- a/ui/app/components/app/modals/metametrics-opt-in-modal/metametrics-opt-in-modal.container.js +++ b/ui/app/components/app/modals/metametrics-opt-in-modal/metametrics-opt-in-modal.container.js @@ -1,25 +1,25 @@ -import { connect } from 'react-redux' -import { compose } from 'redux' -import withModalProps from '../../../../helpers/higher-order-components/with-modal-props' -import { setParticipateInMetaMetrics } from '../../../../store/actions' -import MetaMetricsOptInModal from './metametrics-opt-in-modal.component' +import { connect } from 'react-redux'; +import { compose } from 'redux'; +import withModalProps from '../../../../helpers/higher-order-components/with-modal-props'; +import { setParticipateInMetaMetrics } from '../../../../store/actions'; +import MetaMetricsOptInModal from './metametrics-opt-in-modal.component'; const mapStateToProps = (_, ownProps) => { - const { unapprovedTxCount } = ownProps + const { unapprovedTxCount } = ownProps; return { unapprovedTxCount, - } -} + }; +}; const mapDispatchToProps = (dispatch) => { return { setParticipateInMetaMetrics: (val) => dispatch(setParticipateInMetaMetrics(val)), - } -} + }; +}; export default compose( withModalProps, connect(mapStateToProps, mapDispatchToProps), -)(MetaMetricsOptInModal) +)(MetaMetricsOptInModal); diff --git a/ui/app/components/app/modals/metametrics-opt-in-modal/tests/metametrics-opt-in-modal.test.js b/ui/app/components/app/modals/metametrics-opt-in-modal/tests/metametrics-opt-in-modal.test.js index 5b9f4798d..a34ad9905 100644 --- a/ui/app/components/app/modals/metametrics-opt-in-modal/tests/metametrics-opt-in-modal.test.js +++ b/ui/app/components/app/modals/metametrics-opt-in-modal/tests/metametrics-opt-in-modal.test.js @@ -1,18 +1,18 @@ -import assert from 'assert' -import React from 'react' -import sinon from 'sinon' -import { mount } from 'enzyme' -import MetaMetricsOptIn from '..' -import messages from '../../../../../../../app/_locales/en/messages.json' +import assert from 'assert'; +import React from 'react'; +import sinon from 'sinon'; +import { mount } from 'enzyme'; +import MetaMetricsOptIn from '..'; +import messages from '../../../../../../../app/_locales/en/messages.json'; describe('MetaMetrics Opt In', function () { - let wrapper + let wrapper; const props = { setParticipateInMetaMetrics: sinon.stub().resolves(), hideModal: sinon.spy(), participateInMetaMetrics: null, - } + }; beforeEach(function () { wrapper = mount(, { @@ -20,43 +20,43 @@ describe('MetaMetrics Opt In', function () { metricsEvent: () => undefined, t: (key) => messages[key].message, }, - }) - }) + }); + }); afterEach(function () { - props.setParticipateInMetaMetrics.resetHistory() - props.hideModal.resetHistory() - }) + props.setParticipateInMetaMetrics.resetHistory(); + props.hideModal.resetHistory(); + }); it('passes false to setParticipateInMetaMetrics and hides modal', function (done) { - const noThanks = wrapper.find('.btn-default.page-container__footer-button') - noThanks.simulate('click') + const noThanks = wrapper.find('.btn-default.page-container__footer-button'); + noThanks.simulate('click'); setImmediate(() => { - assert(props.setParticipateInMetaMetrics.calledOnce) + assert(props.setParticipateInMetaMetrics.calledOnce); assert.strictEqual( props.setParticipateInMetaMetrics.getCall(0).args[0], false, - ) - assert(props.hideModal.calledOnce) - done() - }) - }) + ); + assert(props.hideModal.calledOnce); + done(); + }); + }); it('passes true to setParticipateInMetaMetrics and hides modal', function (done) { const affirmAgree = wrapper.find( '.btn-primary.page-container__footer-button', - ) - affirmAgree.simulate('click') + ); + affirmAgree.simulate('click'); setImmediate(() => { - assert(props.setParticipateInMetaMetrics.calledOnce) + assert(props.setParticipateInMetaMetrics.calledOnce); assert.strictEqual( props.setParticipateInMetaMetrics.getCall(0).args[0], true, - ) - assert(props.hideModal.calledOnce) - done() - }) - }) -}) + ); + assert(props.hideModal.calledOnce); + done(); + }); + }); +}); diff --git a/ui/app/components/app/modals/modal.js b/ui/app/components/app/modals/modal.js index 5ad7d3470..9aa659d32 100644 --- a/ui/app/components/app/modals/modal.js +++ b/ui/app/components/app/modals/modal.js @@ -1,34 +1,34 @@ -import PropTypes from 'prop-types' -import React, { Component } from 'react' +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; -import { connect } from 'react-redux' -import * as actions from '../../../store/actions' -import { resetCustomData as resetCustomGasData } from '../../../ducks/gas/gas.duck' -import isMobileView from '../../../../lib/is-mobile-view' -import { getEnvironmentType } from '../../../../../app/scripts/lib/util' -import { ENVIRONMENT_TYPE_POPUP } from '../../../../../shared/constants/app' +import { connect } from 'react-redux'; +import * as actions from '../../../store/actions'; +import { resetCustomData as resetCustomGasData } from '../../../ducks/gas/gas.duck'; +import isMobileView from '../../../../lib/is-mobile-view'; +import { getEnvironmentType } from '../../../../../app/scripts/lib/util'; +import { ENVIRONMENT_TYPE_POPUP } from '../../../../../shared/constants/app'; // Modal Components -import ConfirmCustomizeGasModal from '../gas-customization/gas-modal-page-container' -import SwapsGasCustomizationModal from '../../../pages/swaps/swaps-gas-customization-modal' -import DepositEtherModal from './deposit-ether-modal' -import AccountDetailsModal from './account-details-modal' -import ExportPrivateKeyModal from './export-private-key-modal' -import HideTokenConfirmationModal from './hide-token-confirmation-modal' -import QRScanner from './qr-scanner' +import ConfirmCustomizeGasModal from '../gas-customization/gas-modal-page-container'; +import SwapsGasCustomizationModal from '../../../pages/swaps/swaps-gas-customization-modal'; +import DepositEtherModal from './deposit-ether-modal'; +import AccountDetailsModal from './account-details-modal'; +import ExportPrivateKeyModal from './export-private-key-modal'; +import HideTokenConfirmationModal from './hide-token-confirmation-modal'; +import QRScanner from './qr-scanner'; -import ConfirmRemoveAccount from './confirm-remove-account' -import ConfirmResetAccount from './confirm-reset-account' -import TransactionConfirmed from './transaction-confirmed' -import CancelTransaction from './cancel-transaction' +import ConfirmRemoveAccount from './confirm-remove-account'; +import ConfirmResetAccount from './confirm-reset-account'; +import TransactionConfirmed from './transaction-confirmed'; +import CancelTransaction from './cancel-transaction'; -import FadeModal from './fade-modal' -import MetaMetricsOptInModal from './metametrics-opt-in-modal' -import RejectTransactions from './reject-transactions' -import ConfirmDeleteNetwork from './confirm-delete-network' -import AddToAddressBookModal from './add-to-addressbook-modal' -import EditApprovalPermission from './edit-approval-permission' -import NewAccountModal from './new-account-modal' +import FadeModal from './fade-modal'; +import MetaMetricsOptInModal from './metametrics-opt-in-modal'; +import RejectTransactions from './reject-transactions'; +import ConfirmDeleteNetwork from './confirm-delete-network'; +import AddToAddressBookModal from './add-to-addressbook-modal'; +import EditApprovalPermission from './edit-approval-permission'; +import NewAccountModal from './new-account-modal'; const modalContainerBaseStyle = { transform: 'translate3d(-50%, 0, 0px)', @@ -36,19 +36,19 @@ const modalContainerBaseStyle = { borderRadius: '8px', backgroundColor: '#FFFFFF', boxShadow: '0 2px 22px 0 rgba(0,0,0,0.2)', -} +}; const modalContainerLaptopStyle = { ...modalContainerBaseStyle, width: '344px', top: '15%', -} +}; const modalContainerMobileStyle = { ...modalContainerBaseStyle, width: '309px', top: '12.5%', -} +}; const accountModalStyle = { mobileModalStyle: { @@ -76,7 +76,7 @@ const accountModalStyle = { contentStyle: { borderRadius: '4px', }, -} +}; const MODALS = { DEPOSIT_ETHER: { @@ -381,31 +381,31 @@ const MODALS = { mobileModalStyle: {}, laptopModalStyle: {}, }, -} +}; const BACKDROPSTYLE = { backgroundColor: 'rgba(0, 0, 0, 0.5)', -} +}; function mapStateToProps(state) { return { active: state.appState.modal.open, modalState: state.appState.modal.modalState, - } + }; } function mapDispatchToProps(dispatch) { return { hideModal: (customOnHideOpts) => { - dispatch(actions.hideModal()) + dispatch(actions.hideModal()); if (customOnHideOpts && customOnHideOpts.action) { - dispatch(customOnHideOpts.action(...customOnHideOpts.args)) + dispatch(customOnHideOpts.action(...customOnHideOpts.args)); } }, hideWarning: () => { - dispatch(actions.hideWarning()) + dispatch(actions.hideWarning()); }, - } + }; } class Modal extends Component { @@ -414,30 +414,30 @@ class Modal extends Component { hideModal: PropTypes.func.isRequired, hideWarning: PropTypes.func.isRequired, modalState: PropTypes.object.isRequired, - } + }; hide() { - this.modalRef.hide() + this.modalRef.hide(); } show() { - this.modalRef.show() + this.modalRef.show(); } UNSAFE_componentWillReceiveProps(nextProps, _) { if (nextProps.active) { - this.show() + this.show(); } else if (this.props.active) { - this.hide() + this.hide(); } } render() { - const modal = MODALS[this.props.modalState.name || 'DEFAULT'] - const { contents: children, disableBackdropClick = false } = modal + const modal = MODALS[this.props.modalState.name || 'DEFAULT']; + const { contents: children, disableBackdropClick = false } = modal; const modalStyle = - modal[isMobileView() ? 'mobileModalStyle' : 'laptopModalStyle'] - const contentStyle = modal.contentStyle || {} + modal[isMobileView() ? 'mobileModalStyle' : 'laptopModalStyle']; + const contentStyle = modal.contentStyle || {}; return ( { - this.modalRef = ref + this.modalRef = ref; }} modalStyle={modalStyle} contentStyle={contentStyle} @@ -460,8 +460,8 @@ class Modal extends Component { > {children} - ) + ); } } -export default connect(mapStateToProps, mapDispatchToProps)(Modal) +export default connect(mapStateToProps, mapDispatchToProps)(Modal); diff --git a/ui/app/components/app/modals/new-account-modal/index.js b/ui/app/components/app/modals/new-account-modal/index.js index 2c8b78890..f83a18951 100644 --- a/ui/app/components/app/modals/new-account-modal/index.js +++ b/ui/app/components/app/modals/new-account-modal/index.js @@ -1 +1 @@ -export { default } from './new-account-modal.container' +export { default } from './new-account-modal.container'; diff --git a/ui/app/components/app/modals/new-account-modal/new-account-modal.component.js b/ui/app/components/app/modals/new-account-modal/new-account-modal.component.js index 612947249..18119a3f0 100644 --- a/ui/app/components/app/modals/new-account-modal/new-account-modal.component.js +++ b/ui/app/components/app/modals/new-account-modal/new-account-modal.component.js @@ -1,42 +1,42 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import Button from '../../../ui/button/button.component' +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import Button from '../../../ui/button/button.component'; export default class NewAccountModal extends Component { static contextTypes = { t: PropTypes.func, - } + }; static propTypes = { hideModal: PropTypes.func.isRequired, newAccountNumber: PropTypes.number.isRequired, onSave: PropTypes.func.isRequired, - } + }; state = { alias: this.context.t('newAccountNumberName', [ this.props.newAccountNumber, ]), - } + }; onChange = (e) => { this.setState({ alias: e.target.value, - }) - } + }); + }; onSubmit = () => { - this.props.onSave(this.state.alias).then(this.props.hideModal) - } + this.props.onSave(this.state.alias).then(this.props.hideModal); + }; onKeyPress = (e) => { if (e.key === 'Enter' && this.state.alias) { - this.onSubmit() + this.onSubmit(); } - } + }; render() { - const { t } = this.context + const { t } = this.context; return (
    @@ -74,6 +74,6 @@ export default class NewAccountModal extends Component {
    - ) + ); } } diff --git a/ui/app/components/app/modals/new-account-modal/new-account-modal.container.js b/ui/app/components/app/modals/new-account-modal/new-account-modal.container.js index ab3caccd8..2a1ba3175 100644 --- a/ui/app/components/app/modals/new-account-modal/new-account-modal.container.js +++ b/ui/app/components/app/modals/new-account-modal/new-account-modal.container.js @@ -1,11 +1,11 @@ -import { connect } from 'react-redux' -import * as actions from '../../../../store/actions' -import NewAccountModal from './new-account-modal.component' +import { connect } from 'react-redux'; +import * as actions from '../../../../store/actions'; +import NewAccountModal from './new-account-modal.component'; function mapStateToProps(state) { return { ...(state.appState.modal.modalState.props || {}), - } + }; } function mapDispatchToProps(dispatch) { @@ -14,17 +14,17 @@ function mapDispatchToProps(dispatch) { createAccount: (newAccountName) => { return dispatch(actions.addNewAccount()).then((newAccountAddress) => { if (newAccountName) { - dispatch(actions.setAccountLabel(newAccountAddress, newAccountName)) + dispatch(actions.setAccountLabel(newAccountAddress, newAccountName)); } - return newAccountAddress - }) + return newAccountAddress; + }); }, - } + }; } function mergeProps(stateProps, dispatchProps) { - const { onCreateNewAccount } = stateProps - const { createAccount } = dispatchProps + const { onCreateNewAccount } = stateProps; + const { createAccount } = dispatchProps; return { ...stateProps, @@ -32,13 +32,13 @@ function mergeProps(stateProps, dispatchProps) { onSave: (newAccountName) => { return createAccount(newAccountName).then((newAccountAddress) => onCreateNewAccount(newAccountAddress), - ) + ); }, - } + }; } export default connect( mapStateToProps, mapDispatchToProps, mergeProps, -)(NewAccountModal) +)(NewAccountModal); diff --git a/ui/app/components/app/modals/qr-scanner/index.js b/ui/app/components/app/modals/qr-scanner/index.js index d96782c13..609ca893d 100644 --- a/ui/app/components/app/modals/qr-scanner/index.js +++ b/ui/app/components/app/modals/qr-scanner/index.js @@ -1,3 +1,3 @@ -import QrScanner from './qr-scanner.container' +import QrScanner from './qr-scanner.container'; -export default QrScanner +export default QrScanner; diff --git a/ui/app/components/app/modals/qr-scanner/qr-scanner.component.js b/ui/app/components/app/modals/qr-scanner/qr-scanner.component.js index 2f82ce65f..7ca6a5089 100644 --- a/ui/app/components/app/modals/qr-scanner/qr-scanner.component.js +++ b/ui/app/components/app/modals/qr-scanner/qr-scanner.component.js @@ -1,54 +1,54 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import log from 'loglevel' -import { BrowserQRCodeReader } from '@zxing/library' -import { getEnvironmentType } from '../../../../../../app/scripts/lib/util' -import { ENVIRONMENT_TYPE_FULLSCREEN } from '../../../../../../shared/constants/app' -import Spinner from '../../../ui/spinner' -import WebcamUtils from '../../../../../lib/webcam-utils' -import PageContainerFooter from '../../../ui/page-container/page-container-footer/page-container-footer.component' +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import log from 'loglevel'; +import { BrowserQRCodeReader } from '@zxing/library'; +import { getEnvironmentType } from '../../../../../../app/scripts/lib/util'; +import { ENVIRONMENT_TYPE_FULLSCREEN } from '../../../../../../shared/constants/app'; +import Spinner from '../../../ui/spinner'; +import WebcamUtils from '../../../../../lib/webcam-utils'; +import PageContainerFooter from '../../../ui/page-container/page-container-footer/page-container-footer.component'; const READY_STATE = { ACCESSING_CAMERA: 'ACCESSING_CAMERA', NEED_TO_ALLOW_ACCESS: 'NEED_TO_ALLOW_ACCESS', READY: 'READY', -} +}; export default class QrScanner extends Component { static propTypes = { hideModal: PropTypes.func.isRequired, qrCodeDetected: PropTypes.func.isRequired, - } + }; static contextTypes = { t: PropTypes.func, - } + }; constructor(props) { - super(props) + super(props); - this.state = this.getInitialState() - this.codeReader = null - this.permissionChecker = null - this.mounted = false + this.state = this.getInitialState(); + this.codeReader = null; + this.permissionChecker = null; + this.mounted = false; // Clear pre-existing qr code data before scanning - this.props.qrCodeDetected(null) + this.props.qrCodeDetected(null); } componentDidMount() { - this.mounted = true - this.checkEnvironment() + this.mounted = true; + this.checkEnvironment(); } componentDidUpdate(_, prevState) { - const { ready } = this.state + const { ready } = this.state; if (prevState.ready !== ready) { if (ready === READY_STATE.READY) { - this.initCamera() + this.initCamera(); } else if (ready === READY_STATE.NEED_TO_ALLOW_ACCESS) { - this.checkPermissions() + this.checkPermissions(); } } } @@ -57,62 +57,62 @@ export default class QrScanner extends Component { return { ready: READY_STATE.ACCESSING_CAMERA, error: null, - } + }; } checkEnvironment = async () => { try { - const { environmentReady } = await WebcamUtils.checkStatus() + const { environmentReady } = await WebcamUtils.checkStatus(); if ( !environmentReady && getEnvironmentType() !== ENVIRONMENT_TYPE_FULLSCREEN ) { - const currentUrl = new URL(window.location.href) - const currentHash = currentUrl.hash - const currentRoute = currentHash ? currentHash.substring(1) : null - global.platform.openExtensionInBrowser(currentRoute) + const currentUrl = new URL(window.location.href); + const currentHash = currentUrl.hash; + const currentRoute = currentHash ? currentHash.substring(1) : null; + global.platform.openExtensionInBrowser(currentRoute); } } catch (error) { if (this.mounted) { - this.setState({ error }) + this.setState({ error }); } } // initial attempt is required to trigger permission prompt - this.initCamera() - } + this.initCamera(); + }; checkPermissions = async () => { try { - const { permissions } = await WebcamUtils.checkStatus() + const { permissions } = await WebcamUtils.checkStatus(); if (permissions) { // Let the video stream load first... - await new Promise((resolve) => setTimeout(resolve, 2000)) + await new Promise((resolve) => setTimeout(resolve, 2000)); if (!this.mounted) { - return + return; } - this.setState({ ready: READY_STATE.READY }) + this.setState({ ready: READY_STATE.READY }); } else if (this.mounted) { // Keep checking for permissions - this.permissionChecker = setTimeout(this.checkPermissions, 1000) + this.permissionChecker = setTimeout(this.checkPermissions, 1000); } } catch (error) { if (this.mounted) { - this.setState({ error }) + this.setState({ error }); } } - } + }; componentWillUnmount() { - this.mounted = false - clearTimeout(this.permissionChecker) - this.teardownCodeReader() + this.mounted = false; + clearTimeout(this.permissionChecker); + this.teardownCodeReader(); } teardownCodeReader() { if (this.codeReader) { - this.codeReader.reset() - this.codeReader.stop() - this.codeReader = null + this.codeReader.reset(); + this.codeReader.stop(); + this.codeReader = null; } } @@ -123,40 +123,40 @@ export default class QrScanner extends Component { // It's important to prevent this codeReader from being created twice; // Firefox otherwise starts 2 video streams, one of which cannot be stopped if (!this.codeReader) { - this.codeReader = new BrowserQRCodeReader() + this.codeReader = new BrowserQRCodeReader(); } try { - await this.codeReader.getVideoInputDevices() - this.checkPermissions() + await this.codeReader.getVideoInputDevices(); + this.checkPermissions(); const content = await this.codeReader.decodeFromInputVideoDevice( undefined, 'video', - ) - const result = this.parseContent(content.text) + ); + const result = this.parseContent(content.text); if (!this.mounted) { - return + return; } else if (result.type === 'unknown') { - this.setState({ error: new Error(this.context.t('unknownQrCode')) }) + this.setState({ error: new Error(this.context.t('unknownQrCode')) }); } else { - this.props.qrCodeDetected(result) - this.stopAndClose() + this.props.qrCodeDetected(result); + this.stopAndClose(); } } catch (error) { if (!this.mounted) { - return + return; } if (error.name === 'NotAllowedError') { - log.info(`Permission denied: '${error}'`) - this.setState({ ready: READY_STATE.NEED_TO_ALLOW_ACCESS }) + log.info(`Permission denied: '${error}'`); + this.setState({ ready: READY_STATE.NEED_TO_ALLOW_ACCESS }); } else { - this.setState({ error }) + this.setState({ error }); } } - } + }; parseContent(content) { - let type = 'unknown' - let values = {} + let type = 'unknown'; + let values = {}; // Here we could add more cases // To parse other type of links @@ -164,47 +164,47 @@ export default class QrScanner extends Component { // Ethereum address links - fox ex. ethereum:0x.....1111 if (content.split('ethereum:').length > 1) { - type = 'address' - values = { address: content.split('ethereum:')[1] } + type = 'address'; + values = { address: content.split('ethereum:')[1] }; // Regular ethereum addresses - fox ex. 0x.....1111 } else if (content.substring(0, 2).toLowerCase() === '0x') { - type = 'address' - values = { address: content } + type = 'address'; + values = { address: content }; } - return { type, values } + return { type, values }; } stopAndClose = () => { if (this.codeReader) { - this.teardownCodeReader() + this.teardownCodeReader(); } - this.props.hideModal() - } + this.props.hideModal(); + }; tryAgain = () => { - clearTimeout(this.permissionChecker) + clearTimeout(this.permissionChecker); if (this.codeReader) { - this.teardownCodeReader() + this.teardownCodeReader(); } this.setState(this.getInitialState(), () => { - this.checkEnvironment() - }) - } + this.checkEnvironment(); + }); + }; renderError() { - const { t } = this.context - const { error } = this.state + const { t } = this.context; + const { error } = this.state; - let title, msg + let title, msg; if (error.type === 'NO_WEBCAM_FOUND') { - title = t('noWebcamFoundTitle') - msg = t('noWebcamFound') + title = t('noWebcamFoundTitle'); + msg = t('noWebcamFound'); } else if (error.message === t('unknownQrCode')) { - msg = t('unknownQrCode') + msg = t('unknownQrCode'); } else { - title = t('unknownCameraErrorTitle') - msg = t('unknownCameraError') + title = t('unknownCameraErrorTitle'); + msg = t('unknownCameraError'); } return ( @@ -222,20 +222,20 @@ export default class QrScanner extends Component { submitButtonType="confirm" /> - ) + ); } renderVideo() { - const { t } = this.context - const { ready } = this.state + const { t } = this.context; + const { ready } = this.state; - let message + let message; if (ready === READY_STATE.ACCESSING_CAMERA) { - message = t('accessingYourCamera') + message = t('accessingYourCamera'); } else if (ready === READY_STATE.READY) { - message = t('scanInstructions') + message = t('scanInstructions'); } else if (ready === READY_STATE.NEED_TO_ALLOW_ACCESS) { - message = t('youNeedToAllowCameraAccess') + message = t('youNeedToAllowCameraAccess'); } return ( @@ -254,16 +254,16 @@ export default class QrScanner extends Component {
    {message}
    - ) + ); } render() { - const { error } = this.state + const { error } = this.state; return (
    {error ? this.renderError() : this.renderVideo()}
    - ) + ); } } diff --git a/ui/app/components/app/modals/qr-scanner/qr-scanner.container.js b/ui/app/components/app/modals/qr-scanner/qr-scanner.container.js index 98472c6ea..3ee0209fc 100644 --- a/ui/app/components/app/modals/qr-scanner/qr-scanner.container.js +++ b/ui/app/components/app/modals/qr-scanner/qr-scanner.container.js @@ -1,12 +1,12 @@ -import { connect } from 'react-redux' -import { hideModal, qrCodeDetected } from '../../../../store/actions' -import QrScanner from './qr-scanner.component' +import { connect } from 'react-redux'; +import { hideModal, qrCodeDetected } from '../../../../store/actions'; +import QrScanner from './qr-scanner.component'; const mapDispatchToProps = (dispatch) => { return { hideModal: () => dispatch(hideModal()), qrCodeDetected: (data) => dispatch(qrCodeDetected(data)), - } -} + }; +}; -export default connect(null, mapDispatchToProps)(QrScanner) +export default connect(null, mapDispatchToProps)(QrScanner); diff --git a/ui/app/components/app/modals/reject-transactions/index.js b/ui/app/components/app/modals/reject-transactions/index.js index fcdc372b6..8cb5055c4 100644 --- a/ui/app/components/app/modals/reject-transactions/index.js +++ b/ui/app/components/app/modals/reject-transactions/index.js @@ -1 +1 @@ -export { default } from './reject-transactions.container' +export { default } from './reject-transactions.container'; diff --git a/ui/app/components/app/modals/reject-transactions/reject-transactions.component.js b/ui/app/components/app/modals/reject-transactions/reject-transactions.component.js index 4d7ed241a..3bb4cd9d9 100644 --- a/ui/app/components/app/modals/reject-transactions/reject-transactions.component.js +++ b/ui/app/components/app/modals/reject-transactions/reject-transactions.component.js @@ -1,28 +1,28 @@ -import PropTypes from 'prop-types' -import React, { PureComponent } from 'react' -import Modal from '../../modal' +import PropTypes from 'prop-types'; +import React, { PureComponent } from 'react'; +import Modal from '../../modal'; export default class RejectTransactionsModal extends PureComponent { static contextTypes = { t: PropTypes.func.isRequired, - } + }; static propTypes = { onSubmit: PropTypes.func.isRequired, hideModal: PropTypes.func.isRequired, unapprovedTxCount: PropTypes.number.isRequired, - } + }; onSubmit = async () => { - const { onSubmit, hideModal } = this.props + const { onSubmit, hideModal } = this.props; - await onSubmit() - hideModal() - } + await onSubmit(); + hideModal(); + }; render() { - const { t } = this.context - const { hideModal, unapprovedTxCount } = this.props + const { t } = this.context; + const { hideModal, unapprovedTxCount } = this.props; return ( - ) + ); } } diff --git a/ui/app/components/app/modals/reject-transactions/reject-transactions.container.js b/ui/app/components/app/modals/reject-transactions/reject-transactions.container.js index 08061a48d..bcba59350 100644 --- a/ui/app/components/app/modals/reject-transactions/reject-transactions.container.js +++ b/ui/app/components/app/modals/reject-transactions/reject-transactions.container.js @@ -1,17 +1,17 @@ -import { connect } from 'react-redux' -import { compose } from 'redux' -import withModalProps from '../../../../helpers/higher-order-components/with-modal-props' -import RejectTransactionsModal from './reject-transactions.component' +import { connect } from 'react-redux'; +import { compose } from 'redux'; +import withModalProps from '../../../../helpers/higher-order-components/with-modal-props'; +import RejectTransactionsModal from './reject-transactions.component'; const mapStateToProps = (_, ownProps) => { - const { unapprovedTxCount } = ownProps + const { unapprovedTxCount } = ownProps; return { unapprovedTxCount, - } -} + }; +}; export default compose( withModalProps, connect(mapStateToProps), -)(RejectTransactionsModal) +)(RejectTransactionsModal); diff --git a/ui/app/components/app/modals/reject-transactions/tests/reject-transactions.test.js b/ui/app/components/app/modals/reject-transactions/tests/reject-transactions.test.js index f0151939d..7988d2681 100644 --- a/ui/app/components/app/modals/reject-transactions/tests/reject-transactions.test.js +++ b/ui/app/components/app/modals/reject-transactions/tests/reject-transactions.test.js @@ -1,49 +1,49 @@ -import assert from 'assert' -import React from 'react' -import sinon from 'sinon' -import { mount } from 'enzyme' -import RejectTransactionsModal from '..' +import assert from 'assert'; +import React from 'react'; +import sinon from 'sinon'; +import { mount } from 'enzyme'; +import RejectTransactionsModal from '..'; describe('Reject Transactions Model', function () { - let wrapper + let wrapper; const props = { onSubmit: sinon.spy(), hideModal: sinon.spy(), unapprovedTxCount: 2, - } + }; beforeEach(function () { wrapper = mount(, { context: { t: (str) => str, }, - }) - }) + }); + }); afterEach(function () { - props.hideModal.resetHistory() - }) + props.hideModal.resetHistory(); + }); it('hides modal when cancel button is clicked', function () { const cancelButton = wrapper.find( '.btn-default.modal-container__footer-button', - ) - cancelButton.simulate('click') + ); + cancelButton.simulate('click'); - assert(props.hideModal.calledOnce) - }) + assert(props.hideModal.calledOnce); + }); it('onSubmit is called and hides modal when reject all clicked', function (done) { const rejectAllButton = wrapper.find( '.btn-secondary.modal-container__footer-button', - ) - rejectAllButton.simulate('click') + ); + rejectAllButton.simulate('click'); setImmediate(() => { - assert(props.onSubmit.calledOnce) - assert(props.hideModal.calledOnce) - done() - }) - }) -}) + assert(props.onSubmit.calledOnce); + assert(props.hideModal.calledOnce); + done(); + }); + }); +}); diff --git a/ui/app/components/app/modals/tests/account-details-modal.test.js b/ui/app/components/app/modals/tests/account-details-modal.test.js index 62da1c56e..f4da817e4 100644 --- a/ui/app/components/app/modals/tests/account-details-modal.test.js +++ b/ui/app/components/app/modals/tests/account-details-modal.test.js @@ -1,13 +1,13 @@ -import assert from 'assert' -import React from 'react' -import sinon from 'sinon' -import { shallow } from 'enzyme' -import AccountDetailsModal from '../account-details-modal' +import assert from 'assert'; +import React from 'react'; +import sinon from 'sinon'; +import { shallow } from 'enzyme'; +import AccountDetailsModal from '../account-details-modal'; describe('Account Details Modal', function () { - let wrapper + let wrapper; - global.platform = { openTab: sinon.spy() } + global.platform = { openTab: sinon.spy() }; const props = { hideModal: sinon.spy(), @@ -31,50 +31,50 @@ describe('Account Details Modal', function () { name: 'Account 1', }, }, - } + }; beforeEach(function () { wrapper = shallow(, { context: { t: (str) => str, }, - }) - }) + }); + }); it('sets account label when changing default account label', function () { - const accountLabel = wrapper.find('.account-details-modal__name').first() - accountLabel.simulate('submit', 'New Label') + const accountLabel = wrapper.find('.account-details-modal__name').first(); + accountLabel.simulate('submit', 'New Label'); - assert(props.setAccountLabel.calledOnce) - assert.strictEqual(props.setAccountLabel.getCall(0).args[1], 'New Label') - }) + assert(props.setAccountLabel.calledOnce); + assert.strictEqual(props.setAccountLabel.getCall(0).args[1], 'New Label'); + }); it('opens new tab when view block explorer is clicked', function () { - const modalButton = wrapper.find('.account-details-modal__button') - const etherscanLink = modalButton.first() + const modalButton = wrapper.find('.account-details-modal__button'); + const etherscanLink = modalButton.first(); - etherscanLink.simulate('click') - assert(global.platform.openTab.calledOnce) - }) + etherscanLink.simulate('click'); + assert(global.platform.openTab.calledOnce); + }); it('shows export private key modal when clicked', function () { - const modalButton = wrapper.find('.account-details-modal__button') - const etherscanLink = modalButton.last() + const modalButton = wrapper.find('.account-details-modal__button'); + const etherscanLink = modalButton.last(); - etherscanLink.simulate('click') - assert(props.showExportPrivateKeyModal.calledOnce) - }) + etherscanLink.simulate('click'); + assert(props.showExportPrivateKeyModal.calledOnce); + }); it('sets blockexplorerview text when block explorer url in rpcPrefs exists', function () { - const blockExplorerUrl = 'https://block.explorer' - wrapper.setProps({ rpcPrefs: { blockExplorerUrl } }) + const blockExplorerUrl = 'https://block.explorer'; + wrapper.setProps({ rpcPrefs: { blockExplorerUrl } }); - const modalButton = wrapper.find('.account-details-modal__button') - const blockExplorerLink = modalButton.first() + const modalButton = wrapper.find('.account-details-modal__button'); + const blockExplorerLink = modalButton.first(); assert.strictEqual( blockExplorerLink.html(), '', - ) - }) -}) + ); + }); +}); diff --git a/ui/app/components/app/modals/transaction-confirmed/index.js b/ui/app/components/app/modals/transaction-confirmed/index.js index 7776b969e..626b9c577 100644 --- a/ui/app/components/app/modals/transaction-confirmed/index.js +++ b/ui/app/components/app/modals/transaction-confirmed/index.js @@ -1 +1 @@ -export { default } from './transaction-confirmed.container' +export { default } from './transaction-confirmed.container'; diff --git a/ui/app/components/app/modals/transaction-confirmed/tests/transaction-confirmed.test.js b/ui/app/components/app/modals/transaction-confirmed/tests/transaction-confirmed.test.js index f4d35faca..5ca602785 100644 --- a/ui/app/components/app/modals/transaction-confirmed/tests/transaction-confirmed.test.js +++ b/ui/app/components/app/modals/transaction-confirmed/tests/transaction-confirmed.test.js @@ -1,15 +1,15 @@ -import assert from 'assert' -import React from 'react' -import sinon from 'sinon' -import { mount } from 'enzyme' -import TransactionConfirmed from '..' +import assert from 'assert'; +import React from 'react'; +import sinon from 'sinon'; +import { mount } from 'enzyme'; +import TransactionConfirmed from '..'; describe('Transaction Confirmed', function () { it('clicks ok to submit and hide modal', function () { const props = { onSubmit: sinon.spy(), hideModal: sinon.spy(), - } + }; const wrapper = mount( , { @@ -17,11 +17,13 @@ describe('Transaction Confirmed', function () { t: (str) => str, }, }, - ) - const submit = wrapper.find('.btn-secondary.modal-container__footer-button') - submit.simulate('click') + ); + const submit = wrapper.find( + '.btn-secondary.modal-container__footer-button', + ); + submit.simulate('click'); - assert(props.onSubmit.calledOnce) - assert(props.hideModal.calledOnce) - }) -}) + assert(props.onSubmit.calledOnce); + assert(props.hideModal.calledOnce); + }); +}); diff --git a/ui/app/components/app/modals/transaction-confirmed/transaction-confirmed.component.js b/ui/app/components/app/modals/transaction-confirmed/transaction-confirmed.component.js index aded7cb65..570867df2 100644 --- a/ui/app/components/app/modals/transaction-confirmed/transaction-confirmed.component.js +++ b/ui/app/components/app/modals/transaction-confirmed/transaction-confirmed.component.js @@ -1,29 +1,29 @@ -import React, { PureComponent } from 'react' -import PropTypes from 'prop-types' -import Modal from '../../modal' +import React, { PureComponent } from 'react'; +import PropTypes from 'prop-types'; +import Modal from '../../modal'; export default class TransactionConfirmed extends PureComponent { static contextTypes = { t: PropTypes.func, - } + }; static propTypes = { onSubmit: PropTypes.func, hideModal: PropTypes.func, - } + }; handleSubmit = () => { - const { hideModal, onSubmit } = this.props + const { hideModal, onSubmit } = this.props; - hideModal() + hideModal(); if (onSubmit && typeof onSubmit === 'function') { - onSubmit() + onSubmit(); } - } + }; render() { - const { t } = this.context + const { t } = this.context; return ( @@ -37,6 +37,6 @@ export default class TransactionConfirmed extends PureComponent { - ) + ); } } diff --git a/ui/app/components/app/modals/transaction-confirmed/transaction-confirmed.container.js b/ui/app/components/app/modals/transaction-confirmed/transaction-confirmed.container.js index 3109c5e27..eba868a9c 100644 --- a/ui/app/components/app/modals/transaction-confirmed/transaction-confirmed.container.js +++ b/ui/app/components/app/modals/transaction-confirmed/transaction-confirmed.container.js @@ -1,4 +1,4 @@ -import withModalProps from '../../../../helpers/higher-order-components/with-modal-props' -import TransactionConfirmed from './transaction-confirmed.component' +import withModalProps from '../../../../helpers/higher-order-components/with-modal-props'; +import TransactionConfirmed from './transaction-confirmed.component'; -export default withModalProps(TransactionConfirmed) +export default withModalProps(TransactionConfirmed); diff --git a/ui/app/components/app/multiple-notifications/index.js b/ui/app/components/app/multiple-notifications/index.js index a27a65187..2e7429ed0 100644 --- a/ui/app/components/app/multiple-notifications/index.js +++ b/ui/app/components/app/multiple-notifications/index.js @@ -1 +1 @@ -export { default } from './multiple-notifications.component' +export { default } from './multiple-notifications.component'; diff --git a/ui/app/components/app/multiple-notifications/multiple-notifications.component.js b/ui/app/components/app/multiple-notifications/multiple-notifications.component.js index 9d16d1dfe..4bc64ab14 100644 --- a/ui/app/components/app/multiple-notifications/multiple-notifications.component.js +++ b/ui/app/components/app/multiple-notifications/multiple-notifications.component.js @@ -1,29 +1,29 @@ -import React, { PureComponent } from 'react' -import classnames from 'classnames' -import PropTypes from 'prop-types' +import React, { PureComponent } from 'react'; +import classnames from 'classnames'; +import PropTypes from 'prop-types'; export default class MultipleNotifications extends PureComponent { static defaultProps = { children: [], classNames: [], - } + }; static propTypes = { children: PropTypes.array, classNames: PropTypes.array, - } + }; state = { showAll: false, - } + }; render() { - const { showAll } = this.state - const { children, classNames } = this.props + const { showAll } = this.state; + const { children, classNames } = this.props; - const childrenToRender = children.filter(Boolean) + const childrenToRender = children.filter(Boolean); if (childrenToRender.length === 0) { - return null + return null; } return ( @@ -47,6 +47,6 @@ export default class MultipleNotifications extends PureComponent { ) : null} - ) + ); } } diff --git a/ui/app/components/app/network-display/index.js b/ui/app/components/app/network-display/index.js index 6e361e905..bf11d5450 100644 --- a/ui/app/components/app/network-display/index.js +++ b/ui/app/components/app/network-display/index.js @@ -1 +1 @@ -export { default } from './network-display' +export { default } from './network-display'; diff --git a/ui/app/components/app/network-display/network-display.js b/ui/app/components/app/network-display/network-display.js index 351725a18..beda83498 100644 --- a/ui/app/components/app/network-display/network-display.js +++ b/ui/app/components/app/network-display/network-display.js @@ -1,18 +1,18 @@ -import React from 'react' -import PropTypes from 'prop-types' -import classnames from 'classnames' -import { useSelector } from 'react-redux' -import { NETWORK_TYPE_RPC } from '../../../../../shared/constants/network' +import React from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; +import { useSelector } from 'react-redux'; +import { NETWORK_TYPE_RPC } from '../../../../../shared/constants/network'; -import LoadingIndicator from '../../ui/loading-indicator' -import ColorIndicator from '../../ui/color-indicator' +import LoadingIndicator from '../../ui/loading-indicator'; +import ColorIndicator from '../../ui/color-indicator'; import { COLORS, SIZES, TYPOGRAPHY, -} from '../../../helpers/constants/design-system' -import Chip from '../../ui/chip/chip' -import { useI18nContext } from '../../../hooks/useI18nContext' +} from '../../../helpers/constants/design-system'; +import Chip from '../../ui/chip/chip'; +import { useI18nContext } from '../../../hooks/useI18nContext'; export default function NetworkDisplay({ colored, @@ -27,8 +27,8 @@ export default function NetworkDisplay({ network: state.metamask.network, networkNickname: state.metamask.provider.nickname, networkType: state.metamask.provider.type, - })) - const t = useI18nContext() + })); + const t = useI18nContext(); return ( - ) + ); } NetworkDisplay.propTypes = { colored: PropTypes.bool, @@ -82,9 +82,9 @@ NetworkDisplay.propTypes = { disabled: PropTypes.bool, iconClassName: PropTypes.string, onClick: PropTypes.func, -} +}; NetworkDisplay.defaultProps = { colored: true, indicatorSize: SIZES.LG, -} +}; diff --git a/ui/app/components/app/permission-page-container/index.js b/ui/app/components/app/permission-page-container/index.js index 8fe6b44b9..9c9615212 100644 --- a/ui/app/components/app/permission-page-container/index.js +++ b/ui/app/components/app/permission-page-container/index.js @@ -1,2 +1,2 @@ -export { default } from './permission-page-container.container' -export { default as PermissionPageContainerContent } from './permission-page-container-content' +export { default } from './permission-page-container.container'; +export { default as PermissionPageContainerContent } from './permission-page-container-content'; diff --git a/ui/app/components/app/permission-page-container/permission-page-container-content/index.js b/ui/app/components/app/permission-page-container/permission-page-container-content/index.js index 014e4ff59..762b02a7c 100644 --- a/ui/app/components/app/permission-page-container/permission-page-container-content/index.js +++ b/ui/app/components/app/permission-page-container/permission-page-container-content/index.js @@ -1 +1 @@ -export { default } from './permission-page-container-content.component' +export { default } from './permission-page-container-content.component'; diff --git a/ui/app/components/app/permission-page-container/permission-page-container-content/permission-page-container-content.component.js b/ui/app/components/app/permission-page-container/permission-page-container-content/permission-page-container-content.component.js index 650b9333b..3213e896b 100644 --- a/ui/app/components/app/permission-page-container/permission-page-container-content/permission-page-container-content.component.js +++ b/ui/app/components/app/permission-page-container/permission-page-container-content/permission-page-container-content.component.js @@ -1,8 +1,8 @@ -import PropTypes from 'prop-types' -import React, { PureComponent } from 'react' -import PermissionsConnectHeader from '../../permissions-connect-header' -import Tooltip from '../../../ui/tooltip' -import CheckBox from '../../../ui/check-box' +import PropTypes from 'prop-types'; +import React, { PureComponent } from 'react'; +import PermissionsConnectHeader from '../../permissions-connect-header'; +import Tooltip from '../../../ui/tooltip'; +import CheckBox from '../../../ui/check-box'; export default class PermissionPageContainerContent extends PureComponent { static propTypes = { @@ -17,29 +17,29 @@ export default class PermissionPageContainerContent extends PureComponent { onPermissionToggle: PropTypes.func.isRequired, selectedIdentities: PropTypes.array, allIdentitiesSelected: PropTypes.bool, - } + }; static defaultProps = { selectedIdentities: [], allIdentitiesSelected: false, - } + }; static contextTypes = { t: PropTypes.func, - } + }; renderRequestedPermissions() { - const { selectedPermissions, onPermissionToggle } = this.props - const { t } = this.context + const { selectedPermissions, onPermissionToggle } = this.props; + const { t } = this.context; const items = Object.keys(selectedPermissions).map((permissionName) => { - const description = t(permissionName) + const description = t(permissionName); // don't allow deselecting eth_accounts - const isDisabled = permissionName === 'eth_accounts' - const isChecked = Boolean(selectedPermissions[permissionName]) + const isDisabled = permissionName === 'eth_accounts'; + const isChecked = Boolean(selectedPermissions[permissionName]); const title = isChecked ? t('permissionCheckedIconDescription') - : t('permissionUncheckedIconDescription') + : t('permissionUncheckedIconDescription'); return (
    { if (!isDisabled) { - onPermissionToggle(permissionName) + onPermissionToggle(permissionName); } }} > @@ -60,25 +60,25 @@ export default class PermissionPageContainerContent extends PureComponent { />
    - ) - }) + ); + }); return (
    {items}
    - ) + ); } getAccountDescriptor(identity) { return `${identity.label} (...${identity.address.slice( identity.address.length - 4, - )})` + )})`; } renderAccountTooltip(textContent) { - const { selectedIdentities } = this.props - const { t } = this.context + const { selectedIdentities } = this.props; + const { t } = this.context; return ( {this.getAccountDescriptor(identity)} - ) + ); })} {selectedIdentities.length > 6 ? t('plusXMore', [selectedIdentities.length - 6]) @@ -102,7 +102,7 @@ export default class PermissionPageContainerContent extends PureComponent { > {textContent} - ) + ); } getTitle() { @@ -110,30 +110,30 @@ export default class PermissionPageContainerContent extends PureComponent { domainMetadata, selectedIdentities, allIdentitiesSelected, - } = this.props - const { t } = this.context + } = this.props; + const { t } = this.context; if (domainMetadata.extensionId) { - return t('externalExtension', [domainMetadata.extensionId]) + return t('externalExtension', [domainMetadata.extensionId]); } else if (allIdentitiesSelected) { return t('connectToAll', [ this.renderAccountTooltip(t('connectToAllAccounts')), - ]) + ]); } else if (selectedIdentities.length > 1) { return t('connectToMultiple', [ this.renderAccountTooltip( t('connectToMultipleNumberOfAccounts', [selectedIdentities.length]), ), - ]) + ]); } - return t('connectTo', [this.getAccountDescriptor(selectedIdentities[0])]) + return t('connectTo', [this.getAccountDescriptor(selectedIdentities[0])]); } render() { - const { domainMetadata } = this.props - const { t } = this.context + const { domainMetadata } = this.props; + const { t } = this.context; - const title = this.getTitle() + const title = this.getTitle(); return (
    @@ -154,6 +154,6 @@ export default class PermissionPageContainerContent extends PureComponent {
    - ) + ); } } diff --git a/ui/app/components/app/permission-page-container/permission-page-container.component.js b/ui/app/components/app/permission-page-container/permission-page-container.component.js index 14441adfa..a8378f746 100644 --- a/ui/app/components/app/permission-page-container/permission-page-container.component.js +++ b/ui/app/components/app/permission-page-container/permission-page-container.component.js @@ -1,9 +1,9 @@ -import PropTypes from 'prop-types' -import React, { Component } from 'react' -import { isEqual } from 'lodash' -import { PageContainerFooter } from '../../ui/page-container' -import PermissionsConnectFooter from '../permissions-connect-footer' -import { PermissionPageContainerContent } from '.' +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { isEqual } from 'lodash'; +import { PageContainerFooter } from '../../ui/page-container'; +import PermissionsConnectFooter from '../permissions-connect-footer'; +import { PermissionPageContainerContent } from '.'; export default class PermissionPageContainer extends Component { static propTypes = { @@ -20,46 +20,46 @@ export default class PermissionPageContainer extends Component { name: PropTypes.string.isRequired, origin: PropTypes.string.isRequired, }), - } + }; static defaultProps = { request: {}, requestMetadata: {}, selectedIdentities: [], allIdentitiesSelected: false, - } + }; static contextTypes = { t: PropTypes.func, metricsEvent: PropTypes.func, - } + }; state = { selectedPermissions: this.getRequestedMethodState( this.getRequestedMethodNames(this.props), ), - } + }; componentDidUpdate() { - const newMethodNames = this.getRequestedMethodNames(this.props) + const newMethodNames = this.getRequestedMethodNames(this.props); if (!isEqual(Object.keys(this.state.selectedPermissions), newMethodNames)) { // this should be a new request, so just overwrite this.setState({ selectedPermissions: this.getRequestedMethodState(newMethodNames), - }) + }); } } getRequestedMethodState(methodNames) { return methodNames.reduce((acc, methodName) => { - acc[methodName] = true - return acc - }, {}) + acc[methodName] = true; + return acc; + }, {}); } getRequestedMethodNames(props) { - return Object.keys(props.request.permissions || {}) + return Object.keys(props.request.permissions || {}); } onPermissionToggle = (methodName) => { @@ -68,8 +68,8 @@ export default class PermissionPageContainer extends Component { ...this.state.selectedPermissions, [methodName]: !this.state.selectedPermissions[methodName], }, - }) - } + }); + }; componentDidMount() { this.context.metricsEvent({ @@ -78,13 +78,13 @@ export default class PermissionPageContainer extends Component { action: 'Connect', name: 'Tab Opened', }, - }) + }); } onCancel = () => { - const { request, rejectPermissionsRequest } = this.props - rejectPermissionsRequest(request.metadata.id) - } + const { request, rejectPermissionsRequest } = this.props; + rejectPermissionsRequest(request.metadata.id); + }; onSubmit = () => { const { @@ -92,28 +92,28 @@ export default class PermissionPageContainer extends Component { approvePermissionsRequest, rejectPermissionsRequest, selectedIdentities, - } = this.props + } = this.props; const request = { ..._request, permissions: { ..._request.permissions }, - } + }; Object.keys(this.state.selectedPermissions).forEach((key) => { if (!this.state.selectedPermissions[key]) { - delete request.permissions[key] + delete request.permissions[key]; } - }) + }); if (Object.keys(request.permissions).length > 0) { approvePermissionsRequest( request, selectedIdentities.map((selectedIdentity) => selectedIdentity.address), - ) + ); } else { - rejectPermissionsRequest(request.metadata.id) + rejectPermissionsRequest(request.metadata.id); } - } + }; render() { const { @@ -121,7 +121,7 @@ export default class PermissionPageContainer extends Component { targetDomainMetadata, selectedIdentities, allIdentitiesSelected, - } = this.props + } = this.props; return (
    @@ -146,6 +146,6 @@ export default class PermissionPageContainer extends Component { />
    - ) + ); } } diff --git a/ui/app/components/app/permission-page-container/permission-page-container.container.js b/ui/app/components/app/permission-page-container/permission-page-container.container.js index e0b3ff49f..031dfa6f0 100644 --- a/ui/app/components/app/permission-page-container/permission-page-container.container.js +++ b/ui/app/components/app/permission-page-container/permission-page-container.container.js @@ -1,18 +1,18 @@ -import { connect } from 'react-redux' -import { getMetaMaskIdentities } from '../../../selectors' -import PermissionPageContainer from './permission-page-container.component' +import { connect } from 'react-redux'; +import { getMetaMaskIdentities } from '../../../selectors'; +import PermissionPageContainer from './permission-page-container.component'; const mapStateToProps = (state, ownProps) => { - const { selectedIdentities } = ownProps + const { selectedIdentities } = ownProps; - const allIdentities = getMetaMaskIdentities(state) + const allIdentities = getMetaMaskIdentities(state); const allIdentitiesSelected = Object.keys(selectedIdentities).length === - Object.keys(allIdentities).length && selectedIdentities.length > 1 + Object.keys(allIdentities).length && selectedIdentities.length > 1; return { allIdentitiesSelected, - } -} + }; +}; -export default connect(mapStateToProps)(PermissionPageContainer) +export default connect(mapStateToProps)(PermissionPageContainer); diff --git a/ui/app/components/app/permissions-connect-footer/index.js b/ui/app/components/app/permissions-connect-footer/index.js index 8096e1e3d..6d47aff6a 100644 --- a/ui/app/components/app/permissions-connect-footer/index.js +++ b/ui/app/components/app/permissions-connect-footer/index.js @@ -1 +1 @@ -export { default } from './permissions-connect-footer.component' +export { default } from './permissions-connect-footer.component'; diff --git a/ui/app/components/app/permissions-connect-footer/permissions-connect-footer.component.js b/ui/app/components/app/permissions-connect-footer/permissions-connect-footer.component.js index 5a1aef1a4..52713aeb1 100644 --- a/ui/app/components/app/permissions-connect-footer/permissions-connect-footer.component.js +++ b/ui/app/components/app/permissions-connect-footer/permissions-connect-footer.component.js @@ -1,13 +1,13 @@ -import PropTypes from 'prop-types' -import React, { Component } from 'react' +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; export default class PermissionsConnectFooter extends Component { static contextTypes = { t: PropTypes.func, - } + }; render() { - const { t } = this.context + const { t } = this.context; return (
    @@ -18,13 +18,13 @@ export default class PermissionsConnectFooter extends Component { global.platform.openTab({ url: 'https://medium.com/metamask/privacy-mode-is-now-enabled-by-default-1c1c957f4d57', - }) + }); }} > {t('learnMore')}
    - ) + ); } } diff --git a/ui/app/components/app/permissions-connect-header/index.js b/ui/app/components/app/permissions-connect-header/index.js index e9de1a06a..eab021bfb 100644 --- a/ui/app/components/app/permissions-connect-header/index.js +++ b/ui/app/components/app/permissions-connect-header/index.js @@ -1 +1 @@ -export { default } from './permissions-connect-header.component' +export { default } from './permissions-connect-header.component'; diff --git a/ui/app/components/app/permissions-connect-header/permissions-connect-header.component.js b/ui/app/components/app/permissions-connect-header/permissions-connect-header.component.js index 0a71d0d61..b0d8920ff 100644 --- a/ui/app/components/app/permissions-connect-header/permissions-connect-header.component.js +++ b/ui/app/components/app/permissions-connect-header/permissions-connect-header.component.js @@ -1,6 +1,6 @@ -import PropTypes from 'prop-types' -import React, { Component } from 'react' -import SiteIcon from '../../ui/site-icon' +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import SiteIcon from '../../ui/site-icon'; export default class PermissionsConnectHeader extends Component { static propTypes = { @@ -9,33 +9,33 @@ export default class PermissionsConnectHeader extends Component { siteOrigin: PropTypes.string.isRequired, headerTitle: PropTypes.node, headerText: PropTypes.string, - } + }; static defaultProps = { icon: null, headerTitle: '', headerText: '', - } + }; renderHeaderIcon() { - const { icon, iconName, siteOrigin } = this.props + const { icon, iconName, siteOrigin } = this.props; return (
    {siteOrigin}
    - ) + ); } render() { - const { headerTitle, headerText } = this.props + const { headerTitle, headerText } = this.props; return (
    {this.renderHeaderIcon()}
    {headerTitle}
    {headerText}
    - ) + ); } } diff --git a/ui/app/components/app/selected-account/index.js b/ui/app/components/app/selected-account/index.js index 7a362f09e..95793e3cc 100644 --- a/ui/app/components/app/selected-account/index.js +++ b/ui/app/components/app/selected-account/index.js @@ -1,3 +1,3 @@ -import SelectedAccount from './selected-account.container' +import SelectedAccount from './selected-account.container'; -export default SelectedAccount +export default SelectedAccount; diff --git a/ui/app/components/app/selected-account/selected-account.component.js b/ui/app/components/app/selected-account/selected-account.component.js index b3b04b5d0..f703678a1 100644 --- a/ui/app/components/app/selected-account/selected-account.component.js +++ b/ui/app/components/app/selected-account/selected-account.component.js @@ -1,38 +1,38 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import copyToClipboard from 'copy-to-clipboard' -import { shortenAddress, checksumAddress } from '../../../helpers/utils/util' +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import copyToClipboard from 'copy-to-clipboard'; +import { shortenAddress, checksumAddress } from '../../../helpers/utils/util'; -import Tooltip from '../../ui/tooltip' +import Tooltip from '../../ui/tooltip'; class SelectedAccount extends Component { state = { copied: false, - } + }; static contextTypes = { t: PropTypes.func, - } + }; static propTypes = { selectedIdentity: PropTypes.object.isRequired, - } + }; componentDidMount() { - this.copyTimeout = null + this.copyTimeout = null; } componentWillUnmount() { if (this.copyTimeout) { - clearTimeout(this.copyTimeout) - this.copyTimeout = null + clearTimeout(this.copyTimeout); + this.copyTimeout = null; } } render() { - const { t } = this.context - const { selectedIdentity } = this.props - const checksummedAddress = checksumAddress(selectedIdentity.address) + const { t } = this.context; + const { selectedIdentity } = this.props; + const checksummedAddress = checksumAddress(selectedIdentity.address); return (
    @@ -46,12 +46,12 @@ class SelectedAccount extends Component {
    - ) + ); } } -export default SelectedAccount +export default SelectedAccount; diff --git a/ui/app/components/app/selected-account/selected-account.container.js b/ui/app/components/app/selected-account/selected-account.container.js index 154bf4311..3e29bd3ec 100644 --- a/ui/app/components/app/selected-account/selected-account.container.js +++ b/ui/app/components/app/selected-account/selected-account.container.js @@ -1,11 +1,11 @@ -import { connect } from 'react-redux' -import { getSelectedIdentity } from '../../../selectors' -import SelectedAccount from './selected-account.component' +import { connect } from 'react-redux'; +import { getSelectedIdentity } from '../../../selectors'; +import SelectedAccount from './selected-account.component'; const mapStateToProps = (state) => { return { selectedIdentity: getSelectedIdentity(state), - } -} + }; +}; -export default connect(mapStateToProps)(SelectedAccount) +export default connect(mapStateToProps)(SelectedAccount); diff --git a/ui/app/components/app/selected-account/tests/selected-account-component.test.js b/ui/app/components/app/selected-account/tests/selected-account-component.test.js index fcb924c25..4cc81396d 100644 --- a/ui/app/components/app/selected-account/tests/selected-account-component.test.js +++ b/ui/app/components/app/selected-account/tests/selected-account-component.test.js @@ -1,7 +1,7 @@ -import assert from 'assert' -import React from 'react' -import { render } from 'enzyme' -import SelectedAccount from '../selected-account.component' +import assert from 'assert'; +import React from 'react'; +import { render } from 'enzyme'; +import SelectedAccount from '../selected-account.component'; describe('SelectedAccount Component', function () { it('should render checksummed address', function () { @@ -13,15 +13,15 @@ describe('SelectedAccount Component', function () { }} />, { context: { t: () => undefined } }, - ) + ); // Checksummed version of address is displayed assert.strictEqual( wrapper.find('.selected-account__address').text(), '0x1B82...5C9D', - ) + ); assert.strictEqual( wrapper.find('.selected-account__name').text(), 'testName', - ) - }) -}) + ); + }); +}); diff --git a/ui/app/components/app/sidebars/index.js b/ui/app/components/app/sidebars/index.js index 732925f69..d5d5026c6 100644 --- a/ui/app/components/app/sidebars/index.js +++ b/ui/app/components/app/sidebars/index.js @@ -1 +1 @@ -export { default } from './sidebar.component' +export { default } from './sidebar.component'; diff --git a/ui/app/components/app/sidebars/sidebar.component.js b/ui/app/components/app/sidebars/sidebar.component.js index 37c1abcd9..7a31f2be4 100644 --- a/ui/app/components/app/sidebars/sidebar.component.js +++ b/ui/app/components/app/sidebars/sidebar.component.js @@ -1,7 +1,7 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import ReactCSSTransitionGroup from 'react-transition-group/CSSTransitionGroup' -import CustomizeGas from '../gas-customization/gas-modal-page-container' +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import ReactCSSTransitionGroup from 'react-transition-group/CSSTransitionGroup'; +import CustomizeGas from '../gas-customization/gas-modal-page-container'; export default class Sidebar extends Component { static propTypes = { @@ -12,45 +12,45 @@ export default class Sidebar extends Component { type: PropTypes.string, sidebarProps: PropTypes.object, onOverlayClose: PropTypes.func, - } + }; renderOverlay() { - const { onOverlayClose } = this.props + const { onOverlayClose } = this.props; return (
    { - onOverlayClose?.() - this.props.hideSidebar() + onOverlayClose?.(); + this.props.hideSidebar(); }} /> - ) + ); } renderSidebarContent() { - const { type, sidebarProps = {} } = this.props - const { transaction = {} } = sidebarProps + const { type, sidebarProps = {} } = this.props; + const { transaction = {} } = sidebarProps; switch (type) { case 'customize-gas': return (
    - ) + ); default: - return null + return null; } } componentDidUpdate(prevProps) { if (!prevProps.sidebarShouldClose && this.props.sidebarShouldClose) { - this.props.hideSidebar() + this.props.hideSidebar(); } } render() { - const { transitionName, sidebarOpen, sidebarShouldClose } = this.props + const { transitionName, sidebarOpen, sidebarShouldClose } = this.props; return (
    @@ -65,6 +65,6 @@ export default class Sidebar extends Component { {sidebarOpen && !sidebarShouldClose ? this.renderOverlay() : null}
    - ) + ); } } diff --git a/ui/app/components/app/sidebars/tests/sidebars-component.test.js b/ui/app/components/app/sidebars/tests/sidebars-component.test.js index 87d9377c0..6ce792716 100644 --- a/ui/app/components/app/sidebars/tests/sidebars-component.test.js +++ b/ui/app/components/app/sidebars/tests/sidebars-component.test.js @@ -1,18 +1,18 @@ -import assert from 'assert' -import React from 'react' -import { shallow } from 'enzyme' -import sinon from 'sinon' -import ReactCSSTransitionGroup from 'react-transition-group/CSSTransitionGroup' -import Sidebar from '../sidebar.component' +import assert from 'assert'; +import React from 'react'; +import { shallow } from 'enzyme'; +import sinon from 'sinon'; +import ReactCSSTransitionGroup from 'react-transition-group/CSSTransitionGroup'; +import Sidebar from '../sidebar.component'; -import CustomizeGas from '../../gas-customization/gas-modal-page-container' +import CustomizeGas from '../../gas-customization/gas-modal-page-container'; const propsMethodSpies = { hideSidebar: sinon.spy(), -} +}; describe('Sidebar Component', function () { - let wrapper + let wrapper; beforeEach(function () { wrapper = shallow( @@ -22,69 +22,71 @@ describe('Sidebar Component', function () { transitionName="someTransition" type="customize-gas" />, - ) - }) + ); + }); afterEach(function () { - propsMethodSpies.hideSidebar.resetHistory() - }) + propsMethodSpies.hideSidebar.resetHistory(); + }); describe('renderOverlay', function () { - let renderOverlay + let renderOverlay; beforeEach(function () { - renderOverlay = shallow(wrapper.instance().renderOverlay()) - }) + renderOverlay = shallow(wrapper.instance().renderOverlay()); + }); it('should render a overlay element', function () { - assert(renderOverlay.hasClass('sidebar-overlay')) - }) + assert(renderOverlay.hasClass('sidebar-overlay')); + }); it('should pass the correct onClick function to the element', function () { - assert.strictEqual(propsMethodSpies.hideSidebar.callCount, 0) - renderOverlay.props().onClick() - assert.strictEqual(propsMethodSpies.hideSidebar.callCount, 1) - }) - }) + assert.strictEqual(propsMethodSpies.hideSidebar.callCount, 0); + renderOverlay.props().onClick(); + assert.strictEqual(propsMethodSpies.hideSidebar.callCount, 1); + }); + }); describe('renderSidebarContent', function () { - let renderSidebarContent + let renderSidebarContent; beforeEach(function () { - renderSidebarContent = wrapper.instance().renderSidebarContent() - }) + renderSidebarContent = wrapper.instance().renderSidebarContent(); + }); it('should render sidebar content with the type customize-gas', function () { - renderSidebarContent = wrapper.instance().renderSidebarContent() - const renderedSidebarContent = shallow(renderSidebarContent) - assert(renderedSidebarContent.hasClass('sidebar-left')) - assert(renderedSidebarContent.childAt(0).is(CustomizeGas)) - }) + renderSidebarContent = wrapper.instance().renderSidebarContent(); + const renderedSidebarContent = shallow(renderSidebarContent); + assert(renderedSidebarContent.hasClass('sidebar-left')); + assert(renderedSidebarContent.childAt(0).is(CustomizeGas)); + }); it('should not render with an unrecognized type', function () { - wrapper.setProps({ type: 'foobar' }) - renderSidebarContent = wrapper.instance().renderSidebarContent() - assert.strictEqual(renderSidebarContent, null) - }) - }) + wrapper.setProps({ type: 'foobar' }); + renderSidebarContent = wrapper.instance().renderSidebarContent(); + assert.strictEqual(renderSidebarContent, null); + }); + }); describe('render', function () { it('should render a div with one child', function () { - assert(wrapper.is('div')) - assert.strictEqual(wrapper.children().length, 1) - }) + assert(wrapper.is('div')); + assert.strictEqual(wrapper.children().length, 1); + }); it('should render the ReactCSSTransitionGroup without any children', function () { - assert(wrapper.children().at(0).is(ReactCSSTransitionGroup)) - assert.strictEqual(wrapper.children().at(0).children().length, 0) - }) + assert(wrapper.children().at(0).is(ReactCSSTransitionGroup)); + assert.strictEqual(wrapper.children().at(0).children().length, 0); + }); it('should render sidebar content and the overlay if sidebarOpen is true', function () { - wrapper.setProps({ sidebarOpen: true }) - assert.strictEqual(wrapper.children().length, 2) - assert(wrapper.children().at(1).hasClass('sidebar-overlay')) - assert.strictEqual(wrapper.children().at(0).children().length, 1) - assert(wrapper.children().at(0).children().at(0).hasClass('sidebar-left')) + wrapper.setProps({ sidebarOpen: true }); + assert.strictEqual(wrapper.children().length, 2); + assert(wrapper.children().at(1).hasClass('sidebar-overlay')); + assert.strictEqual(wrapper.children().at(0).children().length, 1); + assert( + wrapper.children().at(0).children().at(0).hasClass('sidebar-left'), + ); assert( wrapper .children() @@ -94,7 +96,7 @@ describe('Sidebar Component', function () { .children() .at(0) .is(CustomizeGas), - ) - }) - }) -}) + ); + }); + }); +}); diff --git a/ui/app/components/app/signature-request-original/index.js b/ui/app/components/app/signature-request-original/index.js index 00a906785..23d7a6df3 100644 --- a/ui/app/components/app/signature-request-original/index.js +++ b/ui/app/components/app/signature-request-original/index.js @@ -1 +1 @@ -export { default } from './signature-request-original.container' +export { default } from './signature-request-original.container'; diff --git a/ui/app/components/app/signature-request-original/signature-request-original.component.js b/ui/app/components/app/signature-request-original/signature-request-original.component.js index 32f8aafcc..ab7bd6c50 100644 --- a/ui/app/components/app/signature-request-original/signature-request-original.component.js +++ b/ui/app/components/app/signature-request-original/signature-request-original.component.js @@ -1,25 +1,25 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import ethUtil from 'ethereumjs-util' -import classnames from 'classnames' -import { ObjectInspector } from 'react-inspector' +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import ethUtil from 'ethereumjs-util'; +import classnames from 'classnames'; +import { ObjectInspector } from 'react-inspector'; import { ENVIRONMENT_TYPE_NOTIFICATION, MESSAGE_TYPE, -} from '../../../../../shared/constants/app' -import { getEnvironmentType } from '../../../../../app/scripts/lib/util' -import Identicon from '../../ui/identicon' -import AccountListItem from '../account-list-item' -import { conversionUtil } from '../../../helpers/utils/conversion-util' -import Button from '../../ui/button' -import SiteIcon from '../../ui/site-icon' +} from '../../../../../shared/constants/app'; +import { getEnvironmentType } from '../../../../../app/scripts/lib/util'; +import Identicon from '../../ui/identicon'; +import AccountListItem from '../account-list-item'; +import { conversionUtil } from '../../../helpers/utils/conversion-util'; +import Button from '../../ui/button'; +import SiteIcon from '../../ui/site-icon'; export default class SignatureRequestOriginal extends Component { static contextTypes = { t: PropTypes.func.isRequired, metricsEvent: PropTypes.func.isRequired, - } + }; static propTypes = { fromAccount: PropTypes.shape({ @@ -36,41 +36,41 @@ export default class SignatureRequestOriginal extends Component { sign: PropTypes.func.isRequired, txData: PropTypes.object.isRequired, domainMetadata: PropTypes.object, - } + }; state = { fromAccount: this.props.fromAccount, - } + }; componentDidMount = () => { if (getEnvironmentType() === ENVIRONMENT_TYPE_NOTIFICATION) { - window.addEventListener('beforeunload', this._beforeUnload) + window.addEventListener('beforeunload', this._beforeUnload); } - } + }; componentWillUnmount = () => { - this._removeBeforeUnload() - } + this._removeBeforeUnload(); + }; _beforeUnload = (event) => { - const { clearConfirmTransaction, cancel } = this.props - const { metricsEvent } = this.context + const { clearConfirmTransaction, cancel } = this.props; + const { metricsEvent } = this.context; metricsEvent({ eventOpts: { category: 'Transactions', action: 'Sign Request', name: 'Cancel Sig Request Via Notification Close', }, - }) - clearConfirmTransaction() - cancel(event) - } + }); + clearConfirmTransaction(); + cancel(event); + }; _removeBeforeUnload = () => { if (getEnvironmentType() === ENVIRONMENT_TYPE_NOTIFICATION) { - window.removeEventListener('beforeunload', this._beforeUnload) + window.removeEventListener('beforeunload', this._beforeUnload); } - } + }; renderHeader = () => { return ( @@ -85,11 +85,11 @@ export default class SignatureRequestOriginal extends Component {
    - ) - } + ); + }; renderAccount = () => { - const { fromAccount } = this.state + const { fromAccount } = this.state; return (
    @@ -101,14 +101,14 @@ export default class SignatureRequestOriginal extends Component {
    - ) - } + ); + }; renderBalance = () => { - const { conversionRate } = this.props + const { conversionRate } = this.props; const { fromAccount: { balance }, - } = this.state + } = this.state; const balanceInEther = conversionUtil(balance, { fromNumericBase: 'hex', @@ -116,7 +116,7 @@ export default class SignatureRequestOriginal extends Component { fromDenomination: 'WEI', numberOfDecimals: 6, conversionRate, - }) + }); return (
    @@ -127,18 +127,18 @@ export default class SignatureRequestOriginal extends Component { {`${balanceInEther} ETH`}
    - ) - } + ); + }; renderRequestIcon = () => { - const { requesterAddress } = this.props + const { requesterAddress } = this.props; return (
    - ) - } + ); + }; renderAccountInfo = () => { return ( @@ -147,16 +147,16 @@ export default class SignatureRequestOriginal extends Component { {this.renderRequestIcon()} {this.renderBalance()} - ) - } + ); + }; renderOriginInfo = () => { - const { txData, domainMetadata } = this.props - const { t } = this.context + const { txData, domainMetadata } = this.props; + const { t } = this.context; const originMetadata = txData.msgParams.origin ? domainMetadata?.[txData.msgParams.origin] - : null + : null; return (
    @@ -174,21 +174,21 @@ export default class SignatureRequestOriginal extends Component { {txData.msgParams.origin}
    - ) - } + ); + }; msgHexToText = (hex) => { try { - const stripped = ethUtil.stripHexPrefix(hex) - const buff = Buffer.from(stripped, 'hex') - return buff.length === 32 ? hex : buff.toString('utf8') + const stripped = ethUtil.stripHexPrefix(hex); + const buff = Buffer.from(stripped, 'hex'); + return buff.length === 32 ? hex : buff.toString('utf8'); } catch (e) { - return hex + return hex; } - } + }; renderTypedData = (data) => { - const { domain, message } = JSON.parse(data) + const { domain, message } = JSON.parse(data); return (
    {domain ? ( @@ -208,28 +208,28 @@ export default class SignatureRequestOriginal extends Component { '' )}
    - ) - } + ); + }; renderBody = () => { - let rows - let notice = `${this.context.t('youSign')}:` + let rows; + let notice = `${this.context.t('youSign')}:`; - const { txData } = this.props + const { txData } = this.props; const { type, msgParams: { data }, - } = txData + } = txData; if (type === MESSAGE_TYPE.PERSONAL_SIGN) { rows = [ { name: this.context.t('message'), value: this.msgHexToText(data) }, - ] + ]; } else if (type === MESSAGE_TYPE.ETH_SIGN_TYPED_DATA) { - rows = data + rows = data; } else if (type === MESSAGE_TYPE.ETH_SIGN) { - rows = [{ name: this.context.t('message'), value: data }] - notice = this.context.t('signNotice') + rows = [{ name: this.context.t('message'), value: data }]; + notice = this.context.t('signNotice'); } return ( @@ -249,7 +249,7 @@ export default class SignatureRequestOriginal extends Component { global.platform.openTab({ url: 'https://metamask.zendesk.com/hc/en-us/articles/360015488751', - }) + }); }} > {this.context.t('learnMore')} @@ -260,7 +260,7 @@ export default class SignatureRequestOriginal extends Component { {rows.map(({ name, value }, index) => { if (typeof value === 'boolean') { // eslint-disable-next-line no-param-reassign - value = value.toString() + value = value.toString(); } return (
    {`${name}:`}
    {value}
    - ) + ); })} - ) - } + ); + }; renderFooter = () => { const { @@ -284,7 +284,7 @@ export default class SignatureRequestOriginal extends Component { history, mostRecentOverviewPage, sign, - } = this.props + } = this.props; return (
    @@ -293,17 +293,17 @@ export default class SignatureRequestOriginal extends Component { large className="request-signature__footer__cancel-button" onClick={async (event) => { - this._removeBeforeUnload() - await cancel(event) + this._removeBeforeUnload(); + await cancel(event); this.context.metricsEvent({ eventOpts: { category: 'Transactions', action: 'Sign Request', name: 'Cancel', }, - }) - clearConfirmTransaction() - history.push(mostRecentOverviewPage) + }); + clearConfirmTransaction(); + history.push(mostRecentOverviewPage); }} > {this.context.t('cancel')} @@ -314,24 +314,24 @@ export default class SignatureRequestOriginal extends Component { large className="request-signature__footer__sign-button" onClick={async (event) => { - this._removeBeforeUnload() - await sign(event) + this._removeBeforeUnload(); + await sign(event); this.context.metricsEvent({ eventOpts: { category: 'Transactions', action: 'Sign Request', name: 'Confirm', }, - }) - clearConfirmTransaction() - history.push(mostRecentOverviewPage) + }); + clearConfirmTransaction(); + history.push(mostRecentOverviewPage); }} > {this.context.t('sign')}
    - ) - } + ); + }; render = () => { return ( @@ -340,6 +340,6 @@ export default class SignatureRequestOriginal extends Component { {this.renderBody()} {this.renderFooter()} - ) - } + ); + }; } diff --git a/ui/app/components/app/signature-request-original/signature-request-original.container.js b/ui/app/components/app/signature-request-original/signature-request-original.container.js index 90b78b734..c32e30d66 100644 --- a/ui/app/components/app/signature-request-original/signature-request-original.container.js +++ b/ui/app/components/app/signature-request-original/signature-request-original.container.js @@ -1,18 +1,18 @@ -import { connect } from 'react-redux' -import { compose } from 'redux' -import { withRouter } from 'react-router-dom' +import { connect } from 'react-redux'; +import { compose } from 'redux'; +import { withRouter } from 'react-router-dom'; -import { MESSAGE_TYPE } from '../../../../../shared/constants/app' -import { goHome } from '../../../store/actions' +import { MESSAGE_TYPE } from '../../../../../shared/constants/app'; +import { goHome } from '../../../store/actions'; import { accountsWithSendEtherInfoSelector, conversionRateSelector, getDomainMetadata, -} from '../../../selectors' -import { getAccountByAddress } from '../../../helpers/utils/util' -import { clearConfirmTransaction } from '../../../ducks/confirm-transaction/confirm-transaction.duck' -import { getMostRecentOverviewPage } from '../../../ducks/history/history' -import SignatureRequestOriginal from './signature-request-original.component' +} from '../../../selectors'; +import { getAccountByAddress } from '../../../helpers/utils/util'; +import { clearConfirmTransaction } from '../../../ducks/confirm-transaction/confirm-transaction.duck'; +import { getMostRecentOverviewPage } from '../../../ducks/history/history'; +import SignatureRequestOriginal from './signature-request-original.component'; function mapStateToProps(state) { return { @@ -23,14 +23,14 @@ function mapStateToProps(state) { // not passed to component allAccounts: accountsWithSendEtherInfoSelector(state), domainMetadata: getDomainMetadata(state), - } + }; } function mapDispatchToProps(dispatch) { return { goHome: () => dispatch(goHome()), clearConfirmTransaction: () => dispatch(clearConfirmTransaction()), - } + }; } function mergeProps(stateProps, dispatchProps, ownProps) { @@ -42,28 +42,28 @@ function mergeProps(stateProps, dispatchProps, ownProps) { signMessage, cancelMessage, txData, - } = ownProps + } = ownProps; - const { allAccounts, ...otherStateProps } = stateProps + const { allAccounts, ...otherStateProps } = stateProps; const { type, msgParams: { from }, - } = txData + } = txData; - const fromAccount = getAccountByAddress(allAccounts, from) + const fromAccount = getAccountByAddress(allAccounts, from); - let cancel - let sign + let cancel; + let sign; if (type === MESSAGE_TYPE.PERSONAL_SIGN) { - cancel = cancelPersonalMessage - sign = signPersonalMessage + cancel = cancelPersonalMessage; + sign = signPersonalMessage; } else if (type === MESSAGE_TYPE.ETH_SIGN_TYPED_DATA) { - cancel = cancelTypedMessage - sign = signTypedMessage + cancel = cancelTypedMessage; + sign = signTypedMessage; } else if (type === MESSAGE_TYPE.ETH_SIGN) { - cancel = cancelMessage - sign = signMessage + cancel = cancelMessage; + sign = signMessage; } return { @@ -74,10 +74,10 @@ function mergeProps(stateProps, dispatchProps, ownProps) { txData, cancel, sign, - } + }; } export default compose( withRouter, connect(mapStateToProps, mapDispatchToProps, mergeProps), -)(SignatureRequestOriginal) +)(SignatureRequestOriginal); diff --git a/ui/app/components/app/signature-request/index.js b/ui/app/components/app/signature-request/index.js index b1c8a1960..8a01d820e 100644 --- a/ui/app/components/app/signature-request/index.js +++ b/ui/app/components/app/signature-request/index.js @@ -1 +1 @@ -export { default } from './signature-request.container' +export { default } from './signature-request.container'; diff --git a/ui/app/components/app/signature-request/signature-request-footer/index.js b/ui/app/components/app/signature-request/signature-request-footer/index.js index 11d0b3944..2b27bbb66 100644 --- a/ui/app/components/app/signature-request/signature-request-footer/index.js +++ b/ui/app/components/app/signature-request/signature-request-footer/index.js @@ -1 +1 @@ -export { default } from './signature-request-footer.component' +export { default } from './signature-request-footer.component'; diff --git a/ui/app/components/app/signature-request/signature-request-footer/signature-request-footer.component.js b/ui/app/components/app/signature-request/signature-request-footer/signature-request-footer.component.js index 0f925e3e3..c0a08812b 100644 --- a/ui/app/components/app/signature-request/signature-request-footer/signature-request-footer.component.js +++ b/ui/app/components/app/signature-request/signature-request-footer/signature-request-footer.component.js @@ -1,19 +1,19 @@ -import React, { PureComponent } from 'react' -import PropTypes from 'prop-types' -import Button from '../../../ui/button' +import React, { PureComponent } from 'react'; +import PropTypes from 'prop-types'; +import Button from '../../../ui/button'; export default class SignatureRequestFooter extends PureComponent { static propTypes = { cancelAction: PropTypes.func.isRequired, signAction: PropTypes.func.isRequired, - } + }; static contextTypes = { t: PropTypes.func, - } + }; render() { - const { cancelAction, signAction } = this.props + const { cancelAction, signAction } = this.props; return (
    - ) + ); } } diff --git a/ui/app/components/app/signature-request/signature-request-header/index.js b/ui/app/components/app/signature-request/signature-request-header/index.js index fa596383a..b12d0cb73 100644 --- a/ui/app/components/app/signature-request/signature-request-header/index.js +++ b/ui/app/components/app/signature-request/signature-request-header/index.js @@ -1 +1 @@ -export { default } from './signature-request-header.component' +export { default } from './signature-request-header.component'; diff --git a/ui/app/components/app/signature-request/signature-request-header/signature-request-header.component.js b/ui/app/components/app/signature-request/signature-request-header/signature-request-header.component.js index 42468d276..684a3abce 100644 --- a/ui/app/components/app/signature-request/signature-request-header/signature-request-header.component.js +++ b/ui/app/components/app/signature-request/signature-request-header/signature-request-header.component.js @@ -1,15 +1,15 @@ -import React, { PureComponent } from 'react' -import PropTypes from 'prop-types' -import AccountListItem from '../../account-list-item' -import NetworkDisplay from '../../network-display' +import React, { PureComponent } from 'react'; +import PropTypes from 'prop-types'; +import AccountListItem from '../../account-list-item'; +import NetworkDisplay from '../../network-display'; export default class SignatureRequestHeader extends PureComponent { static propTypes = { fromAccount: PropTypes.object, - } + }; render() { - const { fromAccount } = this.props + const { fromAccount } = this.props; return (
    @@ -20,6 +20,6 @@ export default class SignatureRequestHeader extends PureComponent {
    - ) + ); } } diff --git a/ui/app/components/app/signature-request/signature-request-message/index.js b/ui/app/components/app/signature-request/signature-request-message/index.js index e62265a5f..5fe8ddb1c 100644 --- a/ui/app/components/app/signature-request/signature-request-message/index.js +++ b/ui/app/components/app/signature-request/signature-request-message/index.js @@ -1 +1 @@ -export { default } from './signature-request-message.component' +export { default } from './signature-request-message.component'; diff --git a/ui/app/components/app/signature-request/signature-request-message/signature-request-message.component.js b/ui/app/components/app/signature-request/signature-request-message/signature-request-message.component.js index 848f5b38b..7802fd591 100644 --- a/ui/app/components/app/signature-request/signature-request-message/signature-request-message.component.js +++ b/ui/app/components/app/signature-request/signature-request-message/signature-request-message.component.js @@ -1,15 +1,15 @@ -import React, { PureComponent } from 'react' -import PropTypes from 'prop-types' -import classnames from 'classnames' +import React, { PureComponent } from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; export default class SignatureRequestMessage extends PureComponent { static propTypes = { data: PropTypes.object.isRequired, - } + }; static contextTypes = { t: PropTypes.func, - } + }; renderNode(data) { return ( @@ -35,11 +35,11 @@ export default class SignatureRequestMessage extends PureComponent { ))} - ) + ); } render() { - const { data } = this.props + const { data } = this.props; return (
    @@ -53,6 +53,6 @@ export default class SignatureRequestMessage extends PureComponent { {this.renderNode(data)}
    - ) + ); } } diff --git a/ui/app/components/app/signature-request/signature-request.component.js b/ui/app/components/app/signature-request/signature-request.component.js index 712c5e8c2..9515ac02a 100644 --- a/ui/app/components/app/signature-request/signature-request.component.js +++ b/ui/app/components/app/signature-request/signature-request.component.js @@ -1,11 +1,11 @@ -import React, { PureComponent } from 'react' -import PropTypes from 'prop-types' -import { getEnvironmentType } from '../../../../../app/scripts/lib/util' -import Identicon from '../../ui/identicon' -import Header from './signature-request-header' -import Footer from './signature-request-footer' -import Message from './signature-request-message' -import { ENVIRONMENT_TYPE_NOTIFICATION } from './signature-request.constants' +import React, { PureComponent } from 'react'; +import PropTypes from 'prop-types'; +import { getEnvironmentType } from '../../../../../app/scripts/lib/util'; +import Identicon from '../../ui/identicon'; +import Header from './signature-request-header'; +import Footer from './signature-request-footer'; +import Message from './signature-request-message'; +import { ENVIRONMENT_TYPE_NOTIFICATION } from './signature-request.constants'; export default class SignatureRequest extends PureComponent { static propTypes = { @@ -19,16 +19,16 @@ export default class SignatureRequest extends PureComponent { clearConfirmTransaction: PropTypes.func.isRequired, cancel: PropTypes.func.isRequired, sign: PropTypes.func.isRequired, - } + }; static contextTypes = { t: PropTypes.func, metricsEvent: PropTypes.func, - } + }; componentDidMount() { - const { clearConfirmTransaction, cancel } = this.props - const { metricsEvent } = this.context + const { clearConfirmTransaction, cancel } = this.props; + const { metricsEvent } = this.context; if (getEnvironmentType() === ENVIRONMENT_TYPE_NOTIFICATION) { window.addEventListener('beforeunload', (event) => { metricsEvent({ @@ -37,10 +37,10 @@ export default class SignatureRequest extends PureComponent { action: 'Sign Request', name: 'Cancel Sig Request Via Notification Close', }, - }) - clearConfirmTransaction() - cancel(event) - }) + }); + clearConfirmTransaction(); + cancel(event); + }); } } @@ -48,7 +48,7 @@ export default class SignatureRequest extends PureComponent { return `${wallet.slice(0, 8)}...${wallet.slice( wallet.length - 8, wallet.length, - )}` + )}`; } render() { @@ -59,9 +59,9 @@ export default class SignatureRequest extends PureComponent { }, cancel, sign, - } = this.props - const { address: fromAddress } = fromAccount - const { message, domain = {} } = JSON.parse(data) + } = this.props; + const { address: fromAddress } = fromAccount; + const { message, domain = {} } = JSON.parse(data); return (
    @@ -88,6 +88,6 @@ export default class SignatureRequest extends PureComponent {
    - ) + ); } } diff --git a/ui/app/components/app/signature-request/signature-request.constants.js b/ui/app/components/app/signature-request/signature-request.constants.js index 7311a7a18..34ac7b40d 100644 --- a/ui/app/components/app/signature-request/signature-request.constants.js +++ b/ui/app/components/app/signature-request/signature-request.constants.js @@ -1,3 +1,3 @@ -import { ENVIRONMENT_TYPE_NOTIFICATION } from '../../../../../shared/constants/app' +import { ENVIRONMENT_TYPE_NOTIFICATION } from '../../../../../shared/constants/app'; -export { ENVIRONMENT_TYPE_NOTIFICATION } +export { ENVIRONMENT_TYPE_NOTIFICATION }; diff --git a/ui/app/components/app/signature-request/signature-request.container.js b/ui/app/components/app/signature-request/signature-request.container.js index 0c69f1c7a..4c45a256d 100644 --- a/ui/app/components/app/signature-request/signature-request.container.js +++ b/ui/app/components/app/signature-request/signature-request.container.js @@ -1,25 +1,25 @@ -import { connect } from 'react-redux' -import { clearConfirmTransaction } from '../../../ducks/confirm-transaction/confirm-transaction.duck' -import { accountsWithSendEtherInfoSelector } from '../../../selectors' -import { getAccountByAddress } from '../../../helpers/utils/util' -import { MESSAGE_TYPE } from '../../../../../shared/constants/app' -import SignatureRequest from './signature-request.component' +import { connect } from 'react-redux'; +import { clearConfirmTransaction } from '../../../ducks/confirm-transaction/confirm-transaction.duck'; +import { accountsWithSendEtherInfoSelector } from '../../../selectors'; +import { getAccountByAddress } from '../../../helpers/utils/util'; +import { MESSAGE_TYPE } from '../../../../../shared/constants/app'; +import SignatureRequest from './signature-request.component'; function mapStateToProps(state) { return { // not forwarded to component allAccounts: accountsWithSendEtherInfoSelector(state), - } + }; } function mapDispatchToProps(dispatch) { return { clearConfirmTransaction: () => dispatch(clearConfirmTransaction()), - } + }; } function mergeProps(stateProps, dispatchProps, ownProps) { - const { allAccounts } = stateProps + const { allAccounts } = stateProps; const { signPersonalMessage, signTypedMessage, @@ -28,27 +28,27 @@ function mergeProps(stateProps, dispatchProps, ownProps) { signMessage, cancelMessage, txData, - } = ownProps + } = ownProps; const { type, msgParams: { from }, - } = txData + } = txData; - const fromAccount = getAccountByAddress(allAccounts, from) + const fromAccount = getAccountByAddress(allAccounts, from); - let cancel - let sign + let cancel; + let sign; if (type === MESSAGE_TYPE.PERSONAL_SIGN) { - cancel = cancelPersonalMessage - sign = signPersonalMessage + cancel = cancelPersonalMessage; + sign = signPersonalMessage; } else if (type === MESSAGE_TYPE.ETH_SIGN_TYPED_DATA) { - cancel = cancelTypedMessage - sign = signTypedMessage + cancel = cancelTypedMessage; + sign = signTypedMessage; } else if (type === MESSAGE_TYPE.ETH_SIGN) { - cancel = cancelMessage - sign = signMessage + cancel = cancelMessage; + sign = signMessage; } return { @@ -58,11 +58,11 @@ function mergeProps(stateProps, dispatchProps, ownProps) { txData, cancel, sign, - } + }; } export default connect( mapStateToProps, mapDispatchToProps, mergeProps, -)(SignatureRequest) +)(SignatureRequest); diff --git a/ui/app/components/app/signature-request/tests/signature-request.test.js b/ui/app/components/app/signature-request/tests/signature-request.test.js index 8966c014e..261576f16 100644 --- a/ui/app/components/app/signature-request/tests/signature-request.test.js +++ b/ui/app/components/app/signature-request/tests/signature-request.test.js @@ -1,11 +1,11 @@ -import assert from 'assert' -import React from 'react' -import shallow from '../../../../../lib/shallow-with-context' -import SignatureRequest from '../signature-request.component' +import assert from 'assert'; +import React from 'react'; +import shallow from '../../../../../lib/shallow-with-context'; +import SignatureRequest from '../signature-request.component'; describe('Signature Request Component', function () { describe('render', function () { - const fromAddress = '0x123456789abcdef' + const fromAddress = '0x123456789abcdef'; it('should render a div with one child', function () { const wrapper = shallow( , - ) + ); - assert(wrapper.is('div')) - assert.strictEqual(wrapper.length, 1) - assert(wrapper.hasClass('signature-request')) - }) - }) -}) + assert(wrapper.is('div')); + assert.strictEqual(wrapper.length, 1); + assert(wrapper.hasClass('signature-request')); + }); + }); +}); diff --git a/ui/app/components/app/tab-bar/index.js b/ui/app/components/app/tab-bar/index.js index 74f9a7529..07e3c945d 100644 --- a/ui/app/components/app/tab-bar/index.js +++ b/ui/app/components/app/tab-bar/index.js @@ -1 +1 @@ -export { default } from './tab-bar' +export { default } from './tab-bar'; diff --git a/ui/app/components/app/tab-bar/tab-bar.js b/ui/app/components/app/tab-bar/tab-bar.js index e4f38feac..51cefb8a7 100644 --- a/ui/app/components/app/tab-bar/tab-bar.js +++ b/ui/app/components/app/tab-bar/tab-bar.js @@ -1,9 +1,9 @@ -import React from 'react' -import PropTypes from 'prop-types' -import classnames from 'classnames' +import React from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; const TabBar = (props) => { - const { tabs = [], onSelect, isActive } = props + const { tabs = [], onSelect, isActive } = props; return (
    @@ -25,13 +25,13 @@ const TabBar = (props) => { ))}
    - ) -} + ); +}; TabBar.propTypes = { isActive: PropTypes.func.isRequired, tabs: PropTypes.array, onSelect: PropTypes.func, -} +}; -export default TabBar +export default TabBar; diff --git a/ui/app/components/app/tests/signature-request.test.js b/ui/app/components/app/tests/signature-request.test.js index f95bed3af..700b99a91 100644 --- a/ui/app/components/app/tests/signature-request.test.js +++ b/ui/app/components/app/tests/signature-request.test.js @@ -1,13 +1,13 @@ -import assert from 'assert' -import React from 'react' -import { Provider } from 'react-redux' -import sinon from 'sinon' -import configureMockStore from 'redux-mock-store' -import { mountWithRouter } from '../../../../../test/lib/render-helpers' -import SignatureRequest from '../signature-request' +import assert from 'assert'; +import React from 'react'; +import { Provider } from 'react-redux'; +import sinon from 'sinon'; +import configureMockStore from 'redux-mock-store'; +import { mountWithRouter } from '../../../../../test/lib/render-helpers'; +import SignatureRequest from '../signature-request'; describe('Signature Request', function () { - let wrapper + let wrapper; const mockStore = { metamask: { @@ -23,8 +23,8 @@ describe('Signature Request', function () { cachedBalances: {}, selectedAddress: '0xd8f6a2ffb0fc5952d16c9768b71cfd35b6399aa5', }, - } - const store = configureMockStore()(mockStore) + }; + const store = configureMockStore()(mockStore); const props = { fromAccount: { @@ -49,7 +49,7 @@ describe('Signature Request', function () { time: 1, type: 'eth_sign', }, - } + }; beforeEach(function () { wrapper = mountWithRouter( @@ -57,24 +57,24 @@ describe('Signature Request', function () { , store, - ) - }) + ); + }); afterEach(function () { - props.clearConfirmTransaction.resetHistory() - }) + props.clearConfirmTransaction.resetHistory(); + }); it('cancel', function () { - const cancelButton = wrapper.find('button.btn-default') - cancelButton.simulate('click') + const cancelButton = wrapper.find('button.btn-default'); + cancelButton.simulate('click'); - assert(props.cancel.calledOnce) - }) + assert(props.cancel.calledOnce); + }); it('sign', function () { - const signButton = wrapper.find('button.btn-primary') - signButton.simulate('click') + const signButton = wrapper.find('button.btn-primary'); + signButton.simulate('click'); - assert(props.sign.calledOnce) - }) -}) + assert(props.sign.calledOnce); + }); +}); diff --git a/ui/app/components/app/token-cell/index.js b/ui/app/components/app/token-cell/index.js index c33e36adb..3d871c9a8 100644 --- a/ui/app/components/app/token-cell/index.js +++ b/ui/app/components/app/token-cell/index.js @@ -1 +1 @@ -export { default } from './token-cell' +export { default } from './token-cell'; diff --git a/ui/app/components/app/token-cell/token-cell.js b/ui/app/components/app/token-cell/token-cell.js index 9c3a4bcff..777e9b560 100644 --- a/ui/app/components/app/token-cell/token-cell.js +++ b/ui/app/components/app/token-cell/token-cell.js @@ -1,11 +1,11 @@ -import classnames from 'classnames' -import PropTypes from 'prop-types' -import React from 'react' -import { useSelector } from 'react-redux' -import AssetListItem from '../asset-list-item' -import { getSelectedAddress } from '../../../selectors' -import { useI18nContext } from '../../../hooks/useI18nContext' -import { useTokenFiatAmount } from '../../../hooks/useTokenFiatAmount' +import classnames from 'classnames'; +import PropTypes from 'prop-types'; +import React from 'react'; +import { useSelector } from 'react-redux'; +import AssetListItem from '../asset-list-item'; +import { getSelectedAddress } from '../../../selectors'; +import { useI18nContext } from '../../../hooks/useI18nContext'; +import { useTokenFiatAmount } from '../../../hooks/useTokenFiatAmount'; export default function TokenCell({ address, @@ -16,10 +16,10 @@ export default function TokenCell({ image, onClick, }) { - const userAddress = useSelector(getSelectedAddress) - const t = useI18nContext() + const userAddress = useSelector(getSelectedAddress); + const t = useI18nContext(); - const formattedFiat = useTokenFiatAmount(address, string, symbol) + const formattedFiat = useTokenFiatAmount(address, string, symbol); const warning = balanceError ? ( @@ -34,7 +34,7 @@ export default function TokenCell({ {t('here')} - ) : null + ) : null; return ( - ) + ); } TokenCell.propTypes = { @@ -62,8 +62,8 @@ TokenCell.propTypes = { string: PropTypes.string, image: PropTypes.string, onClick: PropTypes.func.isRequired, -} +}; TokenCell.defaultProps = { balanceError: null, -} +}; diff --git a/ui/app/components/app/token-cell/token-cell.test.js b/ui/app/components/app/token-cell/token-cell.test.js index 08b4e545d..677102418 100644 --- a/ui/app/components/app/token-cell/token-cell.test.js +++ b/ui/app/components/app/token-cell/token-cell.test.js @@ -1,17 +1,17 @@ -import assert from 'assert' -import React from 'react' -import thunk from 'redux-thunk' -import { Provider } from 'react-redux' -import configureMockStore from 'redux-mock-store' -import { mount } from 'enzyme' -import sinon from 'sinon' -import { MemoryRouter } from 'react-router-dom' +import assert from 'assert'; +import React from 'react'; +import thunk from 'redux-thunk'; +import { Provider } from 'react-redux'; +import configureMockStore from 'redux-mock-store'; +import { mount } from 'enzyme'; +import sinon from 'sinon'; +import { MemoryRouter } from 'react-router-dom'; -import Identicon from '../../ui/identicon' -import TokenCell from '.' +import Identicon from '../../ui/identicon'; +import TokenCell from '.'; describe('Token Cell', function () { - let wrapper + let wrapper; const state = { metamask: { @@ -33,16 +33,16 @@ describe('Token Cell', function () { isOpen: true, }, }, - } + }; - const middlewares = [thunk] - const mockStore = configureMockStore(middlewares) - const store = mockStore(state) + const middlewares = [thunk]; + const mockStore = configureMockStore(middlewares); + const store = mockStore(state); - let onClick + let onClick; beforeEach(function () { - onClick = sinon.stub() + onClick = sinon.stub(); wrapper = mount( @@ -56,45 +56,45 @@ describe('Token Cell', function () { /> , - ) - }) + ); + }); afterEach(function () { - sinon.restore() - }) + sinon.restore(); + }); it('renders Identicon with props from token cell', function () { assert.strictEqual( wrapper.find(Identicon).prop('address'), '0xAnotherToken', - ) - assert.strictEqual(wrapper.find(Identicon).prop('image'), './test-image') - }) + ); + assert.strictEqual(wrapper.find(Identicon).prop('image'), './test-image'); + }); it('renders token balance', function () { assert.strictEqual( wrapper.find('.asset-list-item__token-value').text(), '5.000', - ) - }) + ); + }); it('renders token symbol', function () { assert.strictEqual( wrapper.find('.asset-list-item__token-symbol').text(), 'TEST', - ) - }) + ); + }); it('renders converted fiat amount', function () { assert.strictEqual( wrapper.find('.list-item__subheading').text(), '$0.52 USD', - ) - }) + ); + }); it('calls onClick when clicked', function () { - assert.ok(!onClick.called) - wrapper.simulate('click') - assert.ok(onClick.called) - }) -}) + assert.ok(!onClick.called); + wrapper.simulate('click'); + assert.ok(onClick.called); + }); +}); diff --git a/ui/app/components/app/token-list/index.js b/ui/app/components/app/token-list/index.js index 613fc9668..b07c45d74 100644 --- a/ui/app/components/app/token-list/index.js +++ b/ui/app/components/app/token-list/index.js @@ -1 +1 @@ -export { default } from './token-list' +export { default } from './token-list'; diff --git a/ui/app/components/app/token-list/token-list.js b/ui/app/components/app/token-list/token-list.js index f01726dc4..298dda081 100644 --- a/ui/app/components/app/token-list/token-list.js +++ b/ui/app/components/app/token-list/token-list.js @@ -1,22 +1,22 @@ -import React from 'react' -import PropTypes from 'prop-types' -import { isEqual } from 'lodash' +import React from 'react'; +import PropTypes from 'prop-types'; +import { isEqual } from 'lodash'; -import { useSelector } from 'react-redux' -import TokenCell from '../token-cell' -import { useI18nContext } from '../../../hooks/useI18nContext' -import { useTokenTracker } from '../../../hooks/useTokenTracker' -import { getAssetImages } from '../../../selectors' -import { getTokens } from '../../../ducks/metamask/metamask' +import { useSelector } from 'react-redux'; +import TokenCell from '../token-cell'; +import { useI18nContext } from '../../../hooks/useI18nContext'; +import { useTokenTracker } from '../../../hooks/useTokenTracker'; +import { getAssetImages } from '../../../selectors'; +import { getTokens } from '../../../ducks/metamask/metamask'; export default function TokenList({ onTokenClick }) { - const t = useI18nContext() - const assetImages = useSelector(getAssetImages) + const t = useI18nContext(); + const assetImages = useSelector(getAssetImages); // use `isEqual` comparison function because the token array is serialized // from the background so it has a new reference with each background update, // even if the tokens haven't changed - const tokens = useSelector(getTokens, isEqual) - const { loading, tokensWithBalances } = useTokenTracker(tokens, true) + const tokens = useSelector(getTokens, isEqual); + const { loading, tokensWithBalances } = useTokenTracker(tokens, true); if (loading) { return ( @@ -31,19 +31,19 @@ export default function TokenList({ onTokenClick }) { > {t('loadingTokens')} - ) + ); } return (
    {tokensWithBalances.map((tokenData, index) => { - tokenData.image = assetImages[tokenData.address] - return + tokenData.image = assetImages[tokenData.address]; + return ; })}
    - ) + ); } TokenList.propTypes = { onTokenClick: PropTypes.func.isRequired, -} +}; diff --git a/ui/app/components/app/transaction-activity-log/index.js b/ui/app/components/app/transaction-activity-log/index.js index a33da15a3..c9e02fc86 100644 --- a/ui/app/components/app/transaction-activity-log/index.js +++ b/ui/app/components/app/transaction-activity-log/index.js @@ -1 +1 @@ -export { default } from './transaction-activity-log.container' +export { default } from './transaction-activity-log.container'; diff --git a/ui/app/components/app/transaction-activity-log/tests/transaction-activity-log.component.test.js b/ui/app/components/app/transaction-activity-log/tests/transaction-activity-log.component.test.js index d07f98764..149ebd4c4 100644 --- a/ui/app/components/app/transaction-activity-log/tests/transaction-activity-log.component.test.js +++ b/ui/app/components/app/transaction-activity-log/tests/transaction-activity-log.component.test.js @@ -1,7 +1,7 @@ -import assert from 'assert' -import React from 'react' -import { shallow } from 'enzyme' -import TransactionActivityLog from '../transaction-activity-log.component' +import assert from 'assert'; +import React from 'react'; +import { shallow } from 'enzyme'; +import TransactionActivityLog from '../transaction-activity-log.component'; describe('TransactionActivityLog Component', function () { it('should render properly', function () { @@ -38,7 +38,7 @@ describe('TransactionActivityLog Component', function () { timestamp: 1543958029960, value: '0x1502634b5800', }, - ] + ]; const wrapper = shallow( , { context: { t: (str1, str2) => (str2 ? str1 + str2 : str1) } }, - ) + ); - assert.ok(wrapper.hasClass('transaction-activity-log')) - assert.ok(wrapper.hasClass('test-class')) - }) + assert.ok(wrapper.hasClass('transaction-activity-log')); + assert.ok(wrapper.hasClass('test-class')); + }); it('should render inline retry and cancel buttons for earliest pending transaction', function () { const activities = [ @@ -90,7 +90,7 @@ describe('TransactionActivityLog Component', function () { timestamp: 4, value: '0x1', }, - ] + ]; const wrapper = shallow( , { context: { t: (str1, str2) => (str2 ? str1 + str2 : str1) } }, - ) + ); - assert.ok(wrapper.hasClass('transaction-activity-log')) - assert.ok(wrapper.hasClass('test-class')) + assert.ok(wrapper.hasClass('transaction-activity-log')); + assert.ok(wrapper.hasClass('test-class')); assert.strictEqual( wrapper.find('.transaction-activity-log__action-link').length, 2, - ) - }) + ); + }); it('should not render inline retry and cancel buttons for newer pending transactions', function () { const activities = [ @@ -147,7 +147,7 @@ describe('TransactionActivityLog Component', function () { timestamp: 4, value: '0x1', }, - ] + ]; const wrapper = shallow( , { context: { t: (str1, str2) => (str2 ? str1 + str2 : str1) } }, - ) + ); - assert.ok(wrapper.hasClass('transaction-activity-log')) - assert.ok(wrapper.hasClass('test-class')) + assert.ok(wrapper.hasClass('transaction-activity-log')); + assert.ok(wrapper.hasClass('test-class')); assert.strictEqual( wrapper.find('.transaction-activity-log__action-link').length, 0, - ) - }) -}) + ); + }); +}); diff --git a/ui/app/components/app/transaction-activity-log/tests/transaction-activity-log.container.test.js b/ui/app/components/app/transaction-activity-log/tests/transaction-activity-log.container.test.js index f54f2ce94..b1608684c 100644 --- a/ui/app/components/app/transaction-activity-log/tests/transaction-activity-log.container.test.js +++ b/ui/app/components/app/transaction-activity-log/tests/transaction-activity-log.container.test.js @@ -1,16 +1,16 @@ -import assert from 'assert' -import proxyquire from 'proxyquire' +import assert from 'assert'; +import proxyquire from 'proxyquire'; -let mapStateToProps +let mapStateToProps; proxyquire('../transaction-activity-log.container.js', { 'react-redux': { connect: (ms) => { - mapStateToProps = ms - return () => ({}) + mapStateToProps = ms; + return () => ({}); }, }, -}) +}); describe('TransactionActivityLog container', function () { describe('mapStateToProps()', function () { @@ -20,12 +20,12 @@ describe('TransactionActivityLog container', function () { conversionRate: 280.45, nativeCurrency: 'ETH', }, - } + }; assert.deepStrictEqual(mapStateToProps(mockState), { conversionRate: 280.45, nativeCurrency: 'ETH', - }) - }) - }) -}) + }); + }); + }); +}); diff --git a/ui/app/components/app/transaction-activity-log/tests/transaction-activity-log.util.test.js b/ui/app/components/app/transaction-activity-log/tests/transaction-activity-log.util.test.js index 8b03326db..e01a5a9de 100644 --- a/ui/app/components/app/transaction-activity-log/tests/transaction-activity-log.util.test.js +++ b/ui/app/components/app/transaction-activity-log/tests/transaction-activity-log.util.test.js @@ -1,18 +1,18 @@ -import assert from 'assert' +import assert from 'assert'; import { TRANSACTION_STATUSES, TRANSACTION_TYPES, -} from '../../../../../../shared/constants/transaction' +} from '../../../../../../shared/constants/transaction'; import { combineTransactionHistories, getActivities, -} from '../transaction-activity-log.util' +} from '../transaction-activity-log.util'; describe('TransactionActivityLog utils', function () { describe('combineTransactionHistories', function () { it('should return no activities for an empty list of transactions', function () { - assert.deepStrictEqual(combineTransactionHistories([]), []) - }) + assert.deepStrictEqual(combineTransactionHistories([]), []); + }); it('should return activities for an array of transactions', function () { const transactions = [ @@ -180,7 +180,7 @@ describe('TransactionActivityLog utils', function () { }, type: TRANSACTION_TYPES.RETRY, }, - ] + ]; const expected = [ { @@ -215,14 +215,14 @@ describe('TransactionActivityLog utils', function () { timestamp: 1543958897165, value: '0x171c3a061400', }, - ] + ]; assert.deepStrictEqual( combineTransactionHistories(transactions), expected, - ) - }) - }) + ); + }); + }); describe('getActivities', function () { it('should return no activities for an empty history', function () { @@ -238,10 +238,10 @@ describe('TransactionActivityLog utils', function () { to: '0x2', value: '0x2386f26fc10000', }, - } + }; - assert.deepStrictEqual(getActivities(transaction), []) - }) + assert.deepStrictEqual(getActivities(transaction), []); + }); it("should return activities for a transaction's history", function () { const transaction = { @@ -389,7 +389,7 @@ describe('TransactionActivityLog utils', function () { value: '0x2386f26fc10000', }, hash: '0xabc', - } + }; const expectedResult = [ { @@ -413,9 +413,9 @@ describe('TransactionActivityLog utils', function () { id: 1, hash: '0xabc', }, - ] + ]; - assert.deepStrictEqual(getActivities(transaction, true), expectedResult) - }) - }) -}) + assert.deepStrictEqual(getActivities(transaction, true), expectedResult); + }); + }); +}); diff --git a/ui/app/components/app/transaction-activity-log/transaction-activity-log-icon/index.js b/ui/app/components/app/transaction-activity-log/transaction-activity-log-icon/index.js index 86b12360a..7d36bdef9 100644 --- a/ui/app/components/app/transaction-activity-log/transaction-activity-log-icon/index.js +++ b/ui/app/components/app/transaction-activity-log/transaction-activity-log-icon/index.js @@ -1 +1 @@ -export { default } from './transaction-activity-log-icon.component' +export { default } from './transaction-activity-log-icon.component'; diff --git a/ui/app/components/app/transaction-activity-log/transaction-activity-log-icon/transaction-activity-log-icon.component.js b/ui/app/components/app/transaction-activity-log/transaction-activity-log-icon/transaction-activity-log-icon.component.js index f00b493e1..9e1c91355 100644 --- a/ui/app/components/app/transaction-activity-log/transaction-activity-log-icon/transaction-activity-log-icon.component.js +++ b/ui/app/components/app/transaction-activity-log/transaction-activity-log-icon/transaction-activity-log-icon.component.js @@ -1,6 +1,6 @@ -import React, { PureComponent } from 'react' -import PropTypes from 'prop-types' -import classnames from 'classnames' +import React, { PureComponent } from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; import { TRANSACTION_CREATED_EVENT, @@ -11,7 +11,7 @@ import { TRANSACTION_ERRORED_EVENT, TRANSACTION_CANCEL_ATTEMPTED_EVENT, TRANSACTION_CANCEL_SUCCESS_EVENT, -} from '../transaction-activity-log.constants' +} from '../transaction-activity-log.constants'; const imageHash = { [TRANSACTION_CREATED_EVENT]: '/images/icons/new.svg', @@ -22,26 +22,26 @@ const imageHash = { [TRANSACTION_ERRORED_EVENT]: '/images/icons/error.svg', [TRANSACTION_CANCEL_ATTEMPTED_EVENT]: '/images/icons/cancelled.svg', [TRANSACTION_CANCEL_SUCCESS_EVENT]: '/images/icons/cancelled.svg', -} +}; export default class TransactionActivityLogIcon extends PureComponent { static contextTypes = { t: PropTypes.func, - } + }; static propTypes = { className: PropTypes.string, eventKey: PropTypes.oneOf(Object.keys(imageHash)), - } + }; render() { - const { className, eventKey } = this.props - const imagePath = imageHash[eventKey] + const { className, eventKey } = this.props; + const imagePath = imageHash[eventKey]; return (
    {imagePath && }
    - ) + ); } } diff --git a/ui/app/components/app/transaction-activity-log/transaction-activity-log.component.js b/ui/app/components/app/transaction-activity-log/transaction-activity-log.component.js index 9320a1ac2..ef38504c0 100644 --- a/ui/app/components/app/transaction-activity-log/transaction-activity-log.component.js +++ b/ui/app/components/app/transaction-activity-log/transaction-activity-log.component.js @@ -1,20 +1,20 @@ -import React, { PureComponent } from 'react' -import PropTypes from 'prop-types' -import classnames from 'classnames' +import React, { PureComponent } from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; import { getEthConversionFromWeiHex, getValueFromWeiHex, -} from '../../../helpers/utils/conversions.util' -import { formatDate } from '../../../helpers/utils/util' -import { getEtherscanNetworkPrefix } from '../../../../lib/etherscan-prefix-for-network' -import TransactionActivityLogIcon from './transaction-activity-log-icon' -import { CONFIRMED_STATUS } from './transaction-activity-log.constants' +} from '../../../helpers/utils/conversions.util'; +import { formatDate } from '../../../helpers/utils/util'; +import { getEtherscanNetworkPrefix } from '../../../../lib/etherscan-prefix-for-network'; +import TransactionActivityLogIcon from './transaction-activity-log-icon'; +import { CONFIRMED_STATUS } from './transaction-activity-log.constants'; export default class TransactionActivityLog extends PureComponent { static contextTypes = { t: PropTypes.func, metricEvent: PropTypes.func, - } + }; static propTypes = { activities: PropTypes.array, @@ -27,27 +27,27 @@ export default class TransactionActivityLog extends PureComponent { onRetry: PropTypes.func, primaryTransaction: PropTypes.object, isEarliestNonce: PropTypes.bool, - } + }; handleActivityClick = (hash) => { - const { primaryTransaction } = this.props - const { metamaskNetworkId } = primaryTransaction + const { primaryTransaction } = this.props; + const { metamaskNetworkId } = primaryTransaction; - const prefix = getEtherscanNetworkPrefix(metamaskNetworkId) - const etherscanUrl = `https://${prefix}etherscan.io/tx/${hash}` + const prefix = getEtherscanNetworkPrefix(metamaskNetworkId); + const etherscanUrl = `https://${prefix}etherscan.io/tx/${hash}`; - global.platform.openTab({ url: etherscanUrl }) - } + global.platform.openTab({ url: etherscanUrl }); + }; renderInlineRetry(index) { - const { t } = this.context + const { t } = this.context; const { inlineRetryIndex, primaryTransaction = {}, onRetry, isEarliestNonce, - } = this.props - const { status } = primaryTransaction + } = this.props; + const { status } = primaryTransaction; return isEarliestNonce && status !== CONFIRMED_STATUS && @@ -55,18 +55,18 @@ export default class TransactionActivityLog extends PureComponent {
    {t('speedUpTransaction')}
    - ) : null + ) : null; } renderInlineCancel(index) { - const { t } = this.context + const { t } = this.context; const { inlineCancelIndex, primaryTransaction = {}, onCancel, isEarliestNonce, - } = this.props - const { status } = primaryTransaction + } = this.props; + const { status } = primaryTransaction; return isEarliestNonce && status !== CONFIRMED_STATUS && @@ -74,12 +74,12 @@ export default class TransactionActivityLog extends PureComponent {
    {t('speedUpCancellation')}
    - ) : null + ) : null; } renderActivity(activity, index) { - const { conversionRate, nativeCurrency } = this.props - const { eventKey, value, timestamp, hash } = activity + const { conversionRate, nativeCurrency } = this.props; + const { eventKey, value, timestamp, hash } = activity; const ethValue = index === 0 ? `${getValueFromWeiHex({ @@ -94,12 +94,12 @@ export default class TransactionActivityLog extends PureComponent { fromCurrency: 'ETH', conversionRate, numberOfDecimals: 3, - }) - const formattedTimestamp = formatDate(timestamp, "T 'on' M/d/y") + }); + const formattedTimestamp = formatDate(timestamp, "T 'on' M/d/y"); const activityText = this.context.t(eventKey, [ ethValue, formattedTimestamp, - ]) + ]); return (
    @@ -119,15 +119,15 @@ export default class TransactionActivityLog extends PureComponent { {this.renderInlineCancel(index)}
    - ) + ); } render() { - const { t } = this.context - const { className, activities } = this.props + const { t } = this.context; + const { className, activities } = this.props; if (activities.length === 0) { - return null + return null; } return ( @@ -141,6 +141,6 @@ export default class TransactionActivityLog extends PureComponent { )} - ) + ); } } diff --git a/ui/app/components/app/transaction-activity-log/transaction-activity-log.constants.js b/ui/app/components/app/transaction-activity-log/transaction-activity-log.constants.js index 72e63d85c..367eae150 100644 --- a/ui/app/components/app/transaction-activity-log/transaction-activity-log.constants.js +++ b/ui/app/components/app/transaction-activity-log/transaction-activity-log.constants.js @@ -1,13 +1,13 @@ -export const TRANSACTION_CREATED_EVENT = 'transactionCreated' -export const TRANSACTION_SUBMITTED_EVENT = 'transactionSubmitted' -export const TRANSACTION_RESUBMITTED_EVENT = 'transactionResubmitted' -export const TRANSACTION_CONFIRMED_EVENT = 'transactionConfirmed' -export const TRANSACTION_DROPPED_EVENT = 'transactionDropped' -export const TRANSACTION_UPDATED_EVENT = 'transactionUpdated' -export const TRANSACTION_ERRORED_EVENT = 'transactionErrored' -export const TRANSACTION_CANCEL_ATTEMPTED_EVENT = 'transactionCancelAttempted' -export const TRANSACTION_CANCEL_SUCCESS_EVENT = 'transactionCancelSuccess' +export const TRANSACTION_CREATED_EVENT = 'transactionCreated'; +export const TRANSACTION_SUBMITTED_EVENT = 'transactionSubmitted'; +export const TRANSACTION_RESUBMITTED_EVENT = 'transactionResubmitted'; +export const TRANSACTION_CONFIRMED_EVENT = 'transactionConfirmed'; +export const TRANSACTION_DROPPED_EVENT = 'transactionDropped'; +export const TRANSACTION_UPDATED_EVENT = 'transactionUpdated'; +export const TRANSACTION_ERRORED_EVENT = 'transactionErrored'; +export const TRANSACTION_CANCEL_ATTEMPTED_EVENT = 'transactionCancelAttempted'; +export const TRANSACTION_CANCEL_SUCCESS_EVENT = 'transactionCancelSuccess'; -export const SUBMITTED_STATUS = 'submitted' -export const CONFIRMED_STATUS = 'confirmed' -export const DROPPED_STATUS = 'dropped' +export const SUBMITTED_STATUS = 'submitted'; +export const CONFIRMED_STATUS = 'confirmed'; +export const DROPPED_STATUS = 'dropped'; diff --git a/ui/app/components/app/transaction-activity-log/transaction-activity-log.container.js b/ui/app/components/app/transaction-activity-log/transaction-activity-log.container.js index 07339193d..bea5e6f7a 100644 --- a/ui/app/components/app/transaction-activity-log/transaction-activity-log.container.js +++ b/ui/app/components/app/transaction-activity-log/transaction-activity-log.container.js @@ -1,38 +1,38 @@ -import { connect } from 'react-redux' -import { findLastIndex } from 'lodash' -import { conversionRateSelector, getNativeCurrency } from '../../../selectors' -import TransactionActivityLog from './transaction-activity-log.component' -import { combineTransactionHistories } from './transaction-activity-log.util' +import { connect } from 'react-redux'; +import { findLastIndex } from 'lodash'; +import { conversionRateSelector, getNativeCurrency } from '../../../selectors'; +import TransactionActivityLog from './transaction-activity-log.component'; +import { combineTransactionHistories } from './transaction-activity-log.util'; import { TRANSACTION_RESUBMITTED_EVENT, TRANSACTION_CANCEL_ATTEMPTED_EVENT, -} from './transaction-activity-log.constants' +} from './transaction-activity-log.constants'; const matchesEventKey = (matchEventKey) => ({ eventKey }) => - eventKey === matchEventKey + eventKey === matchEventKey; const mapStateToProps = (state) => { return { conversionRate: conversionRateSelector(state), nativeCurrency: getNativeCurrency(state), - } -} + }; +}; const mergeProps = (stateProps, dispatchProps, ownProps) => { const { transactionGroup: { transactions = [], primaryTransaction } = {}, ...restOwnProps - } = ownProps + } = ownProps; - const activities = combineTransactionHistories(transactions) + const activities = combineTransactionHistories(transactions); const inlineRetryIndex = findLastIndex( activities, matchesEventKey(TRANSACTION_RESUBMITTED_EVENT), - ) + ); const inlineCancelIndex = findLastIndex( activities, matchesEventKey(TRANSACTION_CANCEL_ATTEMPTED_EVENT), - ) + ); return { ...stateProps, @@ -42,11 +42,11 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => { inlineRetryIndex, inlineCancelIndex, primaryTransaction, - } -} + }; +}; export default connect( mapStateToProps, null, mergeProps, -)(TransactionActivityLog) +)(TransactionActivityLog); diff --git a/ui/app/components/app/transaction-activity-log/transaction-activity-log.util.js b/ui/app/components/app/transaction-activity-log/transaction-activity-log.util.js index 8b7b7ba24..0846b85bc 100644 --- a/ui/app/components/app/transaction-activity-log/transaction-activity-log.util.js +++ b/ui/app/components/app/transaction-activity-log/transaction-activity-log.util.js @@ -1,5 +1,5 @@ -import { TRANSACTION_TYPES } from '../../../../../shared/constants/transaction' -import { getHexGasTotal } from '../../../helpers/utils/confirm-tx.util' +import { TRANSACTION_TYPES } from '../../../../../shared/constants/transaction'; +import { getHexGasTotal } from '../../../helpers/utils/confirm-tx.util'; import { // event constants @@ -16,27 +16,27 @@ import { SUBMITTED_STATUS, CONFIRMED_STATUS, DROPPED_STATUS, -} from './transaction-activity-log.constants' +} from './transaction-activity-log.constants'; // path constants -const STATUS_PATH = '/status' -const GAS_PRICE_PATH = '/txParams/gasPrice' -const GAS_LIMIT_PATH = '/txParams/gas' +const STATUS_PATH = '/status'; +const GAS_PRICE_PATH = '/txParams/gasPrice'; +const GAS_LIMIT_PATH = '/txParams/gas'; // op constants -const REPLACE_OP = 'replace' +const REPLACE_OP = 'replace'; const eventPathsHash = { [STATUS_PATH]: true, [GAS_PRICE_PATH]: true, [GAS_LIMIT_PATH]: true, -} +}; const statusHash = { [SUBMITTED_STATUS]: TRANSACTION_SUBMITTED_EVENT, [CONFIRMED_STATUS]: TRANSACTION_CONFIRMED_EVENT, [DROPPED_STATUS]: TRANSACTION_DROPPED_EVENT, -} +}; /** * @name getActivities @@ -54,10 +54,10 @@ export function getActivities(transaction, isFirstTransaction = false) { txParams: { gas: paramsGasLimit, gasPrice: paramsGasPrice }, xReceipt: { status } = {}, type, - } = transaction + } = transaction; - let cachedGasLimit = '0x0' - let cachedGasPrice = '0x0' + let cachedGasLimit = '0x0'; + let cachedGasPrice = '0x0'; const historyActivities = history.reduce((acc, base, index) => { // First history item should be transaction creation @@ -65,12 +65,12 @@ export function getActivities(transaction, isFirstTransaction = false) { const { time: timestamp, txParams: { value, gas = '0x0', gasPrice = '0x0' } = {}, - } = base + } = base; // The cached gas limit and gas price are used to display the gas fee in the activity log. We // need to cache these values because the status update history events don't provide us with // the latest gas limit and gas price. - cachedGasLimit = gas - cachedGasPrice = gasPrice + cachedGasLimit = gas; + cachedGasPrice = gasPrice; if (isFirstTransaction) { return acc.concat({ @@ -79,17 +79,17 @@ export function getActivities(transaction, isFirstTransaction = false) { eventKey: TRANSACTION_CREATED_EVENT, timestamp, value, - }) + }); } // An entry in the history may be an array of more sub-entries. } else if (Array.isArray(base)) { - const events = [] + const events = []; base.forEach((entry) => { - const { op, path, value, timestamp: entryTimestamp } = entry + const { op, path, value, timestamp: entryTimestamp } = entry; // Not all sub-entries in a history entry have a timestamp. If the sub-entry does not have a // timestamp, the first sub-entry in a history entry should. - const timestamp = entryTimestamp || (base[0] && base[0].timestamp) + const timestamp = entryTimestamp || (base[0] && base[0].timestamp); if (path in eventPathsHash && op === REPLACE_OP) { switch (path) { @@ -103,22 +103,22 @@ export function getActivities(transaction, isFirstTransaction = false) { : getHexGasTotal({ gasLimit: cachedGasLimit, gasPrice: cachedGasPrice, - }) + }); if (value in statusHash) { - let eventKey = statusHash[value] + let eventKey = statusHash[value]; // If the status is 'submitted', we need to determine whether the event is a // transaction retry or a cancellation attempt. if (value === SUBMITTED_STATUS) { if (type === TRANSACTION_TYPES.RETRY) { - eventKey = TRANSACTION_RESUBMITTED_EVENT + eventKey = TRANSACTION_RESUBMITTED_EVENT; } else if (type === TRANSACTION_TYPES.CANCEL) { - eventKey = TRANSACTION_CANCEL_ATTEMPTED_EVENT + eventKey = TRANSACTION_CANCEL_ATTEMPTED_EVENT; } } else if (value === CONFIRMED_STATUS) { if (type === TRANSACTION_TYPES.CANCEL) { - eventKey = TRANSACTION_CANCEL_SUCCESS_EVENT + eventKey = TRANSACTION_CANCEL_SUCCESS_EVENT; } } @@ -128,10 +128,10 @@ export function getActivities(transaction, isFirstTransaction = false) { eventKey, timestamp, value: gasFee, - }) + }); } - break + break; } // If the gas price or gas limit has been changed, we update the gasFee of the @@ -139,13 +139,13 @@ export function getActivities(transaction, isFirstTransaction = false) { // changed at the confirm screen. case GAS_PRICE_PATH: case GAS_LIMIT_PATH: { - const lastEvent = events[events.length - 1] || {} - const { lastEventKey } = lastEvent + const lastEvent = events[events.length - 1] || {}; + const { lastEventKey } = lastEvent; if (path === GAS_LIMIT_PATH) { - cachedGasLimit = value + cachedGasLimit = value; } else if (path === GAS_PRICE_PATH) { - cachedGasPrice = value + cachedGasPrice = value; } if ( @@ -155,10 +155,10 @@ export function getActivities(transaction, isFirstTransaction = false) { lastEvent.value = getHexGasTotal({ gasLimit: cachedGasLimit, gasPrice: cachedGasPrice, - }) + }); } - break + break; } default: { @@ -167,17 +167,17 @@ export function getActivities(transaction, isFirstTransaction = false) { hash, eventKey: TRANSACTION_UPDATED_EVENT, timestamp, - }) + }); } } } - }) + }); - return acc.concat(events) + return acc.concat(events); } - return acc - }, []) + return acc; + }, []); // If txReceipt.status is '0x0', that means that an on-chain error occurred for the transaction, // so we add an error entry to the Activity Log. @@ -187,7 +187,7 @@ export function getActivities(transaction, isFirstTransaction = false) { hash, eventKey: TRANSACTION_ERRORED_EVENT, }) - : historyActivities + : historyActivities; } /** @@ -200,28 +200,28 @@ export function getActivities(transaction, isFirstTransaction = false) { * @returns {Array} */ function filterSortedActivities(activities) { - const filteredActivities = [] + const filteredActivities = []; const hasConfirmedActivity = Boolean( activities.find( ({ eventKey }) => eventKey === TRANSACTION_CONFIRMED_EVENT || eventKey === TRANSACTION_CANCEL_SUCCESS_EVENT, ), - ) - let addedDroppedActivity = false + ); + let addedDroppedActivity = false; activities.forEach((activity) => { if (activity.eventKey === TRANSACTION_DROPPED_EVENT) { if (!hasConfirmedActivity && !addedDroppedActivity) { - filteredActivities.push(activity) - addedDroppedActivity = true + filteredActivities.push(activity); + addedDroppedActivity = true; } } else { - filteredActivities.push(activity) + filteredActivities.push(activity); } - }) + }); - return filteredActivities + return filteredActivities; } /** @@ -231,19 +231,19 @@ function filterSortedActivities(activities) { */ export function combineTransactionHistories(transactions = []) { if (!transactions.length) { - return [] + return []; } - const activities = [] + const activities = []; transactions.forEach((transaction, index) => { // The first transaction should be the transaction with the earliest submittedTime. We show the // 'created' and 'submitted' activities here. All subsequent transactions will use 'resubmitted' // instead. - const transactionActivities = getActivities(transaction, index === 0) - activities.push(...transactionActivities) - }) + const transactionActivities = getActivities(transaction, index === 0); + activities.push(...transactionActivities); + }); - const sortedActivities = activities.sort((a, b) => a.timestamp - b.timestamp) - return filterSortedActivities(sortedActivities) + const sortedActivities = activities.sort((a, b) => a.timestamp - b.timestamp); + return filterSortedActivities(sortedActivities); } diff --git a/ui/app/components/app/transaction-breakdown/index.js b/ui/app/components/app/transaction-breakdown/index.js index 4a5b52663..61d6fef97 100644 --- a/ui/app/components/app/transaction-breakdown/index.js +++ b/ui/app/components/app/transaction-breakdown/index.js @@ -1 +1 @@ -export { default } from './transaction-breakdown.container' +export { default } from './transaction-breakdown.container'; diff --git a/ui/app/components/app/transaction-breakdown/tests/transaction-breakdown.component.test.js b/ui/app/components/app/transaction-breakdown/tests/transaction-breakdown.component.test.js index a4baa21b2..1e4b89a8f 100644 --- a/ui/app/components/app/transaction-breakdown/tests/transaction-breakdown.component.test.js +++ b/ui/app/components/app/transaction-breakdown/tests/transaction-breakdown.component.test.js @@ -1,8 +1,8 @@ -import assert from 'assert' -import React from 'react' -import { shallow } from 'enzyme' -import TransactionBreakdown from '../transaction-breakdown.component' -import { TRANSACTION_STATUSES } from '../../../../../../shared/constants/transaction' +import assert from 'assert'; +import React from 'react'; +import { shallow } from 'enzyme'; +import TransactionBreakdown from '../transaction-breakdown.component'; +import { TRANSACTION_STATUSES } from '../../../../../../shared/constants/transaction'; describe('TransactionBreakdown Component', function () { it('should render properly', function () { @@ -18,14 +18,14 @@ describe('TransactionBreakdown Component', function () { to: '0x2', value: '0x2386f26fc10000', }, - } + }; const wrapper = shallow( , { context: { t: (str1, str2) => (str2 ? str1 + str2 : str1) } }, - ) + ); - assert.ok(wrapper.hasClass('transaction-breakdown')) - assert.ok(wrapper.hasClass('test-class')) - }) -}) + assert.ok(wrapper.hasClass('transaction-breakdown')); + assert.ok(wrapper.hasClass('test-class')); + }); +}); diff --git a/ui/app/components/app/transaction-breakdown/transaction-breakdown-row/index.js b/ui/app/components/app/transaction-breakdown/transaction-breakdown-row/index.js index 557bf75fb..a661081c6 100644 --- a/ui/app/components/app/transaction-breakdown/transaction-breakdown-row/index.js +++ b/ui/app/components/app/transaction-breakdown/transaction-breakdown-row/index.js @@ -1 +1 @@ -export { default } from './transaction-breakdown-row.component' +export { default } from './transaction-breakdown-row.component'; diff --git a/ui/app/components/app/transaction-breakdown/transaction-breakdown-row/tests/transaction-breakdown-row.component.test.js b/ui/app/components/app/transaction-breakdown/transaction-breakdown-row/tests/transaction-breakdown-row.component.test.js index db5ebef70..70929e527 100644 --- a/ui/app/components/app/transaction-breakdown/transaction-breakdown-row/tests/transaction-breakdown-row.component.test.js +++ b/ui/app/components/app/transaction-breakdown/transaction-breakdown-row/tests/transaction-breakdown-row.component.test.js @@ -1,8 +1,8 @@ -import assert from 'assert' -import React from 'react' -import { shallow } from 'enzyme' -import TransactionBreakdownRow from '../transaction-breakdown-row.component' -import Button from '../../../../ui/button' +import assert from 'assert'; +import React from 'react'; +import { shallow } from 'enzyme'; +import TransactionBreakdownRow from '../transaction-breakdown-row.component'; +import Button from '../../../../ui/button'; describe('TransactionBreakdownRow Component', function () { it('should render text properly', function () { @@ -11,18 +11,18 @@ describe('TransactionBreakdownRow Component', function () { Test , { context: { t: (str1, str2) => (str2 ? str1 + str2 : str1) } }, - ) + ); - assert.ok(wrapper.hasClass('transaction-breakdown-row')) + assert.ok(wrapper.hasClass('transaction-breakdown-row')); assert.strictEqual( wrapper.find('.transaction-breakdown-row__title').text(), 'test', - ) + ); assert.strictEqual( wrapper.find('.transaction-breakdown-row__value').text(), 'Test', - ) - }) + ); + }); it('should render components properly', function () { const wrapper = shallow( @@ -30,13 +30,13 @@ describe('TransactionBreakdownRow Component', function () { , { context: { t: (str1, str2) => (str2 ? str1 + str2 : str1) } }, - ) + ); - assert.ok(wrapper.hasClass('transaction-breakdown-row')) + assert.ok(wrapper.hasClass('transaction-breakdown-row')); assert.strictEqual( wrapper.find('.transaction-breakdown-row__title').text(), 'test', - ) - assert.ok(wrapper.find('.transaction-breakdown-row__value').find(Button)) - }) -}) + ); + assert.ok(wrapper.find('.transaction-breakdown-row__value').find(Button)); + }); +}); diff --git a/ui/app/components/app/transaction-breakdown/transaction-breakdown-row/transaction-breakdown-row.component.js b/ui/app/components/app/transaction-breakdown/transaction-breakdown-row/transaction-breakdown-row.component.js index ce652f02d..2668811b1 100644 --- a/ui/app/components/app/transaction-breakdown/transaction-breakdown-row/transaction-breakdown-row.component.js +++ b/ui/app/components/app/transaction-breakdown/transaction-breakdown-row/transaction-breakdown-row.component.js @@ -1,22 +1,22 @@ -import React, { PureComponent } from 'react' -import PropTypes from 'prop-types' -import classnames from 'classnames' +import React, { PureComponent } from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; export default class TransactionBreakdownRow extends PureComponent { static propTypes = { title: PropTypes.string, children: PropTypes.node, className: PropTypes.string, - } + }; render() { - const { title, children, className } = this.props + const { title, children, className } = this.props; return (
    {title}
    {children}
    - ) + ); } } diff --git a/ui/app/components/app/transaction-breakdown/transaction-breakdown.component.js b/ui/app/components/app/transaction-breakdown/transaction-breakdown.component.js index 3e4259f4b..4698819cf 100644 --- a/ui/app/components/app/transaction-breakdown/transaction-breakdown.component.js +++ b/ui/app/components/app/transaction-breakdown/transaction-breakdown.component.js @@ -1,16 +1,16 @@ -import React, { PureComponent } from 'react' -import PropTypes from 'prop-types' -import classnames from 'classnames' -import CurrencyDisplay from '../../ui/currency-display' -import UserPreferencedCurrencyDisplay from '../user-preferenced-currency-display' -import HexToDecimal from '../../ui/hex-to-decimal' -import { GWEI, PRIMARY, SECONDARY } from '../../../helpers/constants/common' -import TransactionBreakdownRow from './transaction-breakdown-row' +import React, { PureComponent } from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; +import CurrencyDisplay from '../../ui/currency-display'; +import UserPreferencedCurrencyDisplay from '../user-preferenced-currency-display'; +import HexToDecimal from '../../ui/hex-to-decimal'; +import { GWEI, PRIMARY, SECONDARY } from '../../../helpers/constants/common'; +import TransactionBreakdownRow from './transaction-breakdown-row'; export default class TransactionBreakdown extends PureComponent { static contextTypes = { t: PropTypes.func, - } + }; static propTypes = { className: PropTypes.string, @@ -23,14 +23,14 @@ export default class TransactionBreakdown extends PureComponent { gasPrice: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), gasUsed: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), totalInHex: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), - } + }; static defaultProps = { showFiat: true, - } + }; render() { - const { t } = this.context + const { t } = this.context; const { gas, gasPrice, @@ -42,7 +42,7 @@ export default class TransactionBreakdown extends PureComponent { totalInHex, gasUsed, isTokenApprove, - } = this.props + } = this.props; return (
    {t('transaction')}
    @@ -116,6 +116,6 @@ export default class TransactionBreakdown extends PureComponent {
    - ) + ); } } diff --git a/ui/app/components/app/transaction-breakdown/transaction-breakdown.container.js b/ui/app/components/app/transaction-breakdown/transaction-breakdown.container.js index d4bf56100..1ab3b4818 100644 --- a/ui/app/components/app/transaction-breakdown/transaction-breakdown.container.js +++ b/ui/app/components/app/transaction-breakdown/transaction-breakdown.container.js @@ -1,30 +1,30 @@ -import { connect } from 'react-redux' +import { connect } from 'react-redux'; import { getIsMainnet, getNativeCurrency, getPreferences, -} from '../../../selectors' -import { getHexGasTotal } from '../../../helpers/utils/confirm-tx.util' -import { sumHexes } from '../../../helpers/utils/transactions.util' -import { TRANSACTION_CATEGORIES } from '../../../../../shared/constants/transaction' -import TransactionBreakdown from './transaction-breakdown.component' +} from '../../../selectors'; +import { getHexGasTotal } from '../../../helpers/utils/confirm-tx.util'; +import { sumHexes } from '../../../helpers/utils/transactions.util'; +import { TRANSACTION_CATEGORIES } from '../../../../../shared/constants/transaction'; +import TransactionBreakdown from './transaction-breakdown.component'; const mapStateToProps = (state, ownProps) => { - const { transaction, transactionCategory } = ownProps + const { transaction, transactionCategory } = ownProps; const { txParams: { gas, gasPrice, value } = {}, txReceipt: { gasUsed } = {}, - } = transaction - const { showFiatInTestnets } = getPreferences(state) - const isMainnet = getIsMainnet(state) + } = transaction; + const { showFiatInTestnets } = getPreferences(state); + const isMainnet = getIsMainnet(state); const isTokenApprove = - transactionCategory === TRANSACTION_CATEGORIES.TOKEN_METHOD_APPROVE + transactionCategory === TRANSACTION_CATEGORIES.TOKEN_METHOD_APPROVE; - const gasLimit = typeof gasUsed === 'string' ? gasUsed : gas + const gasLimit = typeof gasUsed === 'string' ? gasUsed : gas; const hexGasTotal = - (gasLimit && gasPrice && getHexGasTotal({ gasLimit, gasPrice })) || '0x0' - const totalInHex = sumHexes(hexGasTotal, value) + (gasLimit && gasPrice && getHexGasTotal({ gasLimit, gasPrice })) || '0x0'; + const totalInHex = sumHexes(hexGasTotal, value); return { nativeCurrency: getNativeCurrency(state), @@ -34,7 +34,7 @@ const mapStateToProps = (state, ownProps) => { gasPrice, gasUsed, isTokenApprove, - } -} + }; +}; -export default connect(mapStateToProps)(TransactionBreakdown) +export default connect(mapStateToProps)(TransactionBreakdown); diff --git a/ui/app/components/app/transaction-icon/index.js b/ui/app/components/app/transaction-icon/index.js index d41970a54..cca6a32d8 100644 --- a/ui/app/components/app/transaction-icon/index.js +++ b/ui/app/components/app/transaction-icon/index.js @@ -1 +1 @@ -export { default } from './transaction-icon' +export { default } from './transaction-icon'; diff --git a/ui/app/components/app/transaction-icon/transaction-icon.js b/ui/app/components/app/transaction-icon/transaction-icon.js index fe6aa0e5a..5fd8a3cd7 100644 --- a/ui/app/components/app/transaction-icon/transaction-icon.js +++ b/ui/app/components/app/transaction-icon/transaction-icon.js @@ -1,16 +1,16 @@ -import React from 'react' -import PropTypes from 'prop-types' -import Approve from '../../ui/icon/approve-icon.component' -import Interaction from '../../ui/icon/interaction-icon.component' -import Receive from '../../ui/icon/receive-icon.component' -import Send from '../../ui/icon/send-icon.component' -import Sign from '../../ui/icon/sign-icon.component' -import Swap from '../../ui/icon/swap-icon-for-list.component' +import React from 'react'; +import PropTypes from 'prop-types'; +import Approve from '../../ui/icon/approve-icon.component'; +import Interaction from '../../ui/icon/interaction-icon.component'; +import Receive from '../../ui/icon/receive-icon.component'; +import Send from '../../ui/icon/send-icon.component'; +import Sign from '../../ui/icon/sign-icon.component'; +import Swap from '../../ui/icon/swap-icon-for-list.component'; import { TRANSACTION_GROUP_CATEGORIES, TRANSACTION_GROUP_STATUSES, TRANSACTION_STATUSES, -} from '../../../../../shared/constants/transaction' +} from '../../../../../shared/constants/transaction'; const ICON_MAP = { [TRANSACTION_GROUP_CATEGORIES.APPROVAL]: Approve, @@ -19,11 +19,11 @@ const ICON_MAP = { [TRANSACTION_GROUP_CATEGORIES.SIGNATURE_REQUEST]: Sign, [TRANSACTION_GROUP_CATEGORIES.RECEIVE]: Receive, [TRANSACTION_GROUP_CATEGORIES.SWAP]: Swap, -} +}; -const FAIL_COLOR = '#D73A49' -const PENDING_COLOR = '#6A737D' -const OK_COLOR = '#2F80ED' +const FAIL_COLOR = '#D73A49'; +const PENDING_COLOR = '#6A737D'; +const OK_COLOR = '#2F80ED'; const COLOR_MAP = { [TRANSACTION_GROUP_STATUSES.PENDING]: PENDING_COLOR, @@ -33,17 +33,17 @@ const COLOR_MAP = { [TRANSACTION_STATUSES.REJECTED]: FAIL_COLOR, [TRANSACTION_GROUP_STATUSES.CANCELLED]: FAIL_COLOR, [TRANSACTION_STATUSES.DROPPED]: FAIL_COLOR, -} +}; export default function TransactionIcon({ status, category }) { - const color = COLOR_MAP[status] || OK_COLOR + const color = COLOR_MAP[status] || OK_COLOR; - const Icon = ICON_MAP[category] + const Icon = ICON_MAP[category]; - return + return ; } TransactionIcon.propTypes = { status: PropTypes.string.isRequired, category: PropTypes.string.isRequired, -} +}; diff --git a/ui/app/components/app/transaction-list-item-details/index.js b/ui/app/components/app/transaction-list-item-details/index.js index 83bd53e7d..e01ce230c 100644 --- a/ui/app/components/app/transaction-list-item-details/index.js +++ b/ui/app/components/app/transaction-list-item-details/index.js @@ -1 +1 @@ -export { default } from './transaction-list-item-details.container' +export { default } from './transaction-list-item-details.container'; diff --git a/ui/app/components/app/transaction-list-item-details/tests/transaction-list-item-details.component.test.js b/ui/app/components/app/transaction-list-item-details/tests/transaction-list-item-details.component.test.js index 5027cc05b..a333ecd98 100644 --- a/ui/app/components/app/transaction-list-item-details/tests/transaction-list-item-details.component.test.js +++ b/ui/app/components/app/transaction-list-item-details/tests/transaction-list-item-details.component.test.js @@ -1,12 +1,12 @@ -import assert from 'assert' -import React from 'react' -import { shallow } from 'enzyme' -import TransactionListItemDetails from '../transaction-list-item-details.component' -import Button from '../../../ui/button' -import SenderToRecipient from '../../../ui/sender-to-recipient' -import TransactionBreakdown from '../../transaction-breakdown' -import TransactionActivityLog from '../../transaction-activity-log' -import { TRANSACTION_STATUSES } from '../../../../../../shared/constants/transaction' +import assert from 'assert'; +import React from 'react'; +import { shallow } from 'enzyme'; +import TransactionListItemDetails from '../transaction-list-item-details.component'; +import Button from '../../../ui/button'; +import SenderToRecipient from '../../../ui/sender-to-recipient'; +import TransactionBreakdown from '../../transaction-breakdown'; +import TransactionActivityLog from '../../transaction-activity-log'; +import { TRANSACTION_STATUSES } from '../../../../../../shared/constants/transaction'; describe('TransactionListItemDetails Component', function () { it('should render properly', function () { @@ -22,13 +22,13 @@ describe('TransactionListItemDetails Component', function () { to: '0x2', value: '0x2386f26fc10000', }, - } + }; const transactionGroup = { transactions: [transaction], primaryTransaction: transaction, initialTransaction: transaction, - } + }; const wrapper = shallow( , { context: { t: (str1, str2) => (str2 ? str1 + str2 : str1) } }, - ) - const child = wrapper.childAt(0) - assert.ok(child.hasClass('transaction-list-item-details')) - assert.strictEqual(child.find(Button).length, 2) - assert.strictEqual(child.find(SenderToRecipient).length, 1) - assert.strictEqual(child.find(TransactionBreakdown).length, 1) - assert.strictEqual(child.find(TransactionActivityLog).length, 1) - }) + ); + const child = wrapper.childAt(0); + assert.ok(child.hasClass('transaction-list-item-details')); + assert.strictEqual(child.find(Button).length, 2); + assert.strictEqual(child.find(SenderToRecipient).length, 1); + assert.strictEqual(child.find(TransactionBreakdown).length, 1); + assert.strictEqual(child.find(TransactionActivityLog).length, 1); + }); it('should render a retry button', function () { const transaction = { @@ -63,7 +63,7 @@ describe('TransactionListItemDetails Component', function () { to: '0x2', value: '0x2386f26fc10000', }, - } + }; const transactionGroup = { transactions: [transaction], @@ -72,7 +72,7 @@ describe('TransactionListItemDetails Component', function () { nonce: '0xa4', hasRetried: false, hasCancelled: false, - } + }; const wrapper = shallow( , { context: { t: (str1, str2) => (str2 ? str1 + str2 : str1) } }, - ) + ); - const child = wrapper.childAt(0) + const child = wrapper.childAt(0); - assert.ok(child.hasClass('transaction-list-item-details')) - assert.strictEqual(child.find(Button).length, 3) - }) + assert.ok(child.hasClass('transaction-list-item-details')); + assert.strictEqual(child.find(Button).length, 3); + }); it('should disable the Copy Tx ID and View In Etherscan buttons when tx hash is missing', function () { const transaction = { @@ -106,13 +106,13 @@ describe('TransactionListItemDetails Component', function () { to: '0x2', value: '0x2386f26fc10000', }, - } + }; const transactionGroup = { transactions: [transaction], primaryTransaction: transaction, initialTransaction: transaction, - } + }; const wrapper = shallow( , { context: { t: (str1, str2) => (str2 ? str1 + str2 : str1) } }, - ) + ); - const child = wrapper.childAt(0) + const child = wrapper.childAt(0); - assert.ok(child.hasClass('transaction-list-item-details')) - const buttons = child.find(Button) - assert.strictEqual(buttons.at(0).prop('disabled'), true) - assert.strictEqual(buttons.at(1).prop('disabled'), true) - }) + assert.ok(child.hasClass('transaction-list-item-details')); + const buttons = child.find(Button); + assert.strictEqual(buttons.at(0).prop('disabled'), true); + assert.strictEqual(buttons.at(1).prop('disabled'), true); + }); it('should render functional Copy Tx ID and View In Etherscan buttons when tx hash exists', function () { const transaction = { @@ -148,13 +148,13 @@ describe('TransactionListItemDetails Component', function () { to: '0x2', value: '0x2386f26fc10000', }, - } + }; const transactionGroup = { transactions: [transaction], primaryTransaction: transaction, initialTransaction: transaction, - } + }; const wrapper = shallow( , { context: { t: (str1, str2) => (str2 ? str1 + str2 : str1) } }, - ) + ); - const child = wrapper.childAt(0) + const child = wrapper.childAt(0); - assert.ok(child.hasClass('transaction-list-item-details')) - const buttons = child.find(Button) - assert.strictEqual(buttons.at(0).prop('disabled'), false) - assert.strictEqual(buttons.at(1).prop('disabled'), false) - }) -}) + assert.ok(child.hasClass('transaction-list-item-details')); + const buttons = child.find(Button); + assert.strictEqual(buttons.at(0).prop('disabled'), false); + assert.strictEqual(buttons.at(1).prop('disabled'), false); + }); +}); diff --git a/ui/app/components/app/transaction-list-item-details/transaction-list-item-details.component.js b/ui/app/components/app/transaction-list-item-details/transaction-list-item-details.component.js index 31c3adc3e..faa80846c 100644 --- a/ui/app/components/app/transaction-list-item-details/transaction-list-item-details.component.js +++ b/ui/app/components/app/transaction-list-item-details/transaction-list-item-details.component.js @@ -1,25 +1,25 @@ -import React, { PureComponent } from 'react' -import PropTypes from 'prop-types' -import copyToClipboard from 'copy-to-clipboard' -import { getBlockExplorerUrlForTx } from '../../../helpers/utils/transactions.util' -import SenderToRecipient from '../../ui/sender-to-recipient' -import { FLAT_VARIANT } from '../../ui/sender-to-recipient/sender-to-recipient.constants' -import TransactionActivityLog from '../transaction-activity-log' -import TransactionBreakdown from '../transaction-breakdown' -import Button from '../../ui/button' -import Tooltip from '../../ui/tooltip' -import Copy from '../../ui/icon/copy-icon.component' -import Popover from '../../ui/popover' +import React, { PureComponent } from 'react'; +import PropTypes from 'prop-types'; +import copyToClipboard from 'copy-to-clipboard'; +import { getBlockExplorerUrlForTx } from '../../../helpers/utils/transactions.util'; +import SenderToRecipient from '../../ui/sender-to-recipient'; +import { FLAT_VARIANT } from '../../ui/sender-to-recipient/sender-to-recipient.constants'; +import TransactionActivityLog from '../transaction-activity-log'; +import TransactionBreakdown from '../transaction-breakdown'; +import Button from '../../ui/button'; +import Tooltip from '../../ui/tooltip'; +import Copy from '../../ui/icon/copy-icon.component'; +import Popover from '../../ui/popover'; export default class TransactionListItemDetails extends PureComponent { static contextTypes = { t: PropTypes.func, metricsEvent: PropTypes.func, - } + }; static defaultProps = { recipientEns: null, - } + }; static propTypes = { onCancel: PropTypes.func, @@ -40,18 +40,18 @@ export default class TransactionListItemDetails extends PureComponent { tryReverseResolveAddress: PropTypes.func.isRequired, senderNickname: PropTypes.string.isRequired, recipientNickname: PropTypes.string, - } + }; state = { justCopied: false, - } + }; handleEtherscanClick = () => { const { transactionGroup: { primaryTransaction }, rpcPrefs, - } = this.props - const { hash, metamaskNetworkId } = primaryTransaction + } = this.props; + const { hash, metamaskNetworkId } = primaryTransaction; this.context.metricsEvent({ eventOpts: { @@ -59,29 +59,29 @@ export default class TransactionListItemDetails extends PureComponent { action: 'Activity Log', name: 'Clicked "View on Etherscan"', }, - }) + }); global.platform.openTab({ url: getBlockExplorerUrlForTx(metamaskNetworkId, hash, rpcPrefs), - }) - } + }); + }; handleCancel = (event) => { - const { onCancel, onClose } = this.props - onCancel(event) - onClose() - } + const { onCancel, onClose } = this.props; + onCancel(event); + onClose(); + }; handleRetry = (event) => { - const { onClose, onRetry } = this.props - onRetry(event) - onClose() - } + const { onClose, onRetry } = this.props; + onRetry(event); + onClose(); + }; handleCopyTxId = () => { - const { transactionGroup } = this.props - const { primaryTransaction: transaction } = transactionGroup - const { hash } = transaction + const { transactionGroup } = this.props; + const { primaryTransaction: transaction } = transactionGroup; + const { hash } = transaction; this.context.metricsEvent({ eventOpts: { @@ -89,28 +89,28 @@ export default class TransactionListItemDetails extends PureComponent { action: 'Activity Log', name: 'Copied Transaction ID', }, - }) + }); this.setState({ justCopied: true }, () => { - copyToClipboard(hash) - setTimeout(() => this.setState({ justCopied: false }), 1000) - }) - } + copyToClipboard(hash); + setTimeout(() => this.setState({ justCopied: false }), 1000); + }); + }; componentDidMount() { - const { recipientAddress, tryReverseResolveAddress } = this.props + const { recipientAddress, tryReverseResolveAddress } = this.props; if (recipientAddress) { - tryReverseResolveAddress(recipientAddress) + tryReverseResolveAddress(recipientAddress); } } renderCancel() { - const { t } = this.context - const { showCancel, cancelDisabled } = this.props + const { t } = this.context; + const { showCancel, cancelDisabled } = this.props; if (!showCancel) { - return null + return null; } return cancelDisabled ? ( @@ -134,12 +134,12 @@ export default class TransactionListItemDetails extends PureComponent { > {t('cancel')} - ) + ); } render() { - const { t } = this.context - const { justCopied } = this.state + const { t } = this.context; + const { justCopied } = this.state; const { transactionGroup, primaryCurrency, @@ -154,12 +154,12 @@ export default class TransactionListItemDetails extends PureComponent { title, onClose, recipientNickname, - } = this.props + } = this.props; const { primaryTransaction: transaction, initialTransaction: { transactionCategory }, - } = transactionGroup - const { hash } = transaction + } = transactionGroup; + const { hash } = transaction; return ( @@ -240,7 +240,7 @@ export default class TransactionListItemDetails extends PureComponent { action: 'Activity Log', name: 'Copied "To" Address', }, - }) + }); }} onSenderClick={() => { this.context.metricsEvent({ @@ -249,7 +249,7 @@ export default class TransactionListItemDetails extends PureComponent { action: 'Activity Log', name: 'Copied "From" Address', }, - }) + }); }} /> @@ -272,6 +272,6 @@ export default class TransactionListItemDetails extends PureComponent { - ) + ); } } diff --git a/ui/app/components/app/transaction-list-item-details/transaction-list-item-details.container.js b/ui/app/components/app/transaction-list-item-details/transaction-list-item-details.container.js index 55fcf8582..4a96082c7 100644 --- a/ui/app/components/app/transaction-list-item-details/transaction-list-item-details.container.js +++ b/ui/app/components/app/transaction-list-item-details/transaction-list-item-details.container.js @@ -1,48 +1,48 @@ -import { connect } from 'react-redux' -import { checksumAddress } from '../../../helpers/utils/util' -import { tryReverseResolveAddress } from '../../../store/actions' +import { connect } from 'react-redux'; +import { checksumAddress } from '../../../helpers/utils/util'; +import { tryReverseResolveAddress } from '../../../store/actions'; import { getAddressBook, getRpcPrefsForCurrentProvider, -} from '../../../selectors' -import TransactionListItemDetails from './transaction-list-item-details.component' +} from '../../../selectors'; +import TransactionListItemDetails from './transaction-list-item-details.component'; const mapStateToProps = (state, ownProps) => { - const { metamask } = state - const { ensResolutionsByAddress } = metamask - const { recipientAddress, senderAddress } = ownProps - let recipientEns + const { metamask } = state; + const { ensResolutionsByAddress } = metamask; + const { recipientAddress, senderAddress } = ownProps; + let recipientEns; if (recipientAddress) { - const address = checksumAddress(recipientAddress) - recipientEns = ensResolutionsByAddress[address] || '' + const address = checksumAddress(recipientAddress); + recipientEns = ensResolutionsByAddress[address] || ''; } - const addressBook = getAddressBook(state) + const addressBook = getAddressBook(state); const getNickName = (address) => { const entry = addressBook.find((contact) => { - return address.toLowerCase() === contact.address.toLowerCase() - }) - return (entry && entry.name) || '' - } - const rpcPrefs = getRpcPrefsForCurrentProvider(state) + return address.toLowerCase() === contact.address.toLowerCase(); + }); + return (entry && entry.name) || ''; + }; + const rpcPrefs = getRpcPrefsForCurrentProvider(state); return { rpcPrefs, recipientEns, senderNickname: getNickName(senderAddress), recipientNickname: recipientAddress ? getNickName(recipientAddress) : null, - } -} + }; +}; const mapDispatchToProps = (dispatch) => { return { tryReverseResolveAddress: (address) => { - return dispatch(tryReverseResolveAddress(address)) + return dispatch(tryReverseResolveAddress(address)); }, - } -} + }; +}; export default connect( mapStateToProps, mapDispatchToProps, -)(TransactionListItemDetails) +)(TransactionListItemDetails); diff --git a/ui/app/components/app/transaction-list-item/index.js b/ui/app/components/app/transaction-list-item/index.js index 1fdbb29ac..03a62d9e4 100644 --- a/ui/app/components/app/transaction-list-item/index.js +++ b/ui/app/components/app/transaction-list-item/index.js @@ -1 +1 @@ -export { default } from './transaction-list-item.component' +export { default } from './transaction-list-item.component'; diff --git a/ui/app/components/app/transaction-list-item/transaction-list-item.component.js b/ui/app/components/app/transaction-list-item/transaction-list-item.component.js index 64a617cda..ec29e04d6 100644 --- a/ui/app/components/app/transaction-list-item/transaction-list-item.component.js +++ b/ui/app/components/app/transaction-list-item/transaction-list-item.component.js @@ -1,45 +1,45 @@ -import React, { useMemo, useState, useCallback } from 'react' -import PropTypes from 'prop-types' -import classnames from 'classnames' -import { useHistory } from 'react-router-dom' -import ListItem from '../../ui/list-item' -import { useTransactionDisplayData } from '../../../hooks/useTransactionDisplayData' -import { useI18nContext } from '../../../hooks/useI18nContext' -import { useCancelTransaction } from '../../../hooks/useCancelTransaction' -import { useRetryTransaction } from '../../../hooks/useRetryTransaction' -import Button from '../../ui/button' -import Tooltip from '../../ui/tooltip' -import TransactionListItemDetails from '../transaction-list-item-details' -import { CONFIRM_TRANSACTION_ROUTE } from '../../../helpers/constants/routes' -import { useShouldShowSpeedUp } from '../../../hooks/useShouldShowSpeedUp' -import TransactionStatus from '../transaction-status/transaction-status.component' -import TransactionIcon from '../transaction-icon' +import React, { useMemo, useState, useCallback } from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; +import { useHistory } from 'react-router-dom'; +import ListItem from '../../ui/list-item'; +import { useTransactionDisplayData } from '../../../hooks/useTransactionDisplayData'; +import { useI18nContext } from '../../../hooks/useI18nContext'; +import { useCancelTransaction } from '../../../hooks/useCancelTransaction'; +import { useRetryTransaction } from '../../../hooks/useRetryTransaction'; +import Button from '../../ui/button'; +import Tooltip from '../../ui/tooltip'; +import TransactionListItemDetails from '../transaction-list-item-details'; +import { CONFIRM_TRANSACTION_ROUTE } from '../../../helpers/constants/routes'; +import { useShouldShowSpeedUp } from '../../../hooks/useShouldShowSpeedUp'; +import TransactionStatus from '../transaction-status/transaction-status.component'; +import TransactionIcon from '../transaction-icon'; import { TRANSACTION_GROUP_CATEGORIES, TRANSACTION_STATUSES, -} from '../../../../../shared/constants/transaction' +} from '../../../../../shared/constants/transaction'; export default function TransactionListItem({ transactionGroup, isEarliestNonce = false, }) { - const t = useI18nContext() - const history = useHistory() - const { hasCancelled } = transactionGroup - const [showDetails, setShowDetails] = useState(false) + const t = useI18nContext(); + const history = useHistory(); + const { hasCancelled } = transactionGroup; + const [showDetails, setShowDetails] = useState(false); const { initialTransaction: { id }, primaryTransaction: { err, status }, - } = transactionGroup + } = transactionGroup; const [cancelEnabled, cancelTransaction] = useCancelTransaction( transactionGroup, - ) - const retryTransaction = useRetryTransaction(transactionGroup) + ); + const retryTransaction = useRetryTransaction(transactionGroup); const shouldShowSpeedUp = useShouldShowSpeedUp( transactionGroup, isEarliestNonce, - ) + ); const { title, @@ -53,13 +53,13 @@ export default function TransactionListItem({ displayedStatusKey, isPending, senderAddress, - } = useTransactionDisplayData(transactionGroup) + } = useTransactionDisplayData(transactionGroup); const isSignatureReq = - category === TRANSACTION_GROUP_CATEGORIES.SIGNATURE_REQUEST - const isApproval = category === TRANSACTION_GROUP_CATEGORIES.APPROVAL - const isUnapproved = status === TRANSACTION_STATUSES.UNAPPROVED - const isSwap = category === TRANSACTION_GROUP_CATEGORIES.SWAP + category === TRANSACTION_GROUP_CATEGORIES.SIGNATURE_REQUEST; + const isApproval = category === TRANSACTION_GROUP_CATEGORIES.APPROVAL; + const isUnapproved = status === TRANSACTION_STATUSES.UNAPPROVED; + const isSwap = category === TRANSACTION_GROUP_CATEGORIES.SWAP; const className = classnames('transaction-list-item', { 'transaction-list-item--unconfirmed': @@ -69,15 +69,15 @@ export default function TransactionListItem({ TRANSACTION_STATUSES.DROPPED, TRANSACTION_STATUSES.REJECTED, ].includes(displayedStatusKey), - }) + }); const toggleShowDetails = useCallback(() => { if (isUnapproved) { - history.push(`${CONFIRM_TRANSACTION_ROUTE}/${id}`) - return + history.push(`${CONFIRM_TRANSACTION_ROUTE}/${id}`); + return; } - setShowDetails((prev) => !prev) - }, [isUnapproved, history, id]) + setShowDetails((prev) => !prev); + }, [isUnapproved, history, id]); const cancelButton = useMemo(() => { const btn = ( @@ -89,9 +89,9 @@ export default function TransactionListItem({ > {t('cancel')} - ) + ); if (hasCancelled || !isPending || isUnapproved) { - return null + return null; } return cancelEnabled ? ( @@ -100,7 +100,7 @@ export default function TransactionListItem({
    {btn}
    - ) + ); }, [ isPending, t, @@ -108,11 +108,11 @@ export default function TransactionListItem({ cancelEnabled, cancelTransaction, hasCancelled, - ]) + ]); const speedUpButton = useMemo(() => { if (!shouldShowSpeedUp || !isPending || isUnapproved) { - return null + return null; } return ( - ) - }, [shouldShowSpeedUp, isUnapproved, t, isPending, retryTransaction]) + ); + }, [shouldShowSpeedUp, isUnapproved, t, isPending, retryTransaction]); return ( <> @@ -196,10 +196,10 @@ export default function TransactionListItem({ /> )} - ) + ); } TransactionListItem.propTypes = { transactionGroup: PropTypes.object.isRequired, isEarliestNonce: PropTypes.bool, -} +}; diff --git a/ui/app/components/app/transaction-list/index.js b/ui/app/components/app/transaction-list/index.js index 1ec6c5124..f5d9bba6f 100644 --- a/ui/app/components/app/transaction-list/index.js +++ b/ui/app/components/app/transaction-list/index.js @@ -1 +1 @@ -export { default } from './transaction-list.component' +export { default } from './transaction-list.component'; diff --git a/ui/app/components/app/transaction-list/transaction-list.component.js b/ui/app/components/app/transaction-list/transaction-list.component.js index 31f690740..e69523329 100644 --- a/ui/app/components/app/transaction-list/transaction-list.component.js +++ b/ui/app/components/app/transaction-list/transaction-list.component.js @@ -1,18 +1,18 @@ -import React, { useMemo, useState, useCallback } from 'react' -import PropTypes from 'prop-types' -import { useSelector } from 'react-redux' +import React, { useMemo, useState, useCallback } from 'react'; +import PropTypes from 'prop-types'; +import { useSelector } from 'react-redux'; import { nonceSortedCompletedTransactionsSelector, nonceSortedPendingTransactionsSelector, -} from '../../../selectors/transactions' -import { useI18nContext } from '../../../hooks/useI18nContext' -import TransactionListItem from '../transaction-list-item' -import Button from '../../ui/button' -import { TOKEN_CATEGORY_HASH } from '../../../helpers/constants/transactions' -import { SWAPS_CONTRACT_ADDRESS } from '../../../helpers/constants/swaps' -import { TRANSACTION_CATEGORIES } from '../../../../../shared/constants/transaction' +} from '../../../selectors/transactions'; +import { useI18nContext } from '../../../hooks/useI18nContext'; +import TransactionListItem from '../transaction-list-item'; +import Button from '../../ui/button'; +import { TOKEN_CATEGORY_HASH } from '../../../helpers/constants/transactions'; +import { SWAPS_CONTRACT_ADDRESS } from '../../../helpers/constants/swaps'; +import { TRANSACTION_CATEGORIES } from '../../../../../shared/constants/transaction'; -const PAGE_INCREMENT = 10 +const PAGE_INCREMENT = 10; const getTransactionGroupRecipientAddressFilter = (recipientAddress) => { return ({ initialTransaction: { txParams } }) => { @@ -20,9 +20,9 @@ const getTransactionGroupRecipientAddressFilter = (recipientAddress) => { txParams?.to === recipientAddress || (txParams?.to === SWAPS_CONTRACT_ADDRESS && txParams.data.match(recipientAddress.slice(2))) - ) - } -} + ); + }; +}; const tokenTransactionFilter = ({ initialTransaction: { @@ -32,12 +32,12 @@ const tokenTransactionFilter = ({ }, }) => { if (TOKEN_CATEGORY_HASH[transactionCategory]) { - return false + return false; } else if (transactionCategory === TRANSACTION_CATEGORIES.SWAP) { - return destinationTokenSymbol === 'ETH' || sourceTokenSymbol === 'ETH' + return destinationTokenSymbol === 'ETH' || sourceTokenSymbol === 'ETH'; } - return true -} + return true; +}; const getFilteredTransactionGroups = ( transactionGroups, @@ -45,28 +45,28 @@ const getFilteredTransactionGroups = ( tokenAddress, ) => { if (hideTokenTransactions) { - return transactionGroups.filter(tokenTransactionFilter) + return transactionGroups.filter(tokenTransactionFilter); } else if (tokenAddress) { return transactionGroups.filter( getTransactionGroupRecipientAddressFilter(tokenAddress), - ) + ); } - return transactionGroups -} + return transactionGroups; +}; export default function TransactionList({ hideTokenTransactions, tokenAddress, }) { - const [limit, setLimit] = useState(PAGE_INCREMENT) - const t = useI18nContext() + const [limit, setLimit] = useState(PAGE_INCREMENT); + const t = useI18nContext(); const unfilteredPendingTransactions = useSelector( nonceSortedPendingTransactionsSelector, - ) + ); const unfilteredCompletedTransactions = useSelector( nonceSortedCompletedTransactionsSelector, - ) + ); const pendingTransactions = useMemo( () => @@ -76,7 +76,7 @@ export default function TransactionList({ tokenAddress, ), [hideTokenTransactions, tokenAddress, unfilteredPendingTransactions], - ) + ); const completedTransactions = useMemo( () => getFilteredTransactionGroups( @@ -85,14 +85,14 @@ export default function TransactionList({ tokenAddress, ), [hideTokenTransactions, tokenAddress, unfilteredCompletedTransactions], - ) + ); const viewMore = useCallback( () => setLimit((prev) => prev + PAGE_INCREMENT), [], - ) + ); - const pendingLength = pendingTransactions.length + const pendingLength = pendingTransactions.length; return (
    @@ -144,15 +144,15 @@ export default function TransactionList({
    - ) + ); } TransactionList.propTypes = { hideTokenTransactions: PropTypes.bool, tokenAddress: PropTypes.string, -} +}; TransactionList.defaultProps = { hideTokenTransactions: false, tokenAddress: undefined, -} +}; diff --git a/ui/app/components/app/transaction-status/index.js b/ui/app/components/app/transaction-status/index.js index dece41e9c..61bb74e20 100644 --- a/ui/app/components/app/transaction-status/index.js +++ b/ui/app/components/app/transaction-status/index.js @@ -1 +1 @@ -export { default } from './transaction-status.component' +export { default } from './transaction-status.component'; diff --git a/ui/app/components/app/transaction-status/tests/transaction-status.component.test.js b/ui/app/components/app/transaction-status/tests/transaction-status.component.test.js index 016d4d5a9..2300081de 100644 --- a/ui/app/components/app/transaction-status/tests/transaction-status.component.test.js +++ b/ui/app/components/app/transaction-status/tests/transaction-status.component.test.js @@ -1,24 +1,24 @@ -import assert from 'assert' -import React from 'react' -import { mount } from 'enzyme' -import sinon from 'sinon' -import * as i18nHook from '../../../../hooks/useI18nContext' -import TransactionStatus from '../transaction-status.component' -import Tooltip from '../../../ui/tooltip' +import assert from 'assert'; +import React from 'react'; +import { mount } from 'enzyme'; +import sinon from 'sinon'; +import * as i18nHook from '../../../../hooks/useI18nContext'; +import TransactionStatus from '../transaction-status.component'; +import Tooltip from '../../../ui/tooltip'; describe('TransactionStatus Component', function () { before(function () { - sinon.stub(i18nHook, 'useI18nContext').returns((str) => str.toUpperCase()) - }) + sinon.stub(i18nHook, 'useI18nContext').returns((str) => str.toUpperCase()); + }); it('should render CONFIRMED properly', function () { const wrapper = mount( , - ) + ); - assert.ok(wrapper) - assert.strictEqual(wrapper.text(), 'June 1') - }) + assert.ok(wrapper); + assert.strictEqual(wrapper.text(), 'June 1'); + }); it('should render PENDING properly when status is APPROVED', function () { const wrapper = mount( @@ -27,45 +27,45 @@ describe('TransactionStatus Component', function () { isEarliestNonce error={{ message: 'test-title' }} />, - ) + ); - assert.ok(wrapper) - assert.strictEqual(wrapper.text(), 'PENDING') - assert.strictEqual(wrapper.find(Tooltip).props().title, 'test-title') - }) + assert.ok(wrapper); + assert.strictEqual(wrapper.text(), 'PENDING'); + assert.strictEqual(wrapper.find(Tooltip).props().title, 'test-title'); + }); it('should render PENDING properly', function () { const wrapper = mount( , - ) + ); - assert.ok(wrapper) - assert.strictEqual(wrapper.text(), 'PENDING') - }) + assert.ok(wrapper); + assert.strictEqual(wrapper.text(), 'PENDING'); + }); it('should render QUEUED properly', function () { - const wrapper = mount() + const wrapper = mount(); - assert.ok(wrapper) + assert.ok(wrapper); assert.ok( wrapper.find('.transaction-status--queued').length, 'queued className not found', - ) - assert.strictEqual(wrapper.text(), 'QUEUED') - }) + ); + assert.strictEqual(wrapper.text(), 'QUEUED'); + }); it('should render UNAPPROVED properly', function () { - const wrapper = mount() + const wrapper = mount(); - assert.ok(wrapper) + assert.ok(wrapper); assert.ok( wrapper.find('.transaction-status--unapproved').length, 'unapproved className not found', - ) - assert.strictEqual(wrapper.text(), 'UNAPPROVED') - }) + ); + assert.strictEqual(wrapper.text(), 'UNAPPROVED'); + }); after(function () { - sinon.restore() - }) -}) + sinon.restore(); + }); +}); diff --git a/ui/app/components/app/transaction-status/transaction-status.component.js b/ui/app/components/app/transaction-status/transaction-status.component.js index 5c5dd3515..6049a33a9 100644 --- a/ui/app/components/app/transaction-status/transaction-status.component.js +++ b/ui/app/components/app/transaction-status/transaction-status.component.js @@ -1,15 +1,15 @@ -import React from 'react' -import PropTypes from 'prop-types' -import classnames from 'classnames' -import Tooltip from '../../ui/tooltip' +import React from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; +import Tooltip from '../../ui/tooltip'; -import { useI18nContext } from '../../../hooks/useI18nContext' +import { useI18nContext } from '../../../hooks/useI18nContext'; import { TRANSACTION_GROUP_STATUSES, TRANSACTION_STATUSES, -} from '../../../../../shared/constants/transaction' +} from '../../../../../shared/constants/transaction'; -const QUEUED_PSEUDO_STATUS = 'queued' +const QUEUED_PSEUDO_STATUS = 'queued'; /** * A note about status logic for this component: @@ -25,7 +25,7 @@ const pendingStatusHash = { [TRANSACTION_STATUSES.SUBMITTED]: TRANSACTION_GROUP_STATUSES.PENDING, [TRANSACTION_STATUSES.APPROVED]: TRANSACTION_GROUP_STATUSES.PENDING, [TRANSACTION_STATUSES.SIGNED]: TRANSACTION_GROUP_STATUSES.PENDING, -} +}; const statusToClassNameHash = { [TRANSACTION_STATUSES.UNAPPROVED]: 'transaction-status--unapproved', @@ -35,7 +35,7 @@ const statusToClassNameHash = { [TRANSACTION_GROUP_STATUSES.CANCELLED]: 'transaction-status--cancelled', [QUEUED_PSEUDO_STATUS]: 'transaction-status--queued', [TRANSACTION_GROUP_STATUSES.PENDING]: 'transaction-status--pending', -} +}; export default function TransactionStatus({ status, @@ -44,17 +44,17 @@ export default function TransactionStatus({ isEarliestNonce, className, }) { - const t = useI18nContext() - const tooltipText = error?.rpc?.message || error?.message - let statusKey = status + const t = useI18nContext(); + const tooltipText = error?.rpc?.message || error?.message; + let statusKey = status; if (pendingStatusHash[status]) { statusKey = isEarliestNonce ? TRANSACTION_GROUP_STATUSES.PENDING - : QUEUED_PSEUDO_STATUS + : QUEUED_PSEUDO_STATUS; } const statusText = - statusKey === TRANSACTION_STATUSES.CONFIRMED ? date : t(statusKey) + statusKey === TRANSACTION_STATUSES.CONFIRMED ? date : t(statusKey); return ( {statusText} - ) + ); } TransactionStatus.propTypes = { @@ -77,4 +77,4 @@ TransactionStatus.propTypes = { date: PropTypes.string, error: PropTypes.object, isEarliestNonce: PropTypes.bool, -} +}; diff --git a/ui/app/components/app/user-preferenced-currency-display/index.js b/ui/app/components/app/user-preferenced-currency-display/index.js index 5bc2d4246..e0976593b 100644 --- a/ui/app/components/app/user-preferenced-currency-display/index.js +++ b/ui/app/components/app/user-preferenced-currency-display/index.js @@ -1 +1 @@ -export { default } from './user-preferenced-currency-display.component' +export { default } from './user-preferenced-currency-display.component'; diff --git a/ui/app/components/app/user-preferenced-currency-display/tests/user-preferenced-currency-display.component.test.js b/ui/app/components/app/user-preferenced-currency-display/tests/user-preferenced-currency-display.component.test.js index 4c2533de5..7b57d9265 100644 --- a/ui/app/components/app/user-preferenced-currency-display/tests/user-preferenced-currency-display.component.test.js +++ b/ui/app/components/app/user-preferenced-currency-display/tests/user-preferenced-currency-display.component.test.js @@ -1,40 +1,40 @@ -import assert from 'assert' -import React from 'react' -import { shallow } from 'enzyme' -import sinon from 'sinon' -import UserPreferencedCurrencyDisplay from '../user-preferenced-currency-display.component' -import CurrencyDisplay from '../../../ui/currency-display' -import * as currencyHook from '../../../../hooks/useCurrencyDisplay' -import * as currencyPrefHook from '../../../../hooks/useUserPreferencedCurrency' +import assert from 'assert'; +import React from 'react'; +import { shallow } from 'enzyme'; +import sinon from 'sinon'; +import UserPreferencedCurrencyDisplay from '../user-preferenced-currency-display.component'; +import CurrencyDisplay from '../../../ui/currency-display'; +import * as currencyHook from '../../../../hooks/useCurrencyDisplay'; +import * as currencyPrefHook from '../../../../hooks/useUserPreferencedCurrency'; describe('UserPreferencedCurrencyDisplay Component', function () { describe('rendering', function () { beforeEach(function () { - sinon.stub(currencyHook, 'useCurrencyDisplay').returns(['1', {}]) + sinon.stub(currencyHook, 'useCurrencyDisplay').returns(['1', {}]); sinon .stub(currencyPrefHook, 'useUserPreferencedCurrency') - .returns({ currency: 'ETH', decimals: 6 }) - }) + .returns({ currency: 'ETH', decimals: 6 }); + }); it('should render properly', function () { - const wrapper = shallow() + const wrapper = shallow(); - assert.ok(wrapper) - assert.strictEqual(wrapper.find(CurrencyDisplay).length, 1) - }) + assert.ok(wrapper); + assert.strictEqual(wrapper.find(CurrencyDisplay).length, 1); + }); it('should pass all props to the CurrencyDisplay child component', function () { const wrapper = shallow( , - ) + ); - assert.ok(wrapper) - assert.strictEqual(wrapper.find(CurrencyDisplay).length, 1) - assert.strictEqual(wrapper.find(CurrencyDisplay).props().prop1, true) - assert.strictEqual(wrapper.find(CurrencyDisplay).props().prop2, 'test') - assert.strictEqual(wrapper.find(CurrencyDisplay).props().prop3, 1) - }) + assert.ok(wrapper); + assert.strictEqual(wrapper.find(CurrencyDisplay).length, 1); + assert.strictEqual(wrapper.find(CurrencyDisplay).props().prop1, true); + assert.strictEqual(wrapper.find(CurrencyDisplay).props().prop2, 'test'); + assert.strictEqual(wrapper.find(CurrencyDisplay).props().prop3, 1); + }); afterEach(function () { - sinon.restore() - }) - }) -}) + sinon.restore(); + }); + }); +}); diff --git a/ui/app/components/app/user-preferenced-currency-display/user-preferenced-currency-display.component.js b/ui/app/components/app/user-preferenced-currency-display/user-preferenced-currency-display.component.js index 8496d7ca1..dfcc235e2 100644 --- a/ui/app/components/app/user-preferenced-currency-display/user-preferenced-currency-display.component.js +++ b/ui/app/components/app/user-preferenced-currency-display/user-preferenced-currency-display.component.js @@ -1,8 +1,8 @@ -import React, { useMemo } from 'react' -import PropTypes from 'prop-types' -import { PRIMARY, SECONDARY, ETH } from '../../../helpers/constants/common' -import CurrencyDisplay from '../../ui/currency-display' -import { useUserPreferencedCurrency } from '../../../hooks/useUserPreferencedCurrency' +import React, { useMemo } from 'react'; +import PropTypes from 'prop-types'; +import { PRIMARY, SECONDARY, ETH } from '../../../helpers/constants/common'; +import CurrencyDisplay from '../../ui/currency-display'; +import { useUserPreferencedCurrency } from '../../../hooks/useUserPreferencedCurrency'; export default function UserPreferencedCurrencyDisplay({ 'data-testid': dataTestId, @@ -18,13 +18,13 @@ export default function UserPreferencedCurrencyDisplay({ ethNumberOfDecimals, fiatNumberOfDecimals, numberOfDecimals: propsNumberOfDecimals, - }) + }); const prefixComponent = useMemo(() => { return ( currency === ETH && showEthLogo && - ) - }, [currency, showEthLogo, ethLogoHeight]) + ); + }, [currency, showEthLogo, ethLogoHeight]); return ( - ) + ); } UserPreferencedCurrencyDisplay.propTypes = { @@ -57,4 +57,4 @@ UserPreferencedCurrencyDisplay.propTypes = { PropTypes.string, PropTypes.number, ]), -} +}; diff --git a/ui/app/components/app/user-preferenced-currency-input/index.js b/ui/app/components/app/user-preferenced-currency-input/index.js index 4dc70db3d..36ca1ca49 100644 --- a/ui/app/components/app/user-preferenced-currency-input/index.js +++ b/ui/app/components/app/user-preferenced-currency-input/index.js @@ -1 +1 @@ -export { default } from './user-preferenced-currency-input.container' +export { default } from './user-preferenced-currency-input.container'; diff --git a/ui/app/components/app/user-preferenced-currency-input/tests/user-preferenced-currency-input.component.test.js b/ui/app/components/app/user-preferenced-currency-input/tests/user-preferenced-currency-input.component.test.js index 30052e039..f0c704459 100644 --- a/ui/app/components/app/user-preferenced-currency-input/tests/user-preferenced-currency-input.component.test.js +++ b/ui/app/components/app/user-preferenced-currency-input/tests/user-preferenced-currency-input.component.test.js @@ -1,28 +1,28 @@ -import assert from 'assert' -import React from 'react' -import { shallow } from 'enzyme' -import UserPreferencedCurrencyInput from '../user-preferenced-currency-input.component' -import CurrencyInput from '../../../ui/currency-input' +import assert from 'assert'; +import React from 'react'; +import { shallow } from 'enzyme'; +import UserPreferencedCurrencyInput from '../user-preferenced-currency-input.component'; +import CurrencyInput from '../../../ui/currency-input'; describe('UserPreferencedCurrencyInput Component', function () { describe('rendering', function () { it('should render properly', function () { - const wrapper = shallow() + const wrapper = shallow(); - assert.ok(wrapper) - assert.strictEqual(wrapper.find(CurrencyInput).length, 1) - }) + assert.ok(wrapper); + assert.strictEqual(wrapper.find(CurrencyInput).length, 1); + }); it('should render useFiat for CurrencyInput based on preferences.useNativeCurrencyAsPrimaryCurrency', function () { const wrapper = shallow( , - ) + ); - assert.ok(wrapper) - assert.strictEqual(wrapper.find(CurrencyInput).length, 1) - assert.strictEqual(wrapper.find(CurrencyInput).props().useFiat, false) - wrapper.setProps({ useNativeCurrencyAsPrimaryCurrency: false }) - assert.strictEqual(wrapper.find(CurrencyInput).props().useFiat, true) - }) - }) -}) + assert.ok(wrapper); + assert.strictEqual(wrapper.find(CurrencyInput).length, 1); + assert.strictEqual(wrapper.find(CurrencyInput).props().useFiat, false); + wrapper.setProps({ useNativeCurrencyAsPrimaryCurrency: false }); + assert.strictEqual(wrapper.find(CurrencyInput).props().useFiat, true); + }); + }); +}); diff --git a/ui/app/components/app/user-preferenced-currency-input/tests/user-preferenced-currency-input.container.test.js b/ui/app/components/app/user-preferenced-currency-input/tests/user-preferenced-currency-input.container.test.js index a687d469d..40234c9c5 100644 --- a/ui/app/components/app/user-preferenced-currency-input/tests/user-preferenced-currency-input.container.test.js +++ b/ui/app/components/app/user-preferenced-currency-input/tests/user-preferenced-currency-input.container.test.js @@ -1,16 +1,16 @@ -import assert from 'assert' -import proxyquire from 'proxyquire' +import assert from 'assert'; +import proxyquire from 'proxyquire'; -let mapStateToProps +let mapStateToProps; proxyquire('../user-preferenced-currency-input.container.js', { 'react-redux': { connect: (ms) => { - mapStateToProps = ms - return () => ({}) + mapStateToProps = ms; + return () => ({}); }, }, -}) +}); describe('UserPreferencedCurrencyInput container', function () { describe('mapStateToProps()', function () { @@ -21,11 +21,11 @@ describe('UserPreferencedCurrencyInput container', function () { useNativeCurrencyAsPrimaryCurrency: true, }, }, - } + }; assert.deepStrictEqual(mapStateToProps(mockState), { useNativeCurrencyAsPrimaryCurrency: true, - }) - }) - }) -}) + }); + }); + }); +}); diff --git a/ui/app/components/app/user-preferenced-currency-input/user-preferenced-currency-input.component.js b/ui/app/components/app/user-preferenced-currency-input/user-preferenced-currency-input.component.js index f92a74b1d..abd8cabfb 100644 --- a/ui/app/components/app/user-preferenced-currency-input/user-preferenced-currency-input.component.js +++ b/ui/app/components/app/user-preferenced-currency-input/user-preferenced-currency-input.component.js @@ -1,20 +1,20 @@ -import React, { PureComponent } from 'react' -import PropTypes from 'prop-types' -import CurrencyInput from '../../ui/currency-input' +import React, { PureComponent } from 'react'; +import PropTypes from 'prop-types'; +import CurrencyInput from '../../ui/currency-input'; export default class UserPreferencedCurrencyInput extends PureComponent { static propTypes = { useNativeCurrencyAsPrimaryCurrency: PropTypes.bool, - } + }; render() { - const { useNativeCurrencyAsPrimaryCurrency, ...restProps } = this.props + const { useNativeCurrencyAsPrimaryCurrency, ...restProps } = this.props; return ( - ) + ); } } diff --git a/ui/app/components/app/user-preferenced-currency-input/user-preferenced-currency-input.container.js b/ui/app/components/app/user-preferenced-currency-input/user-preferenced-currency-input.container.js index 2cce58027..e04e0c689 100644 --- a/ui/app/components/app/user-preferenced-currency-input/user-preferenced-currency-input.container.js +++ b/ui/app/components/app/user-preferenced-currency-input/user-preferenced-currency-input.container.js @@ -1,13 +1,13 @@ -import { connect } from 'react-redux' -import { getPreferences } from '../../../selectors' -import UserPreferencedCurrencyInput from './user-preferenced-currency-input.component' +import { connect } from 'react-redux'; +import { getPreferences } from '../../../selectors'; +import UserPreferencedCurrencyInput from './user-preferenced-currency-input.component'; const mapStateToProps = (state) => { - const { useNativeCurrencyAsPrimaryCurrency } = getPreferences(state) + const { useNativeCurrencyAsPrimaryCurrency } = getPreferences(state); return { useNativeCurrencyAsPrimaryCurrency, - } -} + }; +}; -export default connect(mapStateToProps)(UserPreferencedCurrencyInput) +export default connect(mapStateToProps)(UserPreferencedCurrencyInput); diff --git a/ui/app/components/app/user-preferenced-token-input/index.js b/ui/app/components/app/user-preferenced-token-input/index.js index 54167e633..454444e2f 100644 --- a/ui/app/components/app/user-preferenced-token-input/index.js +++ b/ui/app/components/app/user-preferenced-token-input/index.js @@ -1 +1 @@ -export { default } from './user-preferenced-token-input.container' +export { default } from './user-preferenced-token-input.container'; diff --git a/ui/app/components/app/user-preferenced-token-input/tests/user-preferenced-token-input.component.test.js b/ui/app/components/app/user-preferenced-token-input/tests/user-preferenced-token-input.component.test.js index dcc5b6874..3fc20f657 100644 --- a/ui/app/components/app/user-preferenced-token-input/tests/user-preferenced-token-input.component.test.js +++ b/ui/app/components/app/user-preferenced-token-input/tests/user-preferenced-token-input.component.test.js @@ -1,19 +1,19 @@ -import assert from 'assert' -import React from 'react' -import { shallow } from 'enzyme' -import UserPreferencedTokenInput from '../user-preferenced-token-input.component' -import TokenInput from '../../../ui/token-input' +import assert from 'assert'; +import React from 'react'; +import { shallow } from 'enzyme'; +import UserPreferencedTokenInput from '../user-preferenced-token-input.component'; +import TokenInput from '../../../ui/token-input'; describe('UserPreferencedCurrencyInput Component', function () { describe('rendering', function () { it('should render properly', function () { const wrapper = shallow( , - ) + ); - assert.ok(wrapper) - assert.strictEqual(wrapper.find(TokenInput).length, 1) - }) + assert.ok(wrapper); + assert.strictEqual(wrapper.find(TokenInput).length, 1); + }); it('should render showFiat for TokenInput based on preferences.useNativeCurrencyAsPrimaryCurrency', function () { const wrapper = shallow( @@ -21,13 +21,13 @@ describe('UserPreferencedCurrencyInput Component', function () { token={{ address: '0x0' }} useNativeCurrencyAsPrimaryCurrency />, - ) + ); - assert.ok(wrapper) - assert.strictEqual(wrapper.find(TokenInput).length, 1) - assert.strictEqual(wrapper.find(TokenInput).props().showFiat, false) - wrapper.setProps({ useNativeCurrencyAsPrimaryCurrency: false }) - assert.strictEqual(wrapper.find(TokenInput).props().showFiat, true) - }) - }) -}) + assert.ok(wrapper); + assert.strictEqual(wrapper.find(TokenInput).length, 1); + assert.strictEqual(wrapper.find(TokenInput).props().showFiat, false); + wrapper.setProps({ useNativeCurrencyAsPrimaryCurrency: false }); + assert.strictEqual(wrapper.find(TokenInput).props().showFiat, true); + }); + }); +}); diff --git a/ui/app/components/app/user-preferenced-token-input/tests/user-preferenced-token-input.container.test.js b/ui/app/components/app/user-preferenced-token-input/tests/user-preferenced-token-input.container.test.js index 8011f4885..9ff33f0f5 100644 --- a/ui/app/components/app/user-preferenced-token-input/tests/user-preferenced-token-input.container.test.js +++ b/ui/app/components/app/user-preferenced-token-input/tests/user-preferenced-token-input.container.test.js @@ -1,16 +1,16 @@ -import assert from 'assert' -import proxyquire from 'proxyquire' +import assert from 'assert'; +import proxyquire from 'proxyquire'; -let mapStateToProps +let mapStateToProps; proxyquire('../user-preferenced-token-input.container.js', { 'react-redux': { connect: (ms) => { - mapStateToProps = ms - return () => ({}) + mapStateToProps = ms; + return () => ({}); }, }, -}) +}); describe('UserPreferencedTokenInput container', function () { describe('mapStateToProps()', function () { @@ -21,11 +21,11 @@ describe('UserPreferencedTokenInput container', function () { useNativeCurrencyAsPrimaryCurrency: true, }, }, - } + }; assert.deepStrictEqual(mapStateToProps(mockState), { useNativeCurrencyAsPrimaryCurrency: true, - }) - }) - }) -}) + }); + }); + }); +}); diff --git a/ui/app/components/app/user-preferenced-token-input/user-preferenced-token-input.component.js b/ui/app/components/app/user-preferenced-token-input/user-preferenced-token-input.component.js index 6e26b6dec..d08e54701 100644 --- a/ui/app/components/app/user-preferenced-token-input/user-preferenced-token-input.component.js +++ b/ui/app/components/app/user-preferenced-token-input/user-preferenced-token-input.component.js @@ -1,6 +1,6 @@ -import React, { PureComponent } from 'react' -import PropTypes from 'prop-types' -import TokenInput from '../../ui/token-input' +import React, { PureComponent } from 'react'; +import PropTypes from 'prop-types'; +import TokenInput from '../../ui/token-input'; export default class UserPreferencedTokenInput extends PureComponent { static propTypes = { @@ -10,16 +10,16 @@ export default class UserPreferencedTokenInput extends PureComponent { symbol: PropTypes.string, }).isRequired, useNativeCurrencyAsPrimaryCurrency: PropTypes.bool, - } + }; render() { - const { useNativeCurrencyAsPrimaryCurrency, ...restProps } = this.props + const { useNativeCurrencyAsPrimaryCurrency, ...restProps } = this.props; return ( - ) + ); } } diff --git a/ui/app/components/app/user-preferenced-token-input/user-preferenced-token-input.container.js b/ui/app/components/app/user-preferenced-token-input/user-preferenced-token-input.container.js index 1d8799d30..33afd8ce2 100644 --- a/ui/app/components/app/user-preferenced-token-input/user-preferenced-token-input.container.js +++ b/ui/app/components/app/user-preferenced-token-input/user-preferenced-token-input.container.js @@ -1,19 +1,19 @@ -import { connect } from 'react-redux' -import PropTypes from 'prop-types' -import { getPreferences } from '../../../selectors' -import UserPreferencedTokenInput from './user-preferenced-token-input.component' +import { connect } from 'react-redux'; +import PropTypes from 'prop-types'; +import { getPreferences } from '../../../selectors'; +import UserPreferencedTokenInput from './user-preferenced-token-input.component'; const mapStateToProps = (state) => { - const { useNativeCurrencyAsPrimaryCurrency } = getPreferences(state) + const { useNativeCurrencyAsPrimaryCurrency } = getPreferences(state); return { useNativeCurrencyAsPrimaryCurrency, - } -} + }; +}; const UserPreferencedTokenInputContainer = connect(mapStateToProps)( UserPreferencedTokenInput, -) +); UserPreferencedTokenInputContainer.propTypes = { token: PropTypes.shape({ @@ -21,6 +21,6 @@ UserPreferencedTokenInputContainer.propTypes = { decimals: PropTypes.number, symbol: PropTypes.string, }).isRequired, -} +}; -export default UserPreferencedTokenInputContainer +export default UserPreferencedTokenInputContainer; diff --git a/ui/app/components/app/wallet-overview/eth-overview.js b/ui/app/components/app/wallet-overview/eth-overview.js index 69aef6382..17bcb8673 100644 --- a/ui/app/components/app/wallet-overview/eth-overview.js +++ b/ui/app/components/app/wallet-overview/eth-overview.js @@ -1,74 +1,74 @@ -import React, { useContext } from 'react' -import PropTypes from 'prop-types' -import { useDispatch, useSelector } from 'react-redux' -import classnames from 'classnames' -import { useHistory } from 'react-router-dom' +import React, { useContext } from 'react'; +import PropTypes from 'prop-types'; +import { useDispatch, useSelector } from 'react-redux'; +import classnames from 'classnames'; +import { useHistory } from 'react-router-dom'; -import Identicon from '../../ui/identicon' -import { I18nContext } from '../../../contexts/i18n' +import Identicon from '../../ui/identicon'; +import { I18nContext } from '../../../contexts/i18n'; import { SEND_ROUTE, BUILD_QUOTE_ROUTE, -} from '../../../helpers/constants/routes' +} from '../../../helpers/constants/routes'; import { useMetricEvent, useNewMetricEvent, -} from '../../../hooks/useMetricEvent' -import { useSwapsEthToken } from '../../../hooks/useSwapsEthToken' -import Tooltip from '../../ui/tooltip' -import UserPreferencedCurrencyDisplay from '../user-preferenced-currency-display' -import { PRIMARY, SECONDARY } from '../../../helpers/constants/common' -import { showModal } from '../../../store/actions' +} from '../../../hooks/useMetricEvent'; +import { useSwapsEthToken } from '../../../hooks/useSwapsEthToken'; +import Tooltip from '../../ui/tooltip'; +import UserPreferencedCurrencyDisplay from '../user-preferenced-currency-display'; +import { PRIMARY, SECONDARY } from '../../../helpers/constants/common'; +import { showModal } from '../../../store/actions'; import { isBalanceCached, getSelectedAccount, getShouldShowFiat, getCurrentChainId, getCurrentKeyring, -} from '../../../selectors/selectors' -import SwapIcon from '../../ui/icon/swap-icon.component' -import BuyIcon from '../../ui/icon/overview-buy-icon.component' -import SendIcon from '../../ui/icon/overview-send-icon.component' +} from '../../../selectors/selectors'; +import SwapIcon from '../../ui/icon/swap-icon.component'; +import BuyIcon from '../../ui/icon/overview-buy-icon.component'; +import SendIcon from '../../ui/icon/overview-send-icon.component'; import { getSwapsFeatureLiveness, setSwapsFromToken, -} from '../../../ducks/swaps/swaps' -import IconButton from '../../ui/icon-button' -import { MAINNET_CHAIN_ID } from '../../../../../shared/constants/network' -import WalletOverview from './wallet-overview' +} from '../../../ducks/swaps/swaps'; +import IconButton from '../../ui/icon-button'; +import { MAINNET_CHAIN_ID } from '../../../../../shared/constants/network'; +import WalletOverview from './wallet-overview'; const EthOverview = ({ className }) => { - const dispatch = useDispatch() - const t = useContext(I18nContext) + const dispatch = useDispatch(); + const t = useContext(I18nContext); const sendEvent = useMetricEvent({ eventOpts: { category: 'Navigation', action: 'Home', name: 'Clicked Send: Eth', }, - }) + }); const depositEvent = useMetricEvent({ eventOpts: { category: 'Navigation', action: 'Home', name: 'Clicked Deposit', }, - }) - const history = useHistory() - const keyring = useSelector(getCurrentKeyring) - const usingHardwareWallet = keyring.type.search('Hardware') !== -1 - const balanceIsCached = useSelector(isBalanceCached) - const showFiat = useSelector(getShouldShowFiat) - const selectedAccount = useSelector(getSelectedAccount) - const { balance } = selectedAccount - const chainId = useSelector(getCurrentChainId) + }); + const history = useHistory(); + const keyring = useSelector(getCurrentKeyring); + const usingHardwareWallet = keyring.type.search('Hardware') !== -1; + const balanceIsCached = useSelector(isBalanceCached); + const showFiat = useSelector(getShouldShowFiat); + const selectedAccount = useSelector(getSelectedAccount); + const { balance } = selectedAccount; + const chainId = useSelector(getCurrentChainId); const enteredSwapsEvent = useNewMetricEvent({ event: 'Swaps Opened', properties: { source: 'Main View', active_currency: 'ETH' }, category: 'swaps', - }) - const swapsEnabled = useSelector(getSwapsFeatureLiveness) - const swapsEthToken = useSwapsEthToken() + }); + const swapsEnabled = useSelector(getSwapsFeatureLiveness); + const swapsEthToken = useSwapsEthToken(); return ( { Icon={BuyIcon} label={t('buy')} onClick={() => { - depositEvent() - dispatch(showModal({ name: 'DEPOSIT_ETHER' })) + depositEvent(); + dispatch(showModal({ name: 'DEPOSIT_ETHER' })); }} /> { Icon={SendIcon} label={t('send')} onClick={() => { - sendEvent() - history.push(SEND_ROUTE) + sendEvent(); + history.push(SEND_ROUTE); }} /> {swapsEnabled ? ( @@ -138,12 +138,12 @@ const EthOverview = ({ className }) => { Icon={SwapIcon} onClick={() => { if (chainId === MAINNET_CHAIN_ID) { - enteredSwapsEvent() - dispatch(setSwapsFromToken(swapsEthToken)) + enteredSwapsEvent(); + dispatch(setSwapsFromToken(swapsEthToken)); if (usingHardwareWallet) { - global.platform.openExtensionInBrowser(BUILD_QUOTE_ROUTE) + global.platform.openExtensionInBrowser(BUILD_QUOTE_ROUTE); } else { - history.push(BUILD_QUOTE_ROUTE) + history.push(BUILD_QUOTE_ROUTE); } } }} @@ -164,15 +164,15 @@ const EthOverview = ({ className }) => { className={className} icon={} /> - ) -} + ); +}; EthOverview.propTypes = { className: PropTypes.string, -} +}; EthOverview.defaultProps = { className: undefined, -} +}; -export default EthOverview +export default EthOverview; diff --git a/ui/app/components/app/wallet-overview/index.js b/ui/app/components/app/wallet-overview/index.js index e8205ea58..d0142dbf1 100644 --- a/ui/app/components/app/wallet-overview/index.js +++ b/ui/app/components/app/wallet-overview/index.js @@ -1,2 +1,2 @@ -export { default as EthOverview } from './eth-overview' -export { default as TokenOverview } from './token-overview' +export { default as EthOverview } from './eth-overview'; +export { default as TokenOverview } from './token-overview'; diff --git a/ui/app/components/app/wallet-overview/token-overview.js b/ui/app/components/app/wallet-overview/token-overview.js index 58b5673db..e705461d9 100644 --- a/ui/app/components/app/wallet-overview/token-overview.js +++ b/ui/app/components/app/wallet-overview/token-overview.js @@ -1,70 +1,70 @@ -import React, { useContext } from 'react' -import PropTypes from 'prop-types' -import { useDispatch, useSelector } from 'react-redux' -import { useHistory } from 'react-router-dom' +import React, { useContext } from 'react'; +import PropTypes from 'prop-types'; +import { useDispatch, useSelector } from 'react-redux'; +import { useHistory } from 'react-router-dom'; -import Identicon from '../../ui/identicon' -import Tooltip from '../../ui/tooltip' -import CurrencyDisplay from '../../ui/currency-display' -import { I18nContext } from '../../../contexts/i18n' +import Identicon from '../../ui/identicon'; +import Tooltip from '../../ui/tooltip'; +import CurrencyDisplay from '../../ui/currency-display'; +import { I18nContext } from '../../../contexts/i18n'; import { SEND_ROUTE, BUILD_QUOTE_ROUTE, -} from '../../../helpers/constants/routes' +} from '../../../helpers/constants/routes'; import { useMetricEvent, useNewMetricEvent, -} from '../../../hooks/useMetricEvent' -import { useTokenTracker } from '../../../hooks/useTokenTracker' -import { useTokenFiatAmount } from '../../../hooks/useTokenFiatAmount' -import { updateSendToken } from '../../../store/actions' +} from '../../../hooks/useMetricEvent'; +import { useTokenTracker } from '../../../hooks/useTokenTracker'; +import { useTokenFiatAmount } from '../../../hooks/useTokenFiatAmount'; +import { updateSendToken } from '../../../store/actions'; import { getSwapsFeatureLiveness, setSwapsFromToken, -} from '../../../ducks/swaps/swaps' +} from '../../../ducks/swaps/swaps'; import { getAssetImages, getCurrentKeyring, getCurrentChainId, -} from '../../../selectors/selectors' -import { MAINNET_CHAIN_ID } from '../../../../../shared/constants/network' +} from '../../../selectors/selectors'; +import { MAINNET_CHAIN_ID } from '../../../../../shared/constants/network'; -import SwapIcon from '../../ui/icon/swap-icon.component' -import SendIcon from '../../ui/icon/overview-send-icon.component' +import SwapIcon from '../../ui/icon/swap-icon.component'; +import SendIcon from '../../ui/icon/overview-send-icon.component'; -import IconButton from '../../ui/icon-button' -import WalletOverview from './wallet-overview' +import IconButton from '../../ui/icon-button'; +import WalletOverview from './wallet-overview'; const TokenOverview = ({ className, token }) => { - const dispatch = useDispatch() - const t = useContext(I18nContext) + const dispatch = useDispatch(); + const t = useContext(I18nContext); const sendTokenEvent = useMetricEvent({ eventOpts: { category: 'Navigation', action: 'Home', name: 'Clicked Send: Token', }, - }) - const history = useHistory() - const assetImages = useSelector(getAssetImages) + }); + const history = useHistory(); + const assetImages = useSelector(getAssetImages); - const keyring = useSelector(getCurrentKeyring) - const usingHardwareWallet = keyring.type.search('Hardware') !== -1 - const { tokensWithBalances } = useTokenTracker([token]) - const balanceToRender = tokensWithBalances[0]?.string - const balance = tokensWithBalances[0]?.balance + const keyring = useSelector(getCurrentKeyring); + const usingHardwareWallet = keyring.type.search('Hardware') !== -1; + const { tokensWithBalances } = useTokenTracker([token]); + const balanceToRender = tokensWithBalances[0]?.string; + const balance = tokensWithBalances[0]?.balance; const formattedFiatBalance = useTokenFiatAmount( token.address, balanceToRender, token.symbol, - ) - const chainId = useSelector(getCurrentChainId) + ); + const chainId = useSelector(getCurrentChainId); const enteredSwapsEvent = useNewMetricEvent({ event: 'Swaps Opened', properties: { source: 'Token View', active_currency: token.symbol }, category: 'swaps', - }) - const swapsEnabled = useSelector(getSwapsFeatureLiveness) + }); + const swapsEnabled = useSelector(getSwapsFeatureLiveness); return ( { { - sendTokenEvent() - dispatch(updateSendToken(token)) - history.push(SEND_ROUTE) + sendTokenEvent(); + dispatch(updateSendToken(token)); + history.push(SEND_ROUTE); }} Icon={SendIcon} label={t('send')} @@ -104,7 +104,7 @@ const TokenOverview = ({ className, token }) => { Icon={SwapIcon} onClick={() => { if (chainId === MAINNET_CHAIN_ID) { - enteredSwapsEvent() + enteredSwapsEvent(); dispatch( setSwapsFromToken({ ...token, @@ -112,11 +112,11 @@ const TokenOverview = ({ className, token }) => { balance, string: balanceToRender, }), - ) + ); if (usingHardwareWallet) { - global.platform.openExtensionInBrowser(BUILD_QUOTE_ROUTE) + global.platform.openExtensionInBrowser(BUILD_QUOTE_ROUTE); } else { - history.push(BUILD_QUOTE_ROUTE) + history.push(BUILD_QUOTE_ROUTE); } } }} @@ -143,8 +143,8 @@ const TokenOverview = ({ className, token }) => { /> } /> - ) -} + ); +}; TokenOverview.propTypes = { className: PropTypes.string, @@ -153,10 +153,10 @@ TokenOverview.propTypes = { decimals: PropTypes.number, symbol: PropTypes.string, }).isRequired, -} +}; TokenOverview.defaultProps = { className: undefined, -} +}; -export default TokenOverview +export default TokenOverview; diff --git a/ui/app/components/app/wallet-overview/wallet-overview.js b/ui/app/components/app/wallet-overview/wallet-overview.js index b4ca1b4ff..6f5d1341d 100644 --- a/ui/app/components/app/wallet-overview/wallet-overview.js +++ b/ui/app/components/app/wallet-overview/wallet-overview.js @@ -1,6 +1,6 @@ -import React from 'react' -import PropTypes from 'prop-types' -import classnames from 'classnames' +import React from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; const WalletOverview = ({ balance, buttons, className, icon }) => { return ( @@ -11,18 +11,18 @@ const WalletOverview = ({ balance, buttons, className, icon }) => {
    {buttons}
    - ) -} + ); +}; WalletOverview.propTypes = { balance: PropTypes.element.isRequired, buttons: PropTypes.element.isRequired, className: PropTypes.string, icon: PropTypes.element.isRequired, -} +}; WalletOverview.defaultProps = { className: undefined, -} +}; -export default WalletOverview +export default WalletOverview; diff --git a/ui/app/components/ui/account-mismatch-warning/account-mismatch-warning.component.js b/ui/app/components/ui/account-mismatch-warning/account-mismatch-warning.component.js index 6fcb10e15..797ce0014 100644 --- a/ui/app/components/ui/account-mismatch-warning/account-mismatch-warning.component.js +++ b/ui/app/components/ui/account-mismatch-warning/account-mismatch-warning.component.js @@ -1,17 +1,17 @@ -import React from 'react' -import { useSelector } from 'react-redux' -import PropTypes from 'prop-types' -import Tooltip from '../tooltip' -import { getSelectedAccount } from '../../../selectors' -import InfoIcon from '../icon/info-icon.component' -import { useI18nContext } from '../../../hooks/useI18nContext' -import { SEVERITIES } from '../../../helpers/constants/design-system' +import React from 'react'; +import { useSelector } from 'react-redux'; +import PropTypes from 'prop-types'; +import Tooltip from '../tooltip'; +import { getSelectedAccount } from '../../../selectors'; +import InfoIcon from '../icon/info-icon.component'; +import { useI18nContext } from '../../../hooks/useI18nContext'; +import { SEVERITIES } from '../../../helpers/constants/design-system'; export default function AccountMismatchWarning({ address }) { - const selectedAccount = useSelector(getSelectedAccount) - const t = useI18nContext() + const selectedAccount = useSelector(getSelectedAccount); + const t = useI18nContext(); if (selectedAccount.address === address) { - return null + return null; } return ( @@ -25,9 +25,9 @@ export default function AccountMismatchWarning({ address }) { - ) + ); } AccountMismatchWarning.propTypes = { address: PropTypes.string.isRequired, -} +}; diff --git a/ui/app/components/ui/account-mismatch-warning/tests/acccount-mismatch-warning.component.test.js b/ui/app/components/ui/account-mismatch-warning/tests/acccount-mismatch-warning.component.test.js index 733d81241..febddd53b 100644 --- a/ui/app/components/ui/account-mismatch-warning/tests/acccount-mismatch-warning.component.test.js +++ b/ui/app/components/ui/account-mismatch-warning/tests/acccount-mismatch-warning.component.test.js @@ -1,32 +1,34 @@ -import assert from 'assert' -import React from 'react' -import * as reactRedux from 'react-redux' -import sinon from 'sinon' -import { shallow } from 'enzyme' -import InfoIcon from '../../icon/info-icon.component' -import AccountMismatchWarning from '../account-mismatch-warning.component' -import { getSelectedAccount } from '../../../../selectors' +import assert from 'assert'; +import React from 'react'; +import * as reactRedux from 'react-redux'; +import sinon from 'sinon'; +import { shallow } from 'enzyme'; +import InfoIcon from '../../icon/info-icon.component'; +import AccountMismatchWarning from '../account-mismatch-warning.component'; +import { getSelectedAccount } from '../../../../selectors'; describe('AccountMismatchWarning', function () { before(function () { sinon.stub(reactRedux, 'useSelector').callsFake((selector) => { if (selector === getSelectedAccount) { - return { address: 'mockedAddress' } + return { address: 'mockedAddress' }; } throw new Error( `${selector.name} is not cared for in the AccountMismatchWarning test useSelector stub`, - ) - }) - }) + ); + }); + }); it('renders nothing when the addresses match', function () { - const wrapper = shallow() - assert.strictEqual(wrapper.find(InfoIcon).length, 0) - }) + const wrapper = shallow(); + assert.strictEqual(wrapper.find(InfoIcon).length, 0); + }); it('renders a warning info icon when addresses do not match', function () { - const wrapper = shallow() - assert.strictEqual(wrapper.find(InfoIcon).length, 1) - }) + const wrapper = shallow( + , + ); + assert.strictEqual(wrapper.find(InfoIcon).length, 1); + }); after(function () { - sinon.restore() - }) -}) + sinon.restore(); + }); +}); diff --git a/ui/app/components/ui/alert-circle-icon/alert-circle-icon.component.js b/ui/app/components/ui/alert-circle-icon/alert-circle-icon.component.js index 7c8a37aaa..71eca7783 100644 --- a/ui/app/components/ui/alert-circle-icon/alert-circle-icon.component.js +++ b/ui/app/components/ui/alert-circle-icon/alert-circle-icon.component.js @@ -1,6 +1,6 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import CircleIcon from '../circle-icon' +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import CircleIcon from '../circle-icon'; const typeConfig = { danger: { @@ -11,14 +11,14 @@ const typeConfig = { circleClass: 'alert-circle-icon--warning', iconSource: 'images/icons/yellow-bell.svg', }, -} +}; export default class AlertCircleIcon extends Component { static propTypes = { type: PropTypes.oneOf(Object.keys(typeConfig)).isRequired, - } + }; render() { - return + return ; } } diff --git a/ui/app/components/ui/alert-circle-icon/alert-circle-icon.stories.js b/ui/app/components/ui/alert-circle-icon/alert-circle-icon.stories.js index 8b2dd5574..e4f0ec846 100644 --- a/ui/app/components/ui/alert-circle-icon/alert-circle-icon.stories.js +++ b/ui/app/components/ui/alert-circle-icon/alert-circle-icon.stories.js @@ -1,10 +1,10 @@ -import React from 'react' -import AlertCircleIcon from './alert-circle-icon.component' +import React from 'react'; +import AlertCircleIcon from './alert-circle-icon.component'; export default { title: 'AlertCircleIcon', -} +}; -export const dangerCircleIcon = () => +export const dangerCircleIcon = () => ; -export const warningCircleIcon = () => +export const warningCircleIcon = () => ; diff --git a/ui/app/components/ui/alert-circle-icon/index.js b/ui/app/components/ui/alert-circle-icon/index.js index 3cf319925..80ab7a4c9 100644 --- a/ui/app/components/ui/alert-circle-icon/index.js +++ b/ui/app/components/ui/alert-circle-icon/index.js @@ -1 +1 @@ -export { default } from './alert-circle-icon.component' +export { default } from './alert-circle-icon.component'; diff --git a/ui/app/components/ui/alert/index.js b/ui/app/components/ui/alert/index.js index e04778569..44677cf0b 100644 --- a/ui/app/components/ui/alert/index.js +++ b/ui/app/components/ui/alert/index.js @@ -1,19 +1,19 @@ -import classnames from 'classnames' -import PropTypes from 'prop-types' -import React, { Component } from 'react' +import classnames from 'classnames'; +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; class Alert extends Component { state = { visible: false, msg: false, className: '', - } + }; UNSAFE_componentWillReceiveProps(nextProps) { if (!this.props.visible && nextProps.visible) { - this.animateIn(nextProps.msg) + this.animateIn(nextProps.msg); } else if (this.props.visible && !nextProps.visible) { - this.animateOut() + this.animateOut(); } } @@ -22,18 +22,18 @@ class Alert extends Component { msg, visible: true, className: 'visible', - }) + }); } animateOut() { this.setState({ msg: null, className: 'hidden', - }) + }); setTimeout((_) => { - this.setState({ visible: false }) - }, 500) + this.setState({ visible: false }); + }, 500); } render() { @@ -42,14 +42,14 @@ class Alert extends Component { - ) + ); } - return null + return null; } } Alert.propTypes = { visible: PropTypes.bool.isRequired, msg: PropTypes.string /* eslint-disable-line react/no-unused-prop-types */, -} -export default Alert +}; +export default Alert; diff --git a/ui/app/components/ui/alert/tests/alert.test.js b/ui/app/components/ui/alert/tests/alert.test.js index c8d36528b..64c519e0e 100644 --- a/ui/app/components/ui/alert/tests/alert.test.js +++ b/ui/app/components/ui/alert/tests/alert.test.js @@ -1,41 +1,41 @@ -import assert from 'assert' -import React from 'react' -import sinon from 'sinon' -import { shallow } from 'enzyme' -import Alert from '..' +import assert from 'assert'; +import React from 'react'; +import sinon from 'sinon'; +import { shallow } from 'enzyme'; +import Alert from '..'; describe('Alert', function () { - let wrapper + let wrapper; beforeEach(function () { - wrapper = shallow() - }) + wrapper = shallow(); + }); it('renders nothing with no visible boolean in state', function () { - const alert = wrapper.find('.global-alert') - assert.strictEqual(alert.length, 0) - }) + const alert = wrapper.find('.global-alert'); + assert.strictEqual(alert.length, 0); + }); it('renders when visible in state is true, and message', function () { - const errorMessage = 'Error Message' + const errorMessage = 'Error Message'; - wrapper.setState({ visible: true, msg: errorMessage }) + wrapper.setState({ visible: true, msg: errorMessage }); - const alert = wrapper.find('.global-alert') - assert.strictEqual(alert.length, 1) + const alert = wrapper.find('.global-alert'); + assert.strictEqual(alert.length, 1); - const errorText = wrapper.find('.msg') - assert.strictEqual(errorText.text(), errorMessage) - }) + const errorText = wrapper.find('.msg'); + assert.strictEqual(errorText.text(), errorMessage); + }); it('calls component method when componentWillReceiveProps is called', function () { - const animateInSpy = sinon.stub(wrapper.instance(), 'animateIn') - const animateOutSpy = sinon.stub(wrapper.instance(), 'animateOut') + const animateInSpy = sinon.stub(wrapper.instance(), 'animateIn'); + const animateOutSpy = sinon.stub(wrapper.instance(), 'animateOut'); - wrapper.setProps({ visible: true }) - assert(animateInSpy.calledOnce) + wrapper.setProps({ visible: true }); + assert(animateInSpy.calledOnce); - wrapper.setProps({ visible: false }) - assert(animateOutSpy.calledOnce) - }) -}) + wrapper.setProps({ visible: false }); + assert(animateOutSpy.calledOnce); + }); +}); diff --git a/ui/app/components/ui/box/box.js b/ui/app/components/ui/box/box.js index 85567e6c6..006d566ce 100644 --- a/ui/app/components/ui/box/box.js +++ b/ui/app/components/ui/box/box.js @@ -1,6 +1,6 @@ -import React from 'react' -import PropTypes from 'prop-types' -import classnames from 'classnames' +import React from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; import { ALIGN_ITEMS, BLOCK_SIZES, @@ -9,26 +9,26 @@ import { DISPLAY, JUSTIFY_CONTENT, SIZES, -} from '../../../helpers/constants/design-system' +} from '../../../helpers/constants/design-system'; -const ValidSize = PropTypes.oneOf([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]) -const ArrayOfValidSizes = PropTypes.arrayOf(ValidSize) -const MultipleSizes = PropTypes.oneOfType([ValidSize, ArrayOfValidSizes]) +const ValidSize = PropTypes.oneOf([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]); +const ArrayOfValidSizes = PropTypes.arrayOf(ValidSize); +const MultipleSizes = PropTypes.oneOfType([ValidSize, ArrayOfValidSizes]); function generateSizeClasses(baseClass, type, main, top, right, bottom, left) { - const arr = Array.isArray(main) ? main : [] - const singleDigit = Array.isArray(main) ? undefined : main + const arr = Array.isArray(main) ? main : []; + const singleDigit = Array.isArray(main) ? undefined : main; if (Array.isArray(main) && ![2, 3, 4].includes(main.length)) { throw new Error( `Expected prop ${type} to have length between 2 and 4, received ${main.length}`, - ) + ); } - const isHorizontalAndVertical = arr.length === 2 - const isTopHorizontalAndBottom = arr.length === 3 - const isAllFour = arr.length === 4 - const hasAtLeastTwo = arr.length >= 2 - const hasAtLeastThree = arr.length >= 3 + const isHorizontalAndVertical = arr.length === 2; + const isTopHorizontalAndBottom = arr.length === 3; + const isAllFour = arr.length === 4; + const hasAtLeastTwo = arr.length >= 2; + const hasAtLeastThree = arr.length >= 3; return { [`${baseClass}--${type}-${singleDigit}`]: singleDigit !== undefined, [`${baseClass}--${type}-top-${top}`]: typeof top === 'number', @@ -50,7 +50,7 @@ function generateSizeClasses(baseClass, type, main, top, right, bottom, left) { isHorizontalAndVertical || isTopHorizontalAndBottom, // If an array has 4 values, the fourth number is the left value [`${baseClass}--${type}-left-${arr?.[3]}`]: isAllFour, - } + }; } export default function Box({ @@ -117,12 +117,12 @@ export default function Box({ // width & height [`box--width-${width}`]: Boolean(width), [`box--height-${height}`]: Boolean(height), - }) + }); // Apply Box styles to any other component using function pattern if (typeof children === 'function') { - return children(boxClassName) + return children(boxClassName); } - return
    {children}
    + return
    {children}
    ; } Box.propTypes = { @@ -146,4 +146,4 @@ Box.propTypes = { display: PropTypes.oneOf(Object.values(DISPLAY)), width: PropTypes.oneOf(Object.values(BLOCK_SIZES)), height: PropTypes.oneOf(Object.values(BLOCK_SIZES)), -} +}; diff --git a/ui/app/components/ui/box/box.stories.js b/ui/app/components/ui/box/box.stories.js index bae0f257a..a76d2fff5 100644 --- a/ui/app/components/ui/box/box.stories.js +++ b/ui/app/components/ui/box/box.stories.js @@ -1,5 +1,5 @@ -import { number, select } from '@storybook/addon-knobs' -import React from 'react' +import { number, select } from '@storybook/addon-knobs'; +import React from 'react'; import { ALIGN_ITEMS, BLOCK_SIZES, @@ -7,25 +7,25 @@ import { COLORS, DISPLAY, JUSTIFY_CONTENT, -} from '../../../helpers/constants/design-system' -import Box from './box' +} from '../../../helpers/constants/design-system'; +import Box from './box'; export default { title: 'Box', -} +}; -const sizeKnobOptions = [undefined, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] +const sizeKnobOptions = [undefined, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; export const box = () => { - const items = [] + const items = []; const size = number( 'size', 100, { range: true, min: 50, max: 500, step: 10 }, 'children', - ) + ); for (let $i = 0; $i < number('items', 1, {}, 'children'); $i++) { - items.push() + items.push(); } return ( { > {items} - ) -} + ); +}; diff --git a/ui/app/components/ui/box/index.js b/ui/app/components/ui/box/index.js index e5b58f373..20292302c 100644 --- a/ui/app/components/ui/box/index.js +++ b/ui/app/components/ui/box/index.js @@ -1 +1 @@ -export { default } from './box' +export { default } from './box'; diff --git a/ui/app/components/ui/breadcrumbs/breadcrumbs.component.js b/ui/app/components/ui/breadcrumbs/breadcrumbs.component.js index 192fb1f42..c00844aa1 100644 --- a/ui/app/components/ui/breadcrumbs/breadcrumbs.component.js +++ b/ui/app/components/ui/breadcrumbs/breadcrumbs.component.js @@ -1,16 +1,16 @@ -import React, { PureComponent } from 'react' -import PropTypes from 'prop-types' -import classnames from 'classnames' +import React, { PureComponent } from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; export default class Breadcrumbs extends PureComponent { static propTypes = { className: PropTypes.string, currentIndex: PropTypes.number, total: PropTypes.number, - } + }; render() { - const { className, currentIndex, total } = this.props + const { className, currentIndex, total } = this.props; return (
    @@ -26,6 +26,6 @@ export default class Breadcrumbs extends PureComponent { /> ))}
    - ) + ); } } diff --git a/ui/app/components/ui/breadcrumbs/index.js b/ui/app/components/ui/breadcrumbs/index.js index 07a11574f..f169c7d6a 100644 --- a/ui/app/components/ui/breadcrumbs/index.js +++ b/ui/app/components/ui/breadcrumbs/index.js @@ -1 +1 @@ -export { default } from './breadcrumbs.component' +export { default } from './breadcrumbs.component'; diff --git a/ui/app/components/ui/breadcrumbs/tests/breadcrumbs.component.test.js b/ui/app/components/ui/breadcrumbs/tests/breadcrumbs.component.test.js index 9d9abbdc6..c2f7af83b 100644 --- a/ui/app/components/ui/breadcrumbs/tests/breadcrumbs.component.test.js +++ b/ui/app/components/ui/breadcrumbs/tests/breadcrumbs.component.test.js @@ -1,26 +1,26 @@ -import assert from 'assert' -import React from 'react' -import { shallow } from 'enzyme' -import Breadcrumbs from '../breadcrumbs.component' +import assert from 'assert'; +import React from 'react'; +import { shallow } from 'enzyme'; +import Breadcrumbs from '../breadcrumbs.component'; describe('Breadcrumbs Component', function () { it('should render with the correct colors', function () { - const wrapper = shallow() + const wrapper = shallow(); - assert.ok(wrapper) - assert.strictEqual(wrapper.find('.breadcrumbs').length, 1) - assert.strictEqual(wrapper.find('.breadcrumb').length, 3) + assert.ok(wrapper); + assert.strictEqual(wrapper.find('.breadcrumbs').length, 1); + assert.strictEqual(wrapper.find('.breadcrumb').length, 3); assert.strictEqual( wrapper.find('.breadcrumb').at(0).props().style.backgroundColor, '#FFFFFF', - ) + ); assert.strictEqual( wrapper.find('.breadcrumb').at(1).props().style.backgroundColor, '#D8D8D8', - ) + ); assert.strictEqual( wrapper.find('.breadcrumb').at(2).props().style.backgroundColor, '#FFFFFF', - ) - }) -}) + ); + }); +}); diff --git a/ui/app/components/ui/button-group/button-group.component.js b/ui/app/components/ui/button-group/button-group.component.js index aeb9b37d3..d1f20e961 100644 --- a/ui/app/components/ui/button-group/button-group.component.js +++ b/ui/app/components/ui/button-group/button-group.component.js @@ -1,6 +1,6 @@ -import React, { PureComponent } from 'react' -import PropTypes from 'prop-types' -import classnames from 'classnames' +import React, { PureComponent } from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; export default class ButtonGroup extends PureComponent { static propTypes = { @@ -12,19 +12,19 @@ export default class ButtonGroup extends PureComponent { style: PropTypes.object, newActiveButtonIndex: PropTypes.number, variant: PropTypes.oneOf(['radiogroup', 'default']), - } + }; static defaultProps = { className: 'button-group', defaultActiveButtonIndex: 0, variant: 'default', - } + }; state = { activeButtonIndex: this.props.noButtonActiveByDefault ? null : this.props.defaultActiveButtonIndex, - } + }; componentDidUpdate(_, prevState) { // Provides an API for dynamically updating the activeButtonIndex @@ -32,16 +32,16 @@ export default class ButtonGroup extends PureComponent { typeof this.props.newActiveButtonIndex === 'number' && prevState.activeButtonIndex !== this.props.newActiveButtonIndex ) { - this.setState({ activeButtonIndex: this.props.newActiveButtonIndex }) + this.setState({ activeButtonIndex: this.props.newActiveButtonIndex }); } } handleButtonClick(activeButtonIndex) { - this.setState({ activeButtonIndex }) + this.setState({ activeButtonIndex }); } renderButtons() { - const { children, disabled, variant } = this.props + const { children, disabled, variant } = this.props; return React.Children.map(children, (child, index) => { return ( @@ -62,8 +62,8 @@ export default class ButtonGroup extends PureComponent { }, )} onClick={() => { - this.handleButtonClick(index) - child.props.onClick?.() + this.handleButtonClick(index); + child.props.onClick?.(); }} disabled={disabled || child.props.disabled} key={index} @@ -71,12 +71,12 @@ export default class ButtonGroup extends PureComponent { {child.props.children} ) - ) - }) + ); + }); } render() { - const { className, style, variant } = this.props + const { className, style, variant } = this.props; return (
    {this.renderButtons()}
    - ) + ); } } diff --git a/ui/app/components/ui/button-group/button-group.stories.js b/ui/app/components/ui/button-group/button-group.stories.js index d9cbdf3d5..29b7804d4 100644 --- a/ui/app/components/ui/button-group/button-group.stories.js +++ b/ui/app/components/ui/button-group/button-group.stories.js @@ -1,13 +1,13 @@ -import React from 'react' -import { action } from '@storybook/addon-actions' -import classnames from 'classnames' -import { text, boolean } from '@storybook/addon-knobs' -import Button from '../button' -import ButtonGroup from '.' +import React from 'react'; +import { action } from '@storybook/addon-actions'; +import classnames from 'classnames'; +import { text, boolean } from '@storybook/addon-knobs'; +import Button from '../button'; +import ButtonGroup from '.'; export default { title: 'ButtonGroup', -} +}; export const withButtons = () => ( ( -) +); export const withDisabledButton = () => ( @@ -28,7 +28,7 @@ export const withDisabledButton = () => ( {text('Button2', 'Disabled')} -) +); export const radioButtons = () => ( ( {text('Button3', '5%')} -) +); diff --git a/ui/app/components/ui/button-group/index.js b/ui/app/components/ui/button-group/index.js index df470bd57..eab4b74ff 100644 --- a/ui/app/components/ui/button-group/index.js +++ b/ui/app/components/ui/button-group/index.js @@ -1 +1 @@ -export { default } from './button-group.component' +export { default } from './button-group.component'; diff --git a/ui/app/components/ui/button-group/tests/button-group-component.test.js b/ui/app/components/ui/button-group/tests/button-group-component.test.js index e64c866fa..a7e82cc45 100644 --- a/ui/app/components/ui/button-group/tests/button-group-component.test.js +++ b/ui/app/components/ui/button-group/tests/button-group-component.test.js @@ -1,15 +1,15 @@ -import assert from 'assert' -import React from 'react' -import { shallow } from 'enzyme' -import sinon from 'sinon' -import ButtonGroup from '../button-group.component' +import assert from 'assert'; +import React from 'react'; +import { shallow } from 'enzyme'; +import sinon from 'sinon'; +import ButtonGroup from '../button-group.component'; describe('ButtonGroup Component', function () { - let wrapper + let wrapper; const childButtonSpies = { onClick: sinon.spy(), - } + }; const mockButtons = [ , , , - ] + ]; before(function () { - sinon.spy(ButtonGroup.prototype, 'handleButtonClick') - sinon.spy(ButtonGroup.prototype, 'renderButtons') - }) + sinon.spy(ButtonGroup.prototype, 'handleButtonClick'); + sinon.spy(ButtonGroup.prototype, 'renderButtons'); + }); beforeEach(function () { wrapper = shallow( @@ -34,95 +34,95 @@ describe('ButtonGroup Component', function () { > {mockButtons} , - ) - }) + ); + }); afterEach(function () { - childButtonSpies.onClick.resetHistory() - ButtonGroup.prototype.handleButtonClick.resetHistory() - ButtonGroup.prototype.renderButtons.resetHistory() - }) + childButtonSpies.onClick.resetHistory(); + ButtonGroup.prototype.handleButtonClick.resetHistory(); + ButtonGroup.prototype.renderButtons.resetHistory(); + }); after(function () { - sinon.restore() - }) + sinon.restore(); + }); describe('componentDidUpdate', function () { it('should set the activeButtonIndex to the updated newActiveButtonIndex', function () { - assert.strictEqual(wrapper.state('activeButtonIndex'), 1) - wrapper.setProps({ newActiveButtonIndex: 2 }) - assert.strictEqual(wrapper.state('activeButtonIndex'), 2) - }) + assert.strictEqual(wrapper.state('activeButtonIndex'), 1); + wrapper.setProps({ newActiveButtonIndex: 2 }); + assert.strictEqual(wrapper.state('activeButtonIndex'), 2); + }); it('should not set the activeButtonIndex to an updated newActiveButtonIndex that is not a number', function () { - assert.strictEqual(wrapper.state('activeButtonIndex'), 1) - wrapper.setProps({ newActiveButtonIndex: null }) - assert.strictEqual(wrapper.state('activeButtonIndex'), 1) - }) - }) + assert.strictEqual(wrapper.state('activeButtonIndex'), 1); + wrapper.setProps({ newActiveButtonIndex: null }); + assert.strictEqual(wrapper.state('activeButtonIndex'), 1); + }); + }); describe('handleButtonClick', function () { it('should set the activeButtonIndex', function () { - assert.strictEqual(wrapper.state('activeButtonIndex'), 1) - wrapper.instance().handleButtonClick(2) - assert.strictEqual(wrapper.state('activeButtonIndex'), 2) - }) - }) + assert.strictEqual(wrapper.state('activeButtonIndex'), 1); + wrapper.instance().handleButtonClick(2); + assert.strictEqual(wrapper.state('activeButtonIndex'), 2); + }); + }); describe('renderButtons', function () { it('should render a button for each child', function () { - const childButtons = wrapper.find('.button-group__button') - assert.strictEqual(childButtons.length, 3) - }) + const childButtons = wrapper.find('.button-group__button'); + assert.strictEqual(childButtons.length, 3); + }); it('should render the correct button with an active state', function () { - const childButtons = wrapper.find('.button-group__button') - const activeChildButton = wrapper.find('.button-group__button--active') - assert.deepStrictEqual(childButtons.get(1), activeChildButton.get(0)) - }) + const childButtons = wrapper.find('.button-group__button'); + const activeChildButton = wrapper.find('.button-group__button--active'); + assert.deepStrictEqual(childButtons.get(1), activeChildButton.get(0)); + }); it("should call handleButtonClick and the respective button's onClick method when a button is clicked", function () { - assert.strictEqual(ButtonGroup.prototype.handleButtonClick.callCount, 0) - assert.strictEqual(childButtonSpies.onClick.callCount, 0) - const childButtons = wrapper.find('.button-group__button') - childButtons.at(0).props().onClick() - childButtons.at(1).props().onClick() - childButtons.at(2).props().onClick() - assert.strictEqual(ButtonGroup.prototype.handleButtonClick.callCount, 3) - assert.strictEqual(childButtonSpies.onClick.callCount, 3) - }) + assert.strictEqual(ButtonGroup.prototype.handleButtonClick.callCount, 0); + assert.strictEqual(childButtonSpies.onClick.callCount, 0); + const childButtons = wrapper.find('.button-group__button'); + childButtons.at(0).props().onClick(); + childButtons.at(1).props().onClick(); + childButtons.at(2).props().onClick(); + assert.strictEqual(ButtonGroup.prototype.handleButtonClick.callCount, 3); + assert.strictEqual(childButtonSpies.onClick.callCount, 3); + }); it('should render all child buttons as disabled if props.disabled is true', function () { - const childButtons = wrapper.find('.button-group__button') + const childButtons = wrapper.find('.button-group__button'); childButtons.forEach((button) => { - assert.strictEqual(button.props().disabled, undefined) - }) - wrapper.setProps({ disabled: true }) - const disabledChildButtons = wrapper.find('[disabled=true]') - assert.strictEqual(disabledChildButtons.length, 3) - }) + assert.strictEqual(button.props().disabled, undefined); + }); + wrapper.setProps({ disabled: true }); + const disabledChildButtons = wrapper.find('[disabled=true]'); + assert.strictEqual(disabledChildButtons.length, 3); + }); it('should render the children of the button', function () { - const mockClass = wrapper.find('.mockClass') - assert.strictEqual(mockClass.length, 1) - }) - }) + const mockClass = wrapper.find('.mockClass'); + assert.strictEqual(mockClass.length, 1); + }); + }); describe('render', function () { it('should render a div with the expected class and style', function () { assert.strictEqual( wrapper.find('div').at(0).props().className, 'someClassName', - ) + ); assert.deepStrictEqual(wrapper.find('div').at(0).props().style, { color: 'red', - }) - }) + }); + }); it('should call renderButtons when rendering', function () { - assert.strictEqual(ButtonGroup.prototype.renderButtons.callCount, 1) - wrapper.instance().render() - assert.strictEqual(ButtonGroup.prototype.renderButtons.callCount, 2) - }) - }) -}) + assert.strictEqual(ButtonGroup.prototype.renderButtons.callCount, 1); + wrapper.instance().render(); + assert.strictEqual(ButtonGroup.prototype.renderButtons.callCount, 2); + }); + }); +}); diff --git a/ui/app/components/ui/button/button.component.js b/ui/app/components/ui/button/button.component.js index 52b267517..a1af4da43 100644 --- a/ui/app/components/ui/button/button.component.js +++ b/ui/app/components/ui/button/button.component.js @@ -1,15 +1,15 @@ -import React from 'react' -import PropTypes from 'prop-types' -import classnames from 'classnames' +import React from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; -const CLASSNAME_DEFAULT = 'btn-default' -const CLASSNAME_PRIMARY = 'btn-primary' -const CLASSNAME_SECONDARY = 'btn-secondary' -const CLASSNAME_CONFIRM = 'btn-primary' -const CLASSNAME_RAISED = 'btn-raised' -const CLASSNAME_LARGE = 'btn--large' -const CLASSNAME_ROUNDED = 'btn--rounded' -const CLASSNAME_FIRST_TIME = 'btn--first-time' +const CLASSNAME_DEFAULT = 'btn-default'; +const CLASSNAME_PRIMARY = 'btn-primary'; +const CLASSNAME_SECONDARY = 'btn-secondary'; +const CLASSNAME_CONFIRM = 'btn-primary'; +const CLASSNAME_RAISED = 'btn-raised'; +const CLASSNAME_LARGE = 'btn--large'; +const CLASSNAME_ROUNDED = 'btn--rounded'; +const CLASSNAME_FIRST_TIME = 'btn--first-time'; const typeHash = { default: CLASSNAME_DEFAULT, @@ -23,7 +23,7 @@ const typeHash = { confirm: CLASSNAME_CONFIRM, raised: CLASSNAME_RAISED, 'first-time': CLASSNAME_FIRST_TIME, -} +}; const Button = ({ type, @@ -39,11 +39,11 @@ const Button = ({ // we swap the html tag we use to render this component and delete any buttonProps that // we know to be erroneous attributes for a link. We will likely want to extract Link // to its own component in the future. - let Tag = 'button' + let Tag = 'button'; if (type === 'link') { - Tag = 'a' + Tag = 'a'; } else if (submit) { - buttonProps.type = 'submit' + buttonProps.type = 'submit'; } return ( {icon}} {children} - ) -} + ); +}; Button.propTypes = { type: PropTypes.string, @@ -70,10 +70,10 @@ Button.propTypes = { className: PropTypes.string, children: PropTypes.node, icon: PropTypes.node, -} +}; Button.defaultProps = { submit: false, -} +}; -export default Button +export default Button; diff --git a/ui/app/components/ui/button/button.stories.js b/ui/app/components/ui/button/button.stories.js index d07b02e31..f2bfe3838 100644 --- a/ui/app/components/ui/button/button.stories.js +++ b/ui/app/components/ui/button/button.stories.js @@ -1,11 +1,11 @@ -import React from 'react' -import { action } from '@storybook/addon-actions' -import { text, boolean } from '@storybook/addon-knobs' -import Button from '.' +import React from 'react'; +import { action } from '@storybook/addon-actions'; +import { text, boolean } from '@storybook/addon-knobs'; +import Button from '.'; export default { title: 'Button', -} +}; export const primaryType = () => ( -) +); export const secondaryType = () => ( -) +); export const defaultType = () => ( -) +); export const warningType = () => ( -) +); export const dangerType = () => ( -) +); export const dangerPrimaryType = () => ( -) +); diff --git a/ui/app/components/ui/button/index.js b/ui/app/components/ui/button/index.js index 19702ed25..0b6199739 100644 --- a/ui/app/components/ui/button/index.js +++ b/ui/app/components/ui/button/index.js @@ -1,3 +1,3 @@ -import Button from './button.component' +import Button from './button.component'; -export default Button +export default Button; diff --git a/ui/app/components/ui/callout/callout.js b/ui/app/components/ui/callout/callout.js index bc9d4ba62..7da13c2b9 100644 --- a/ui/app/components/ui/callout/callout.js +++ b/ui/app/components/ui/callout/callout.js @@ -1,8 +1,8 @@ -import React, { useEffect, useState } from 'react' -import PropTypes from 'prop-types' -import classnames from 'classnames' -import InfoIconInverted from '../icon/info-icon-inverted.component' -import { SEVERITIES } from '../../../helpers/constants/design-system' +import React, { useEffect, useState } from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; +import InfoIconInverted from '../icon/info-icon-inverted.component'; +import { SEVERITIES } from '../../../helpers/constants/design-system'; export default function Callout({ severity, @@ -12,14 +12,14 @@ export default function Callout({ isLast, isMultiple, }) { - const [removed, setRemoved] = useState(false) + const [removed, setRemoved] = useState(false); const calloutClassName = classnames('callout', `callout--${severity}`, { 'callout--dismissed': removed === true, 'callout--multiple': isMultiple === true, 'callout--dismissible': Boolean(dismiss), 'callout--first': isFirst === true || isMultiple !== true, 'callout--last': isLast === true || isMultiple !== true, - }) + }); // Clicking the close button will set removed state, which will trigger this // effect to refire due to changing dependencies. When that happens, after a // half of a second we fire the dismiss method from the parent. The @@ -28,10 +28,10 @@ export default function Callout({ useEffect(() => { if (removed) { setTimeout(() => { - dismiss() - }, 500) + dismiss(); + }, 500); } - }, [removed, dismiss]) + }, [removed, dismiss]); return (
    @@ -39,11 +39,11 @@ export default function Callout({ {dismiss && ( { - setRemoved(true) + setRemoved(true); }} onKeyUp={(event) => { if (event.key === 'Enter') { - setRemoved(true) + setRemoved(true); } }} role="button" @@ -52,7 +52,7 @@ export default function Callout({ /> )}
    - ) + ); } Callout.propTypes = { @@ -62,4 +62,4 @@ Callout.propTypes = { isFirst: PropTypes.bool, isLast: PropTypes.bool, isMultiple: PropTypes.bool, -} +}; diff --git a/ui/app/components/ui/callout/callout.stories.js b/ui/app/components/ui/callout/callout.stories.js index 079d7d10e..7e2a54691 100644 --- a/ui/app/components/ui/callout/callout.stories.js +++ b/ui/app/components/ui/callout/callout.stories.js @@ -1,17 +1,17 @@ -import { select } from '@storybook/addon-knobs' -import React, { useState } from 'react' +import { select } from '@storybook/addon-knobs'; +import React, { useState } from 'react'; import { COLORS, SEVERITIES, TYPOGRAPHY, -} from '../../../helpers/constants/design-system' -import Box from '../box' -import Typography from '../typography' -import Callout from './callout' +} from '../../../helpers/constants/design-system'; +import Box from '../box'; +import Typography from '../typography'; +import Callout from './callout'; export default { title: 'Callout', -} +}; export const persistentCallout = () => ( @@ -25,10 +25,10 @@ export const persistentCallout = () => ( Always back up your private key! -) +); export const DismissibleCallout = () => { - const [dismissed, setDismissed] = useState(false) + const [dismissed, setDismissed] = useState(false); return ( @@ -49,8 +49,8 @@ export const DismissibleCallout = () => { )} - ) -} + ); +}; const MULTIPLE_CALLOUTS = { WARN: { @@ -63,10 +63,10 @@ const MULTIPLE_CALLOUTS = { content: 'Never give your private key out, it will lead to loss of funds!', dismissed: false, }, -} +}; export const MultipleDismissibleCallouts = () => { - const [calloutState, setCalloutState] = useState(MULTIPLE_CALLOUTS) + const [calloutState, setCalloutState] = useState(MULTIPLE_CALLOUTS); const dismiss = (id) => { setCalloutState((prevState) => ({ ...prevState, @@ -74,8 +74,8 @@ export const MultipleDismissibleCallouts = () => { ...prevState[id], dismissed: true, }, - })) - } + })); + }; return ( @@ -103,5 +103,5 @@ export const MultipleDismissibleCallouts = () => { ))} - ) -} + ); +}; diff --git a/ui/app/components/ui/callout/index.js b/ui/app/components/ui/callout/index.js index dc48ad1ac..a258baf65 100644 --- a/ui/app/components/ui/callout/index.js +++ b/ui/app/components/ui/callout/index.js @@ -1 +1 @@ -export { default } from './callout' +export { default } from './callout'; diff --git a/ui/app/components/ui/card/card.component.js b/ui/app/components/ui/card/card.component.js index c4e96e511..d75506b9a 100644 --- a/ui/app/components/ui/card/card.component.js +++ b/ui/app/components/ui/card/card.component.js @@ -1,6 +1,6 @@ -import React, { PureComponent } from 'react' -import PropTypes from 'prop-types' -import classnames from 'classnames' +import React, { PureComponent } from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; export default class Card extends PureComponent { static propTypes = { @@ -8,16 +8,16 @@ export default class Card extends PureComponent { overrideClassName: PropTypes.bool, title: PropTypes.string, children: PropTypes.node, - } + }; render() { - const { className, overrideClassName, title } = this.props + const { className, overrideClassName, title } = this.props; return (
    {title}
    {this.props.children}
    - ) + ); } } diff --git a/ui/app/components/ui/card/index.js b/ui/app/components/ui/card/index.js index c3ca6e3f4..643fad74d 100644 --- a/ui/app/components/ui/card/index.js +++ b/ui/app/components/ui/card/index.js @@ -1 +1 @@ -export { default } from './card.component' +export { default } from './card.component'; diff --git a/ui/app/components/ui/card/tests/card.component.test.js b/ui/app/components/ui/card/tests/card.component.test.js index efd05e727..2f1d4b43c 100644 --- a/ui/app/components/ui/card/tests/card.component.test.js +++ b/ui/app/components/ui/card/tests/card.component.test.js @@ -1,7 +1,7 @@ -import assert from 'assert' -import React from 'react' -import { shallow } from 'enzyme' -import Card from '../card.component' +import assert from 'assert'; +import React from 'react'; +import { shallow } from 'enzyme'; +import Card from '../card.component'; describe('Card Component', function () { it('should render a card with a title and child element', function () { @@ -9,14 +9,14 @@ describe('Card Component', function () {
    Child
    , - ) + ); - assert.ok(wrapper.hasClass('card-test-class')) - const title = wrapper.find('.card__title') - assert.ok(title) - assert.strictEqual(title.text(), 'Test') - const child = wrapper.find('.child-test-class') - assert.ok(child) - assert.strictEqual(child.text(), 'Child') - }) -}) + assert.ok(wrapper.hasClass('card-test-class')); + const title = wrapper.find('.card__title'); + assert.ok(title); + assert.strictEqual(title.text(), 'Test'); + const child = wrapper.find('.child-test-class'); + assert.ok(child); + assert.strictEqual(child.text(), 'Child'); + }); +}); diff --git a/ui/app/components/ui/check-box/check-box.component.js b/ui/app/components/ui/check-box/check-box.component.js index 360787902..825d2cc16 100644 --- a/ui/app/components/ui/check-box/check-box.component.js +++ b/ui/app/components/ui/check-box/check-box.component.js @@ -1,24 +1,24 @@ -import React, { useLayoutEffect, useRef } from 'react' -import PropTypes from 'prop-types' -import classnames from 'classnames' +import React, { useLayoutEffect, useRef } from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; const CHECKBOX_STATE = { CHECKED: 'CHECKED', INDETERMINATE: 'INDETERMINATE', UNCHECKED: 'UNCHECKED', -} +}; -export const { CHECKED, INDETERMINATE, UNCHECKED } = CHECKBOX_STATE +export const { CHECKED, INDETERMINATE, UNCHECKED } = CHECKBOX_STATE; const CheckBox = ({ className, disabled, id, onClick, checked, title }) => { if (typeof checked === 'boolean') { // eslint-disable-next-line no-param-reassign - checked = checked ? CHECKBOX_STATE.CHECKED : CHECKBOX_STATE.UNCHECKED + checked = checked ? CHECKBOX_STATE.CHECKED : CHECKBOX_STATE.UNCHECKED; } - const ref = useRef(null) + const ref = useRef(null); useLayoutEffect(() => { - ref.current.indeterminate = checked === CHECKBOX_STATE.INDETERMINATE - }, [checked]) + ref.current.indeterminate = checked === CHECKBOX_STATE.INDETERMINATE; + }, [checked]); return ( { onClick={ onClick ? (event) => { - event.preventDefault() - onClick() + event.preventDefault(); + onClick(); } : null } @@ -45,8 +45,8 @@ const CheckBox = ({ className, disabled, id, onClick, checked, title }) => { title={title} type="checkbox" /> - ) -} + ); +}; CheckBox.propTypes = { className: PropTypes.string, @@ -56,12 +56,12 @@ CheckBox.propTypes = { checked: PropTypes.oneOf([...Object.keys(CHECKBOX_STATE), true, false]) .isRequired, title: PropTypes.string, -} +}; CheckBox.defaultProps = { className: undefined, disabled: false, id: undefined, -} +}; -export default CheckBox +export default CheckBox; diff --git a/ui/app/components/ui/check-box/check-box.stories.js b/ui/app/components/ui/check-box/check-box.stories.js index 2fb7cdae7..65e8d7281 100644 --- a/ui/app/components/ui/check-box/check-box.stories.js +++ b/ui/app/components/ui/check-box/check-box.stories.js @@ -1,15 +1,15 @@ -import React from 'react' -import { action } from '@storybook/addon-actions' -import { boolean, select, text } from '@storybook/addon-knobs' +import React from 'react'; +import { action } from '@storybook/addon-actions'; +import { boolean, select, text } from '@storybook/addon-knobs'; import CheckBox, { CHECKED, INDETERMINATE, UNCHECKED, -} from './check-box.component' +} from './check-box.component'; export default { title: 'Check Box', -} +}; const checkboxOptions = { [CHECKED]: CHECKED, @@ -17,7 +17,7 @@ const checkboxOptions = { [UNCHECKED]: UNCHECKED, True: true, False: false, -} +}; export const primaryType = () => ( ( id={text('ID', 'checkboxId')} onClick={action('checkbox clicked')} /> -) +); diff --git a/ui/app/components/ui/check-box/index.js b/ui/app/components/ui/check-box/index.js index 9a7460d6a..d8c0dd421 100644 --- a/ui/app/components/ui/check-box/index.js +++ b/ui/app/components/ui/check-box/index.js @@ -3,4 +3,4 @@ export { CHECKED, INDETERMINATE, UNCHECKED, -} from './check-box.component' +} from './check-box.component'; diff --git a/ui/app/components/ui/chip/chip.js b/ui/app/components/ui/chip/chip.js index 691df480b..1d4f82d2a 100644 --- a/ui/app/components/ui/chip/chip.js +++ b/ui/app/components/ui/chip/chip.js @@ -1,9 +1,9 @@ -import React from 'react' -import PropTypes from 'prop-types' -import classnames from 'classnames' -import { omit } from 'lodash' -import Typography from '../typography' -import { COLORS, TYPOGRAPHY } from '../../../helpers/constants/design-system' +import React from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; +import { omit } from 'lodash'; +import Typography from '../typography'; +import { COLORS, TYPOGRAPHY } from '../../../helpers/constants/design-system'; export default function Chip({ className, @@ -17,9 +17,9 @@ export default function Chip({ }) { const onKeyPress = (event) => { if (event.key === 'Enter' && onClick) { - onClick(event) + onClick(event); } - } + }; return (
    {rightIcon}
    } - ) + ); } Chip.propTypes = { @@ -61,4 +61,4 @@ Chip.propTypes = { rightIcon: PropTypes.node, className: PropTypes.string, onClick: PropTypes.func, -} +}; diff --git a/ui/app/components/ui/chip/chip.stories.js b/ui/app/components/ui/chip/chip.stories.js index e2f3fd5df..690d97172 100644 --- a/ui/app/components/ui/chip/chip.stories.js +++ b/ui/app/components/ui/chip/chip.stories.js @@ -1,15 +1,15 @@ /* eslint-disable react/prop-types */ -import React from 'react' -import { select, text } from '@storybook/addon-knobs' -import { COLORS, TYPOGRAPHY } from '../../../helpers/constants/design-system' -import ApproveIcon from '../icon/approve-icon.component' -import Identicon from '../identicon/identicon.component' -import Chip from '.' +import React from 'react'; +import { select, text } from '@storybook/addon-knobs'; +import { COLORS, TYPOGRAPHY } from '../../../helpers/constants/design-system'; +import ApproveIcon from '../icon/approve-icon.component'; +import Identicon from '../identicon/identicon.component'; +import Chip from '.'; export default { title: 'Chip', -} +}; export const Plain = ({ leftIcon, @@ -28,7 +28,7 @@ export const Plain = ({ }} borderColor={select('borderColor', COLORS, borderColor)} /> -) +); export const WithLeftIcon = () => ( ( fontColor={COLORS.SUCCESS3} leftIcon={} /> -) +); export const WithRightIcon = () => ( ( /> } /> -) +); export const WithBothIcons = () => ( ( /> } /> -) +); diff --git a/ui/app/components/ui/chip/index.js b/ui/app/components/ui/chip/index.js index 54029bc48..144a7e75d 100644 --- a/ui/app/components/ui/chip/index.js +++ b/ui/app/components/ui/chip/index.js @@ -1 +1 @@ -export { default } from './chip' +export { default } from './chip'; diff --git a/ui/app/components/ui/circle-icon/circle-icon.component.js b/ui/app/components/ui/circle-icon/circle-icon.component.js index 179906673..522953286 100644 --- a/ui/app/components/ui/circle-icon/circle-icon.component.js +++ b/ui/app/components/ui/circle-icon/circle-icon.component.js @@ -1,5 +1,5 @@ -import React, { PureComponent } from 'react' -import PropTypes from 'prop-types' +import React, { PureComponent } from 'react'; +import PropTypes from 'prop-types'; export default class CircleIcon extends PureComponent { static propTypes = { @@ -7,16 +7,16 @@ export default class CircleIcon extends PureComponent { circleClass: PropTypes.string, iconSource: PropTypes.string.isRequired, iconSize: PropTypes.string, - } + }; static defaultProps = { size: '56px', iconSize: '18px', circleClass: '', - } + }; render() { - const { size, circleClass, iconSize, iconSource } = this.props + const { size, circleClass, iconSize, iconSource } = this.props; return (
    - ) + ); } } diff --git a/ui/app/components/ui/circle-icon/circle-icon.stories.js b/ui/app/components/ui/circle-icon/circle-icon.stories.js index 230a2f8a3..45b95dbd7 100644 --- a/ui/app/components/ui/circle-icon/circle-icon.stories.js +++ b/ui/app/components/ui/circle-icon/circle-icon.stories.js @@ -1,9 +1,9 @@ -import React from 'react' -import CircleIcon from './circle-icon.component' +import React from 'react'; +import CircleIcon from './circle-icon.component'; export default { title: 'CircleIcon', -} +}; export const basicCircleIcon = () => ( ( iconSize="42px" iconSource="images/eth_logo.svg" /> -) +); diff --git a/ui/app/components/ui/circle-icon/index.js b/ui/app/components/ui/circle-icon/index.js index d5cfd62c1..7a4964c71 100644 --- a/ui/app/components/ui/circle-icon/index.js +++ b/ui/app/components/ui/circle-icon/index.js @@ -1 +1 @@ -export { default } from './circle-icon.component' +export { default } from './circle-icon.component'; diff --git a/ui/app/components/ui/color-indicator/color-indicator.js b/ui/app/components/ui/color-indicator/color-indicator.js index 22ef28c0c..f34eef3d9 100644 --- a/ui/app/components/ui/color-indicator/color-indicator.js +++ b/ui/app/components/ui/color-indicator/color-indicator.js @@ -1,7 +1,7 @@ -import React from 'react' -import classnames from 'classnames' -import PropTypes from 'prop-types' -import { COLORS, SIZES } from '../../../helpers/constants/design-system' +import React from 'react'; +import classnames from 'classnames'; +import PropTypes from 'prop-types'; +import { COLORS, SIZES } from '../../../helpers/constants/design-system'; export default function ColorIndicator({ size = 'small', @@ -16,7 +16,7 @@ export default function ColorIndicator({ [`color-indicator--border-color-${borderColor}`]: Boolean(borderColor), [`color-indicator--color-${color}`]: true, [`color-indicator--size-${size}`]: true, - }) + }); return (
    @@ -26,14 +26,14 @@ export default function ColorIndicator({ )}
    - ) + ); } ColorIndicator.TYPES = { FILLED: 'filled', PARTIAL: 'partial-filled', OUTLINE: 'outline', -} +}; ColorIndicator.propTypes = { color: PropTypes.oneOf(Object.values(COLORS)), @@ -41,4 +41,4 @@ ColorIndicator.propTypes = { size: PropTypes.oneOf(Object.values(SIZES)), iconClassName: PropTypes.string, type: PropTypes.oneOf(Object.values(ColorIndicator.TYPES)), -} +}; diff --git a/ui/app/components/ui/color-indicator/color-indicator.stories.js b/ui/app/components/ui/color-indicator/color-indicator.stories.js index 1c661869b..81ab5f260 100644 --- a/ui/app/components/ui/color-indicator/color-indicator.stories.js +++ b/ui/app/components/ui/color-indicator/color-indicator.stories.js @@ -1,11 +1,11 @@ -import React from 'react' -import { select } from '@storybook/addon-knobs' -import { COLORS, SIZES } from '../../../helpers/constants/design-system' -import ColorIndicator from './color-indicator' +import React from 'react'; +import { select } from '@storybook/addon-knobs'; +import { COLORS, SIZES } from '../../../helpers/constants/design-system'; +import ColorIndicator from './color-indicator'; export default { title: 'ColorIndicator', -} +}; export const colorIndicator = () => ( ( color={select('color', COLORS, COLORS.PRIMARY1)} borderColor={select('borderColor', { NONE: undefined, ...COLORS })} /> -) +); export const withIcon = () => ( ( iconClassName="fa fa-question" borderColor={select('borderColor', { NONE: undefined, ...COLORS })} /> -) +); diff --git a/ui/app/components/ui/color-indicator/index.js b/ui/app/components/ui/color-indicator/index.js index 257ecdc0b..b73dde125 100644 --- a/ui/app/components/ui/color-indicator/index.js +++ b/ui/app/components/ui/color-indicator/index.js @@ -1 +1 @@ -export { default } from './color-indicator' +export { default } from './color-indicator'; diff --git a/ui/app/components/ui/currency-display/currency-display.component.js b/ui/app/components/ui/currency-display/currency-display.component.js index 575fb7368..6310960af 100644 --- a/ui/app/components/ui/currency-display/currency-display.component.js +++ b/ui/app/components/ui/currency-display/currency-display.component.js @@ -1,8 +1,8 @@ -import React from 'react' -import PropTypes from 'prop-types' -import classnames from 'classnames' -import { GWEI } from '../../../helpers/constants/common' -import { useCurrencyDisplay } from '../../../hooks/useCurrencyDisplay' +import React from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; +import { GWEI } from '../../../helpers/constants/common'; +import { useCurrencyDisplay } from '../../../hooks/useCurrencyDisplay'; export default function CurrencyDisplay({ value, @@ -27,7 +27,7 @@ export default function CurrencyDisplay({ denomination, currency, suffix, - }) + }); return (
    )}
    - ) + ); } CurrencyDisplay.propTypes = { @@ -63,4 +63,4 @@ CurrencyDisplay.propTypes = { style: PropTypes.object, suffix: PropTypes.string, value: PropTypes.string, -} +}; diff --git a/ui/app/components/ui/currency-display/index.js b/ui/app/components/ui/currency-display/index.js index f861bb91a..f5b01c575 100644 --- a/ui/app/components/ui/currency-display/index.js +++ b/ui/app/components/ui/currency-display/index.js @@ -1 +1 @@ -export { default } from './currency-display.component' +export { default } from './currency-display.component'; diff --git a/ui/app/components/ui/currency-display/tests/currency-display.component.test.js b/ui/app/components/ui/currency-display/tests/currency-display.component.test.js index 8fd0bb4ba..295d4c463 100644 --- a/ui/app/components/ui/currency-display/tests/currency-display.component.test.js +++ b/ui/app/components/ui/currency-display/tests/currency-display.component.test.js @@ -1,19 +1,19 @@ -import assert from 'assert' -import React from 'react' -import { shallow } from 'enzyme' -import sinon from 'sinon' -import * as reactRedux from 'react-redux' -import CurrencyDisplay from '../currency-display.component' +import assert from 'assert'; +import React from 'react'; +import { shallow } from 'enzyme'; +import sinon from 'sinon'; +import * as reactRedux from 'react-redux'; +import CurrencyDisplay from '../currency-display.component'; describe('CurrencyDisplay Component', function () { beforeEach(function () { - const stub = sinon.stub(reactRedux, 'useSelector') + const stub = sinon.stub(reactRedux, 'useSelector'); stub.callsFake(() => ({ currentCurrency: 'usd', nativeCurrency: 'ETH', conversionRate: 280.45, - })) - }) + })); + }); it('should render text with a className', function () { const wrapper = shallow( , - ) + ); - assert.ok(wrapper.hasClass('currency-display')) - assert.strictEqual(wrapper.text(), '$123.45') - }) + assert.ok(wrapper.hasClass('currency-display')); + assert.strictEqual(wrapper.text(), '$123.45'); + }); it('should render text with a prefix', function () { const wrapper = shallow( @@ -35,12 +35,12 @@ describe('CurrencyDisplay Component', function () { prefix="-" hideLabel />, - ) + ); - assert.ok(wrapper.hasClass('currency-display')) - assert.strictEqual(wrapper.text(), '-$123.45') - }) + assert.ok(wrapper.hasClass('currency-display')); + assert.strictEqual(wrapper.text(), '-$123.45'); + }); afterEach(function () { - sinon.restore() - }) -}) + sinon.restore(); + }); +}); diff --git a/ui/app/components/ui/currency-input/currency-input.component.js b/ui/app/components/ui/currency-input/currency-input.component.js index 0186051de..e953d3090 100644 --- a/ui/app/components/ui/currency-input/currency-input.component.js +++ b/ui/app/components/ui/currency-input/currency-input.component.js @@ -1,12 +1,12 @@ -import React, { PureComponent } from 'react' -import PropTypes from 'prop-types' -import UnitInput from '../unit-input' -import CurrencyDisplay from '../currency-display' +import React, { PureComponent } from 'react'; +import PropTypes from 'prop-types'; +import UnitInput from '../unit-input'; +import CurrencyDisplay from '../currency-display'; import { getValueFromWeiHex, getWeiHexFromDecimalValue, -} from '../../../helpers/utils/conversions.util' -import { ETH } from '../../../helpers/constants/common' +} from '../../../helpers/utils/conversions.util'; +import { ETH } from '../../../helpers/constants/common'; /** * Component that allows user to enter currency values as a number, and props receive a converted @@ -16,7 +16,7 @@ import { ETH } from '../../../helpers/constants/common' export default class CurrencyInput extends PureComponent { static contextTypes = { t: PropTypes.func, - } + }; static propTypes = { conversionRate: PropTypes.number, @@ -28,37 +28,37 @@ export default class CurrencyInput extends PureComponent { value: PropTypes.string, fiatSuffix: PropTypes.string, nativeSuffix: PropTypes.string, - } + }; constructor(props) { - super(props) + super(props); - const { value: hexValue } = props - const decimalValue = hexValue ? this.getDecimalValue(props) : 0 + const { value: hexValue } = props; + const decimalValue = hexValue ? this.getDecimalValue(props) : 0; this.state = { decimalValue, hexValue, isSwapped: false, - } + }; } componentDidUpdate(prevProps) { - const { value: prevPropsHexValue } = prevProps - const { value: propsHexValue } = this.props - const { hexValue: stateHexValue } = this.state + const { value: prevPropsHexValue } = prevProps; + const { value: propsHexValue } = this.props; + const { hexValue: stateHexValue } = this.state; if ( prevPropsHexValue !== propsHexValue && propsHexValue !== stateHexValue ) { - const decimalValue = this.getDecimalValue(this.props) - this.setState({ hexValue: propsHexValue, decimalValue }) + const decimalValue = this.getDecimalValue(this.props); + this.setState({ hexValue: propsHexValue, decimalValue }); } } getDecimalValue(props) { - const { value: hexValue, currentCurrency, conversionRate } = props + const { value: hexValue, currentCurrency, conversionRate } = props; const decimalValueString = this.shouldUseFiat() ? getValueFromWeiHex({ value: hexValue, @@ -70,35 +70,35 @@ export default class CurrencyInput extends PureComponent { value: hexValue, toCurrency: ETH, numberOfDecimals: 6, - }) + }); - return Number(decimalValueString) || 0 + return Number(decimalValueString) || 0; } shouldUseFiat = () => { - const { useFiat, hideFiat } = this.props - const { isSwapped } = this.state || {} + const { useFiat, hideFiat } = this.props; + const { isSwapped } = this.state || {}; if (hideFiat) { - return false + return false; } - return isSwapped ? !useFiat : useFiat - } + return isSwapped ? !useFiat : useFiat; + }; swap = () => { - const { isSwapped, decimalValue } = this.state + const { isSwapped, decimalValue } = this.state; this.setState({ isSwapped: !isSwapped }, () => { - this.handleChange(decimalValue) - }) - } + this.handleChange(decimalValue); + }); + }; handleChange = (decimalValue) => { const { currentCurrency: fromCurrency, conversionRate, onChange, - } = this.props + } = this.props; const hexValue = this.shouldUseFiat() ? getWeiHexFromDecimalValue({ @@ -112,33 +112,33 @@ export default class CurrencyInput extends PureComponent { fromCurrency: ETH, fromDenomination: ETH, conversionRate, - }) + }); - this.setState({ hexValue, decimalValue }) - onChange(hexValue) - } + this.setState({ hexValue, decimalValue }); + onChange(hexValue); + }; renderConversionComponent() { - const { currentCurrency, nativeCurrency, hideFiat } = this.props - const { hexValue } = this.state - let currency, numberOfDecimals + const { currentCurrency, nativeCurrency, hideFiat } = this.props; + const { hexValue } = this.state; + let currency, numberOfDecimals; if (hideFiat) { return (
    {this.context.t('noConversionRateAvailable')}
    - ) + ); } if (this.shouldUseFiat()) { // Display ETH - currency = nativeCurrency || ETH - numberOfDecimals = 6 + currency = nativeCurrency || ETH; + numberOfDecimals = 6; } else { // Display Fiat - currency = currentCurrency - numberOfDecimals = 2 + currency = currentCurrency; + numberOfDecimals = 2; } return ( @@ -148,12 +148,12 @@ export default class CurrencyInput extends PureComponent { value={hexValue} numberOfDecimals={numberOfDecimals} /> - ) + ); } render() { - const { fiatSuffix, nativeSuffix, ...restProps } = this.props - const { decimalValue } = this.state + const { fiatSuffix, nativeSuffix, ...restProps } = this.props; + const { decimalValue } = this.state; return ( {this.renderConversionComponent()} - ) + ); } } diff --git a/ui/app/components/ui/currency-input/currency-input.container.js b/ui/app/components/ui/currency-input/currency-input.container.js index e402a3def..23d792838 100644 --- a/ui/app/components/ui/currency-input/currency-input.container.js +++ b/ui/app/components/ui/currency-input/currency-input.container.js @@ -1,25 +1,25 @@ -import { connect } from 'react-redux' -import { ETH } from '../../../helpers/constants/common' -import { getIsMainnet, getPreferences } from '../../../selectors' -import CurrencyInput from './currency-input.component' +import { connect } from 'react-redux'; +import { ETH } from '../../../helpers/constants/common'; +import { getIsMainnet, getPreferences } from '../../../selectors'; +import CurrencyInput from './currency-input.component'; const mapStateToProps = (state) => { const { metamask: { nativeCurrency, currentCurrency, conversionRate }, - } = state - const { showFiatInTestnets } = getPreferences(state) - const isMainnet = getIsMainnet(state) + } = state; + const { showFiatInTestnets } = getPreferences(state); + const isMainnet = getIsMainnet(state); return { nativeCurrency, currentCurrency, conversionRate, hideFiat: !isMainnet && !showFiatInTestnets, - } -} + }; +}; const mergeProps = (stateProps, dispatchProps, ownProps) => { - const { nativeCurrency, currentCurrency } = stateProps + const { nativeCurrency, currentCurrency } = stateProps; return { ...stateProps, @@ -27,7 +27,7 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => { ...ownProps, nativeSuffix: nativeCurrency || ETH, fiatSuffix: currentCurrency.toUpperCase(), - } -} + }; +}; -export default connect(mapStateToProps, null, mergeProps)(CurrencyInput) +export default connect(mapStateToProps, null, mergeProps)(CurrencyInput); diff --git a/ui/app/components/ui/currency-input/index.js b/ui/app/components/ui/currency-input/index.js index d8069fb67..4f3b7bedf 100644 --- a/ui/app/components/ui/currency-input/index.js +++ b/ui/app/components/ui/currency-input/index.js @@ -1 +1 @@ -export { default } from './currency-input.container' +export { default } from './currency-input.container'; diff --git a/ui/app/components/ui/currency-input/tests/currency-input.component.test.js b/ui/app/components/ui/currency-input/tests/currency-input.component.test.js index e6e05a33b..f47154b5c 100644 --- a/ui/app/components/ui/currency-input/tests/currency-input.component.test.js +++ b/ui/app/components/ui/currency-input/tests/currency-input.component.test.js @@ -1,22 +1,22 @@ -import assert from 'assert' -import React from 'react' -import PropTypes from 'prop-types' -import { shallow, mount } from 'enzyme' -import sinon from 'sinon' -import { Provider } from 'react-redux' -import configureMockStore from 'redux-mock-store' -import CurrencyInput from '../currency-input.component' -import UnitInput from '../../unit-input' -import CurrencyDisplay from '../../currency-display' +import assert from 'assert'; +import React from 'react'; +import PropTypes from 'prop-types'; +import { shallow, mount } from 'enzyme'; +import sinon from 'sinon'; +import { Provider } from 'react-redux'; +import configureMockStore from 'redux-mock-store'; +import CurrencyInput from '../currency-input.component'; +import UnitInput from '../../unit-input'; +import CurrencyDisplay from '../../currency-display'; describe('CurrencyInput Component', function () { describe('rendering', function () { it('should render properly without a suffix', function () { - const wrapper = shallow() + const wrapper = shallow(); - assert.ok(wrapper) - assert.strictEqual(wrapper.find(UnitInput).length, 1) - }) + assert.ok(wrapper); + assert.strictEqual(wrapper.find(UnitInput).length, 1); + }); it('should render properly with a suffix', function () { const mockStore = { @@ -25,8 +25,8 @@ describe('CurrencyInput Component', function () { currentCurrency: 'usd', conversionRate: 231.06, }, - } - const store = configureMockStore()(mockStore) + }; + const store = configureMockStore()(mockStore); const wrapper = mount( @@ -36,13 +36,13 @@ describe('CurrencyInput Component', function () { nativeCurrency="ETH" /> , - ) + ); - assert.ok(wrapper) - assert.strictEqual(wrapper.find('.unit-input__suffix').length, 1) - assert.strictEqual(wrapper.find('.unit-input__suffix').text(), 'ETH') - assert.strictEqual(wrapper.find(CurrencyDisplay).length, 1) - }) + assert.ok(wrapper); + assert.strictEqual(wrapper.find('.unit-input__suffix').length, 1); + assert.strictEqual(wrapper.find('.unit-input__suffix').text(), 'ETH'); + assert.strictEqual(wrapper.find(CurrencyDisplay).length, 1); + }); it('should render properly with an ETH value', function () { const mockStore = { @@ -51,8 +51,8 @@ describe('CurrencyInput Component', function () { currentCurrency: 'usd', conversionRate: 231.06, }, - } - const store = configureMockStore()(mockStore) + }; + const store = configureMockStore()(mockStore); const wrapper = mount( @@ -65,23 +65,26 @@ describe('CurrencyInput Component', function () { conversionRate={231.06} /> , - ) + ); - assert.ok(wrapper) - const currencyInputInstance = wrapper.find(CurrencyInput).at(0).instance() - assert.strictEqual(currencyInputInstance.state.decimalValue, 1) + assert.ok(wrapper); + const currencyInputInstance = wrapper + .find(CurrencyInput) + .at(0) + .instance(); + assert.strictEqual(currencyInputInstance.state.decimalValue, 1); assert.strictEqual( currencyInputInstance.state.hexValue, 'de0b6b3a7640000', - ) - assert.strictEqual(wrapper.find('.unit-input__suffix').length, 1) - assert.strictEqual(wrapper.find('.unit-input__suffix').text(), 'ETH') - assert.strictEqual(wrapper.find('.unit-input__input').props().value, 1) + ); + assert.strictEqual(wrapper.find('.unit-input__suffix').length, 1); + assert.strictEqual(wrapper.find('.unit-input__suffix').text(), 'ETH'); + assert.strictEqual(wrapper.find('.unit-input__input').props().value, 1); assert.strictEqual( wrapper.find('.currency-display-component').text(), '$231.06USD', - ) - }) + ); + }); it('should render properly with a fiat value', function () { const mockStore = { @@ -90,8 +93,8 @@ describe('CurrencyInput Component', function () { currentCurrency: 'usd', conversionRate: 231.06, }, - } - const store = configureMockStore()(mockStore) + }; + const store = configureMockStore()(mockStore); const wrapper = mount( @@ -105,20 +108,23 @@ describe('CurrencyInput Component', function () { conversionRate={231.06} /> , - ) + ); - assert.ok(wrapper) - const currencyInputInstance = wrapper.find(CurrencyInput).at(0).instance() - assert.strictEqual(currencyInputInstance.state.decimalValue, 1) - assert.strictEqual(currencyInputInstance.state.hexValue, 'f602f2234d0ea') - assert.strictEqual(wrapper.find('.unit-input__suffix').length, 1) - assert.strictEqual(wrapper.find('.unit-input__suffix').text(), 'USD') - assert.strictEqual(wrapper.find('.unit-input__input').props().value, 1) + assert.ok(wrapper); + const currencyInputInstance = wrapper + .find(CurrencyInput) + .at(0) + .instance(); + assert.strictEqual(currencyInputInstance.state.decimalValue, 1); + assert.strictEqual(currencyInputInstance.state.hexValue, 'f602f2234d0ea'); + assert.strictEqual(wrapper.find('.unit-input__suffix').length, 1); + assert.strictEqual(wrapper.find('.unit-input__suffix').text(), 'USD'); + assert.strictEqual(wrapper.find('.unit-input__input').props().value, 1); assert.strictEqual( wrapper.find('.currency-display-component').text(), '0.004328ETH', - ) - }) + ); + }); it('should render properly with a native value when hideFiat is true', function () { const mockStore = { @@ -127,8 +133,8 @@ describe('CurrencyInput Component', function () { currentCurrency: 'usd', conversionRate: 231.06, }, - } - const store = configureMockStore()(mockStore) + }; + const store = configureMockStore()(mockStore); const wrapper = mount( @@ -147,33 +153,36 @@ describe('CurrencyInput Component', function () { context: { t: (str) => `${str}_t` }, childContextTypes: { t: PropTypes.func }, }, - ) + ); - assert.ok(wrapper) - const currencyInputInstance = wrapper.find(CurrencyInput).at(0).instance() - assert.strictEqual(currencyInputInstance.state.decimalValue, 0.004328) - assert.strictEqual(currencyInputInstance.state.hexValue, 'f602f2234d0ea') - assert.strictEqual(wrapper.find('.unit-input__suffix').length, 1) - assert.strictEqual(wrapper.find('.unit-input__suffix').text(), 'ETH') + assert.ok(wrapper); + const currencyInputInstance = wrapper + .find(CurrencyInput) + .at(0) + .instance(); + assert.strictEqual(currencyInputInstance.state.decimalValue, 0.004328); + assert.strictEqual(currencyInputInstance.state.hexValue, 'f602f2234d0ea'); + assert.strictEqual(wrapper.find('.unit-input__suffix').length, 1); + assert.strictEqual(wrapper.find('.unit-input__suffix').text(), 'ETH'); assert.strictEqual( wrapper.find('.unit-input__input').props().value, 0.004328, - ) + ); assert.strictEqual( wrapper.find('.currency-input__conversion-component').text(), 'noConversionRateAvailable_t', - ) - }) - }) + ); + }); + }); describe('handling actions', function () { - const handleChangeSpy = sinon.spy() - const handleBlurSpy = sinon.spy() + const handleChangeSpy = sinon.spy(); + const handleBlurSpy = sinon.spy(); afterEach(function () { - handleChangeSpy.resetHistory() - handleBlurSpy.resetHistory() - }) + handleChangeSpy.resetHistory(); + handleBlurSpy.resetHistory(); + }); it('should call onChange on input changes with the hex value for ETH', function () { const mockStore = { @@ -182,8 +191,8 @@ describe('CurrencyInput Component', function () { currentCurrency: 'usd', conversionRate: 231.06, }, - } - const store = configureMockStore()(mockStore) + }; + const store = configureMockStore()(mockStore); const wrapper = mount( , - ) + ); - assert.ok(wrapper) - assert.strictEqual(handleChangeSpy.callCount, 0) - assert.strictEqual(handleBlurSpy.callCount, 0) + assert.ok(wrapper); + assert.strictEqual(handleChangeSpy.callCount, 0); + assert.strictEqual(handleBlurSpy.callCount, 0); - const currencyInputInstance = wrapper.find(CurrencyInput).at(0).instance() - assert.strictEqual(currencyInputInstance.state.decimalValue, 0) - assert.strictEqual(currencyInputInstance.state.hexValue, undefined) + const currencyInputInstance = wrapper + .find(CurrencyInput) + .at(0) + .instance(); + assert.strictEqual(currencyInputInstance.state.decimalValue, 0); + assert.strictEqual(currencyInputInstance.state.hexValue, undefined); assert.strictEqual( wrapper.find('.currency-display-component').text(), '$0.00USD', - ) - const input = wrapper.find('input') - assert.strictEqual(input.props().value, 0) + ); + const input = wrapper.find('input'); + assert.strictEqual(input.props().value, 0); - input.simulate('change', { target: { value: 1 } }) - assert.strictEqual(handleChangeSpy.callCount, 1) - assert.ok(handleChangeSpy.calledWith('de0b6b3a7640000')) + input.simulate('change', { target: { value: 1 } }); + assert.strictEqual(handleChangeSpy.callCount, 1); + assert.ok(handleChangeSpy.calledWith('de0b6b3a7640000')); assert.strictEqual( wrapper.find('.currency-display-component').text(), '$231.06USD', - ) - assert.strictEqual(currencyInputInstance.state.decimalValue, 1) + ); + assert.strictEqual(currencyInputInstance.state.decimalValue, 1); assert.strictEqual( currencyInputInstance.state.hexValue, 'de0b6b3a7640000', - ) - }) + ); + }); it('should call onChange on input changes with the hex value for fiat', function () { const mockStore = { @@ -231,8 +243,8 @@ describe('CurrencyInput Component', function () { currentCurrency: 'usd', conversionRate: 231.06, }, - } - const store = configureMockStore()(mockStore) + }; + const store = configureMockStore()(mockStore); const wrapper = mount( , - ) + ); - assert.ok(wrapper) - assert.strictEqual(handleChangeSpy.callCount, 0) - assert.strictEqual(handleBlurSpy.callCount, 0) + assert.ok(wrapper); + assert.strictEqual(handleChangeSpy.callCount, 0); + assert.strictEqual(handleBlurSpy.callCount, 0); - const currencyInputInstance = wrapper.find(CurrencyInput).at(0).instance() - assert.strictEqual(currencyInputInstance.state.decimalValue, 0) - assert.strictEqual(currencyInputInstance.state.hexValue, undefined) + const currencyInputInstance = wrapper + .find(CurrencyInput) + .at(0) + .instance(); + assert.strictEqual(currencyInputInstance.state.decimalValue, 0); + assert.strictEqual(currencyInputInstance.state.hexValue, undefined); assert.strictEqual( wrapper.find('.currency-display-component').text(), '0ETH', - ) - const input = wrapper.find('input') - assert.strictEqual(input.props().value, 0) + ); + const input = wrapper.find('input'); + assert.strictEqual(input.props().value, 0); - input.simulate('change', { target: { value: 1 } }) - assert.strictEqual(handleChangeSpy.callCount, 1) - assert.ok(handleChangeSpy.calledWith('f602f2234d0ea')) + input.simulate('change', { target: { value: 1 } }); + assert.strictEqual(handleChangeSpy.callCount, 1); + assert.ok(handleChangeSpy.calledWith('f602f2234d0ea')); assert.strictEqual( wrapper.find('.currency-display-component').text(), '0.004328ETH', - ) - assert.strictEqual(currencyInputInstance.state.decimalValue, 1) - assert.strictEqual(currencyInputInstance.state.hexValue, 'f602f2234d0ea') - }) + ); + assert.strictEqual(currencyInputInstance.state.decimalValue, 1); + assert.strictEqual(currencyInputInstance.state.hexValue, 'f602f2234d0ea'); + }); it('should change the state and pass in a new decimalValue when props.value changes', function () { const mockStore = { @@ -278,8 +293,8 @@ describe('CurrencyInput Component', function () { currentCurrency: 'usd', conversionRate: 231.06, }, - } - const store = configureMockStore()(mockStore) + }; + const store = configureMockStore()(mockStore); const wrapper = shallow( , - ) + ); - assert.ok(wrapper) - const currencyInputInstance = wrapper.find(CurrencyInput).dive() - assert.strictEqual(currencyInputInstance.state('decimalValue'), 0) - assert.strictEqual(currencyInputInstance.state('hexValue'), undefined) - assert.strictEqual(currencyInputInstance.find(UnitInput).props().value, 0) + assert.ok(wrapper); + const currencyInputInstance = wrapper.find(CurrencyInput).dive(); + assert.strictEqual(currencyInputInstance.state('decimalValue'), 0); + assert.strictEqual(currencyInputInstance.state('hexValue'), undefined); + assert.strictEqual( + currencyInputInstance.find(UnitInput).props().value, + 0, + ); - currencyInputInstance.setProps({ value: '1ec05e43e72400' }) - currencyInputInstance.update() - assert.strictEqual(currencyInputInstance.state('decimalValue'), 2) + currencyInputInstance.setProps({ value: '1ec05e43e72400' }); + currencyInputInstance.update(); + assert.strictEqual(currencyInputInstance.state('decimalValue'), 2); assert.strictEqual( currencyInputInstance.state('hexValue'), '1ec05e43e72400', - ) - assert.strictEqual(currencyInputInstance.find(UnitInput).props().value, 2) - }) + ); + assert.strictEqual( + currencyInputInstance.find(UnitInput).props().value, + 2, + ); + }); it('should swap selected currency when swap icon is clicked', function () { const mockStore = { @@ -316,8 +337,8 @@ describe('CurrencyInput Component', function () { currentCurrency: 'usd', conversionRate: 231.06, }, - } - const store = configureMockStore()(mockStore) + }; + const store = configureMockStore()(mockStore); const wrapper = mount( , - ) + ); - assert.ok(wrapper) - assert.strictEqual(handleChangeSpy.callCount, 0) - assert.strictEqual(handleBlurSpy.callCount, 0) + assert.ok(wrapper); + assert.strictEqual(handleChangeSpy.callCount, 0); + assert.strictEqual(handleBlurSpy.callCount, 0); - const currencyInputInstance = wrapper.find(CurrencyInput).at(0).instance() - assert.strictEqual(currencyInputInstance.state.decimalValue, 0) - assert.strictEqual(currencyInputInstance.state.hexValue, undefined) + const currencyInputInstance = wrapper + .find(CurrencyInput) + .at(0) + .instance(); + assert.strictEqual(currencyInputInstance.state.decimalValue, 0); + assert.strictEqual(currencyInputInstance.state.hexValue, undefined); assert.strictEqual( wrapper.find('.currency-display-component').text(), '$0.00USD', - ) - const input = wrapper.find('input') - assert.strictEqual(input.props().value, 0) + ); + const input = wrapper.find('input'); + assert.strictEqual(input.props().value, 0); - input.simulate('change', { target: { value: 1 } }) - assert.strictEqual(handleChangeSpy.callCount, 1) - assert.ok(handleChangeSpy.calledWith('de0b6b3a7640000')) + input.simulate('change', { target: { value: 1 } }); + assert.strictEqual(handleChangeSpy.callCount, 1); + assert.ok(handleChangeSpy.calledWith('de0b6b3a7640000')); assert.strictEqual( wrapper.find('.currency-display-component').text(), '$231.06USD', - ) - assert.strictEqual(currencyInputInstance.state.decimalValue, 1) + ); + assert.strictEqual(currencyInputInstance.state.decimalValue, 1); assert.strictEqual( currencyInputInstance.state.hexValue, 'de0b6b3a7640000', - ) + ); - const swap = wrapper.find('.currency-input__swap-component') - swap.simulate('click') + const swap = wrapper.find('.currency-input__swap-component'); + swap.simulate('click'); assert.strictEqual( wrapper.find('.currency-display-component').text(), '0.004328ETH', - ) - }) - }) -}) + ); + }); + }); +}); diff --git a/ui/app/components/ui/currency-input/tests/currency-input.container.test.js b/ui/app/components/ui/currency-input/tests/currency-input.container.test.js index 630e4cdc6..ccb5bb6d0 100644 --- a/ui/app/components/ui/currency-input/tests/currency-input.container.test.js +++ b/ui/app/components/ui/currency-input/tests/currency-input.container.test.js @@ -1,17 +1,17 @@ -import assert from 'assert' -import proxyquire from 'proxyquire' +import assert from 'assert'; +import proxyquire from 'proxyquire'; -let mapStateToProps, mergeProps +let mapStateToProps, mergeProps; proxyquire('../currency-input.container.js', { 'react-redux': { connect: (ms, _, mp) => { - mapStateToProps = ms - mergeProps = mp - return () => ({}) + mapStateToProps = ms; + mergeProps = mp; + return () => ({}); }, }, -}) +}); describe('CurrencyInput container', function () { describe('mapStateToProps()', function () { @@ -111,14 +111,14 @@ describe('CurrencyInput container', function () { hideFiat: false, }, }, - ] + ]; tests.forEach(({ mockState, expected, comment }) => { it(comment, function () { - return assert.deepStrictEqual(mapStateToProps(mockState), expected) - }) - }) - }) + return assert.deepStrictEqual(mapStateToProps(mockState), expected); + }); + }); + }); describe('mergeProps()', function () { const tests = [ @@ -164,7 +164,7 @@ describe('CurrencyInput container', function () { fiatSuffix: 'USD', }, }, - ] + ]; tests.forEach( ({ @@ -176,9 +176,9 @@ describe('CurrencyInput container', function () { assert.deepStrictEqual( mergeProps(stateProps, dispatchProps, ownProps), expected, - ) - }) + ); + }); }, - ) - }) -}) + ); + }); +}); diff --git a/ui/app/components/ui/definition-list/definition-list.js b/ui/app/components/ui/definition-list/definition-list.js index 8c46611eb..50a11b7a1 100644 --- a/ui/app/components/ui/definition-list/definition-list.js +++ b/ui/app/components/ui/definition-list/definition-list.js @@ -1,14 +1,14 @@ -import React from 'react' -import PropTypes from 'prop-types' -import { omit } from 'lodash' -import Typography from '../typography' +import React from 'react'; +import PropTypes from 'prop-types'; +import { omit } from 'lodash'; +import Typography from '../typography'; import { COLORS, SIZES, TYPOGRAPHY, FONT_WEIGHT, -} from '../../../helpers/constants/design-system' -import Tooltip from '../tooltip' +} from '../../../helpers/constants/design-system'; +import Tooltip from '../tooltip'; const MARGIN_MAP = { [SIZES.XS]: 0, @@ -16,7 +16,7 @@ const MARGIN_MAP = { [SIZES.MD]: 4, [SIZES.LG]: 6, [SIZES.XL]: 8, -} +}; export default function DefinitionList({ dictionary, @@ -67,7 +67,7 @@ export default function DefinitionList({ ))} - ) + ); } DefinitionList.propTypes = { @@ -82,4 +82,4 @@ DefinitionList.propTypes = { definitionTypography: PropTypes.shape({ ...omit(Typography.propTypes, ['tag', 'className', 'boxProps']), }), -} +}; diff --git a/ui/app/components/ui/definition-list/definition-list.stories.js b/ui/app/components/ui/definition-list/definition-list.stories.js index b833e71d3..5a5c3042c 100644 --- a/ui/app/components/ui/definition-list/definition-list.stories.js +++ b/ui/app/components/ui/definition-list/definition-list.stories.js @@ -1,15 +1,15 @@ -import React from 'react' -import { object, select } from '@storybook/addon-knobs' +import React from 'react'; +import { object, select } from '@storybook/addon-knobs'; import { COLORS, SIZES, TYPOGRAPHY, -} from '../../../helpers/constants/design-system' -import DefinitionList from './definition-list' +} from '../../../helpers/constants/design-system'; +import DefinitionList from './definition-list'; export default { title: 'Definition List', -} +}; const basic = { term: @@ -19,26 +19,26 @@ const basic = { dl: 'HTML tag denoting a definition list', dt: 'HTML tag denoting a definition list term', dd: 'HTML tag denoting a definition list definition', -} +}; const advanced = { 'Network Name': 'Ethereum Mainnet', 'Chain ID': '1', Ticker: 'ETH', -} +}; const tooltips = { 'Network Name': 'The name that is associated with this network', 'Chain ID': 'The numeric value representing the ID of this network', Ticker: 'The currency symbol of the primary currency for this network', -} +}; export const definitionList = () => ( -) +); export const withTooltips = () => ( ( tooltips={object('tooltips', tooltips)} gapSize={select('gapSize', SIZES, SIZES.SM)} /> -) +); export const withTypographyControl = () => ( ( color: select('definitionTypography.color', COLORS, COLORS.BLACK), }} /> -) +); diff --git a/ui/app/components/ui/definition-list/index.js b/ui/app/components/ui/definition-list/index.js index a321da7a8..9316f4022 100644 --- a/ui/app/components/ui/definition-list/index.js +++ b/ui/app/components/ui/definition-list/index.js @@ -1 +1 @@ -export { default } from './definition-list' +export { default } from './definition-list'; diff --git a/ui/app/components/ui/dialog/index.js b/ui/app/components/ui/dialog/index.js index 672d83337..457aa6a4d 100644 --- a/ui/app/components/ui/dialog/index.js +++ b/ui/app/components/ui/dialog/index.js @@ -1,9 +1,9 @@ -import React from 'react' -import PropTypes from 'prop-types' -import classnames from 'classnames' +import React from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; export default function Dialog(props) { - const { children, type, className, onClick } = props + const { children, type, className, onClick } = props; return (
    {children}
    - ) + ); } Dialog.propTypes = { @@ -23,4 +23,4 @@ Dialog.propTypes = { children: PropTypes.node, type: PropTypes.oneOf(['message', 'error', 'warning']), onClick: PropTypes.func, -} +}; diff --git a/ui/app/components/ui/dropdown/dropdown.js b/ui/app/components/ui/dropdown/dropdown.js index db75be922..ed207d760 100644 --- a/ui/app/components/ui/dropdown/dropdown.js +++ b/ui/app/components/ui/dropdown/dropdown.js @@ -1,6 +1,6 @@ -import React, { useCallback } from 'react' -import PropTypes from 'prop-types' -import classnames from 'classnames' +import React, { useCallback } from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; const Dropdown = ({ className, @@ -13,12 +13,12 @@ const Dropdown = ({ }) => { const _onChange = useCallback( (event) => { - event.preventDefault() - event.stopPropagation() - onChange(event.target.value) + event.preventDefault(); + event.stopPropagation(); + onChange(event.target.value); }, [onChange], - ) + ); return ( - ) -} + ); +}; Dropdown.propTypes = { className: PropTypes.string, @@ -53,7 +53,7 @@ Dropdown.propTypes = { ).isRequired, selectedOption: PropTypes.string, style: PropTypes.object, -} +}; Dropdown.defaultProps = { className: undefined, @@ -61,6 +61,6 @@ Dropdown.defaultProps = { title: undefined, selectedOption: null, style: undefined, -} +}; -export default Dropdown +export default Dropdown; diff --git a/ui/app/components/ui/dropdown/dropdown.stories.js b/ui/app/components/ui/dropdown/dropdown.stories.js index b46358def..d12354e20 100644 --- a/ui/app/components/ui/dropdown/dropdown.stories.js +++ b/ui/app/components/ui/dropdown/dropdown.stories.js @@ -1,26 +1,26 @@ -import React from 'react' -import { action } from '@storybook/addon-actions' -import { boolean, select, text } from '@storybook/addon-knobs' -import Dropdown from '.' +import React from 'react'; +import { action } from '@storybook/addon-actions'; +import { boolean, select, text } from '@storybook/addon-knobs'; +import Dropdown from '.'; export default { title: 'Dropdown', -} +}; const unnamedOptions = [...Array(10).keys()].map((index) => { - return { value: `option${index}` } -}) + return { value: `option${index}` }; +}); const namedOptions = unnamedOptions.map((option, index) => { - return { ...option, name: `Option ${index}` } -}) + return { ...option, name: `Option ${index}` }; +}); const namedOptionsWithVeryLongNames = unnamedOptions.map((option, index) => { return { ...option, name: `Option ${index} with a very${', very'.repeat(index)} long name`, - } -}) + }; +}); export const simple = () => ( ( namedOptions[0].value, )} /> -) +); export const optionsWithoutNames = () => ( ( unnamedOptions[0].value, )} /> -) +); export const optionsWithLongNames = () => ( ( namedOptionsWithVeryLongNames[0].value, )} /> -) +); export const optionsWithLongNamesAndShortWidth = () => ( ( )} style={{ width: '200px' }} /> -) +); diff --git a/ui/app/components/ui/dropdown/index.js b/ui/app/components/ui/dropdown/index.js index 8d23b5709..1ad5658ed 100644 --- a/ui/app/components/ui/dropdown/index.js +++ b/ui/app/components/ui/dropdown/index.js @@ -1 +1 @@ -export { default } from './dropdown' +export { default } from './dropdown'; diff --git a/ui/app/components/ui/editable-label/editable-label.js b/ui/app/components/ui/editable-label/editable-label.js index 12ce68a7b..acda2400b 100644 --- a/ui/app/components/ui/editable-label/editable-label.js +++ b/ui/app/components/ui/editable-label/editable-label.js @@ -1,33 +1,33 @@ -import classnames from 'classnames' -import PropTypes from 'prop-types' -import React, { Component } from 'react' +import classnames from 'classnames'; +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; class EditableLabel extends Component { static propTypes = { onSubmit: PropTypes.func.isRequired, defaultValue: PropTypes.string, className: PropTypes.string, - } + }; state = { isEditing: false, value: this.props.defaultValue || '', - } + }; handleSubmit() { - const { value } = this.state + const { value } = this.state; if (value === '') { - return + return; } Promise.resolve(this.props.onSubmit(value)).then(() => this.setState({ isEditing: false }), - ) + ); } renderEditing() { - const { value } = this.state + const { value } = this.state; return [ { if (event.key === 'Enter') { - this.handleSubmit() + this.handleSubmit(); } }} onChange={(event) => this.setState({ value: event.target.value })} @@ -54,7 +54,7 @@ class EditableLabel extends Component { > , - ] + ]; } renderReadonly() { @@ -69,19 +69,19 @@ class EditableLabel extends Component { > , - ] + ]; } render() { - const { isEditing } = this.state - const { className } = this.props + const { isEditing } = this.state; + const { className } = this.props; return (
    {isEditing ? this.renderEditing() : this.renderReadonly()}
    - ) + ); } } -export default EditableLabel +export default EditableLabel; diff --git a/ui/app/components/ui/editable-label/index.js b/ui/app/components/ui/editable-label/index.js index 43078e7f7..a70b6b8d7 100644 --- a/ui/app/components/ui/editable-label/index.js +++ b/ui/app/components/ui/editable-label/index.js @@ -1 +1 @@ -export { default } from './editable-label' +export { default } from './editable-label'; diff --git a/ui/app/components/ui/error-message/error-message.component.js b/ui/app/components/ui/error-message/error-message.component.js index fdb8b651f..399c7c24c 100644 --- a/ui/app/components/ui/error-message/error-message.component.js +++ b/ui/app/components/ui/error-message/error-message.component.js @@ -1,25 +1,25 @@ -import React from 'react' -import PropTypes from 'prop-types' +import React from 'react'; +import PropTypes from 'prop-types'; const ErrorMessage = (props, context) => { - const { errorMessage, errorKey } = props - const error = errorKey ? context.t(errorKey) : errorMessage + const { errorMessage, errorKey } = props; + const error = errorKey ? context.t(errorKey) : errorMessage; return (
    {`ALERT: ${error}`}
    - ) -} + ); +}; ErrorMessage.propTypes = { errorMessage: PropTypes.string, errorKey: PropTypes.string, -} +}; ErrorMessage.contextTypes = { t: PropTypes.func, -} +}; -export default ErrorMessage +export default ErrorMessage; diff --git a/ui/app/components/ui/error-message/index.js b/ui/app/components/ui/error-message/index.js index 1c97a9955..d4ea3575f 100644 --- a/ui/app/components/ui/error-message/index.js +++ b/ui/app/components/ui/error-message/index.js @@ -1 +1 @@ -export { default } from './error-message.component' +export { default } from './error-message.component'; diff --git a/ui/app/components/ui/error-message/tests/error-message.component.test.js b/ui/app/components/ui/error-message/tests/error-message.component.test.js index 884fe6565..a6c2d4ac3 100644 --- a/ui/app/components/ui/error-message/tests/error-message.component.test.js +++ b/ui/app/components/ui/error-message/tests/error-message.component.test.js @@ -1,36 +1,36 @@ -import assert from 'assert' -import React from 'react' -import { shallow } from 'enzyme' -import ErrorMessage from '../error-message.component' +import assert from 'assert'; +import React from 'react'; +import { shallow } from 'enzyme'; +import ErrorMessage from '../error-message.component'; describe('ErrorMessage Component', function () { - const t = (key) => `translate ${key}` + const t = (key) => `translate ${key}`; it('should render a message from props.errorMessage', function () { const wrapper = shallow(, { context: { t }, - }) + }); - assert.ok(wrapper) - assert.strictEqual(wrapper.find('.error-message').length, 1) - assert.strictEqual(wrapper.find('.error-message__icon').length, 1) + assert.ok(wrapper); + assert.strictEqual(wrapper.find('.error-message').length, 1); + assert.strictEqual(wrapper.find('.error-message__icon').length, 1); assert.strictEqual( wrapper.find('.error-message__text').text(), 'ALERT: This is an error.', - ) - }) + ); + }); it('should render a message translated from props.errorKey', function () { const wrapper = shallow(, { context: { t }, - }) + }); - assert.ok(wrapper) - assert.strictEqual(wrapper.find('.error-message').length, 1) - assert.strictEqual(wrapper.find('.error-message__icon').length, 1) + assert.ok(wrapper); + assert.strictEqual(wrapper.find('.error-message').length, 1); + assert.strictEqual(wrapper.find('.error-message__icon').length, 1); assert.strictEqual( wrapper.find('.error-message__text').text(), 'ALERT: translate testKey', - ) - }) -}) + ); + }); +}); diff --git a/ui/app/components/ui/export-text-container/export-text-container.component.js b/ui/app/components/ui/export-text-container/export-text-container.component.js index 2afa20575..8eb56cf8b 100644 --- a/ui/app/components/ui/export-text-container/export-text-container.component.js +++ b/ui/app/components/ui/export-text-container/export-text-container.component.js @@ -1,13 +1,13 @@ -import React from 'react' -import PropTypes from 'prop-types' -import { exportAsFile } from '../../../helpers/utils/util' -import Copy from '../icon/copy-icon.component' -import { useI18nContext } from '../../../hooks/useI18nContext' -import { useCopyToClipboard } from '../../../hooks/useCopyToClipboard' +import React from 'react'; +import PropTypes from 'prop-types'; +import { exportAsFile } from '../../../helpers/utils/util'; +import Copy from '../icon/copy-icon.component'; +import { useI18nContext } from '../../../hooks/useI18nContext'; +import { useCopyToClipboard } from '../../../hooks/useCopyToClipboard'; function ExportTextContainer({ text = '' }) { - const t = useI18nContext() - const [copied, handleCopy] = useCopyToClipboard() + const t = useI18nContext(); + const [copied, handleCopy] = useCopyToClipboard(); return (
    @@ -18,7 +18,7 @@ function ExportTextContainer({ text = '' }) {
    { - handleCopy(text) + handleCopy(text); }} > @@ -37,11 +37,11 @@ function ExportTextContainer({ text = '' }) {
    - ) + ); } ExportTextContainer.propTypes = { text: PropTypes.string, -} +}; -export default React.memo(ExportTextContainer) +export default React.memo(ExportTextContainer); diff --git a/ui/app/components/ui/export-text-container/index.js b/ui/app/components/ui/export-text-container/index.js index 3c610389f..042e4ada7 100644 --- a/ui/app/components/ui/export-text-container/index.js +++ b/ui/app/components/ui/export-text-container/index.js @@ -1,3 +1,3 @@ -import ExportTextContainer from './export-text-container.component' +import ExportTextContainer from './export-text-container.component'; -export default ExportTextContainer +export default ExportTextContainer; diff --git a/ui/app/components/ui/hex-to-decimal/hex-to-decimal.component.js b/ui/app/components/ui/hex-to-decimal/hex-to-decimal.component.js index 69ddea055..762b7ccf0 100644 --- a/ui/app/components/ui/hex-to-decimal/hex-to-decimal.component.js +++ b/ui/app/components/ui/hex-to-decimal/hex-to-decimal.component.js @@ -1,17 +1,17 @@ -import React, { PureComponent } from 'react' -import PropTypes from 'prop-types' -import { hexToDecimal } from '../../../helpers/utils/conversions.util' +import React, { PureComponent } from 'react'; +import PropTypes from 'prop-types'; +import { hexToDecimal } from '../../../helpers/utils/conversions.util'; export default class HexToDecimal extends PureComponent { static propTypes = { className: PropTypes.string, value: PropTypes.string, - } + }; render() { - const { className, value } = this.props - const decimalValue = hexToDecimal(value) + const { className, value } = this.props; + const decimalValue = hexToDecimal(value); - return
    {decimalValue}
    + return
    {decimalValue}
    ; } } diff --git a/ui/app/components/ui/hex-to-decimal/index.js b/ui/app/components/ui/hex-to-decimal/index.js index 6e8567ca9..94f00781d 100644 --- a/ui/app/components/ui/hex-to-decimal/index.js +++ b/ui/app/components/ui/hex-to-decimal/index.js @@ -1 +1 @@ -export { default } from './hex-to-decimal.component' +export { default } from './hex-to-decimal.component'; diff --git a/ui/app/components/ui/hex-to-decimal/tests/hex-to-decimal.component.test.js b/ui/app/components/ui/hex-to-decimal/tests/hex-to-decimal.component.test.js index cb75bfd63..30bff9fce 100644 --- a/ui/app/components/ui/hex-to-decimal/tests/hex-to-decimal.component.test.js +++ b/ui/app/components/ui/hex-to-decimal/tests/hex-to-decimal.component.test.js @@ -1,24 +1,24 @@ -import assert from 'assert' -import React from 'react' -import { shallow } from 'enzyme' -import HexToDecimal from '../hex-to-decimal.component' +import assert from 'assert'; +import React from 'react'; +import { shallow } from 'enzyme'; +import HexToDecimal from '../hex-to-decimal.component'; describe('HexToDecimal Component', function () { it('should render a prefixed hex as a decimal with a className', function () { const wrapper = shallow( , - ) + ); - assert.ok(wrapper.hasClass('hex-to-decimal')) - assert.strictEqual(wrapper.text(), '12345') - }) + assert.ok(wrapper.hasClass('hex-to-decimal')); + assert.strictEqual(wrapper.text(), '12345'); + }); it('should render an unprefixed hex as a decimal with a className', function () { const wrapper = shallow( , - ) + ); - assert.ok(wrapper.hasClass('hex-to-decimal')) - assert.strictEqual(wrapper.text(), '6789') - }) -}) + assert.ok(wrapper.hasClass('hex-to-decimal')); + assert.strictEqual(wrapper.text(), '6789'); + }); +}); diff --git a/ui/app/components/ui/icon-border/icon-border.js b/ui/app/components/ui/icon-border/icon-border.js index f320a04b8..5ef8186b6 100644 --- a/ui/app/components/ui/icon-border/icon-border.js +++ b/ui/app/components/ui/icon-border/icon-border.js @@ -1,16 +1,16 @@ -import React from 'react' -import PropTypes from 'prop-types' +import React from 'react'; +import PropTypes from 'prop-types'; export default function IconBorder({ children, size }) { - const borderStyle = { height: `${size}px`, width: `${size}px` } + const borderStyle = { height: `${size}px`, width: `${size}px` }; return (
    {children}
    - ) + ); } IconBorder.propTypes = { children: PropTypes.node.isRequired, size: PropTypes.number.isRequired, -} +}; diff --git a/ui/app/components/ui/icon-border/index.js b/ui/app/components/ui/icon-border/index.js index dea3f116e..adcb92af2 100644 --- a/ui/app/components/ui/icon-border/index.js +++ b/ui/app/components/ui/icon-border/index.js @@ -1 +1 @@ -export { default } from './icon-border' +export { default } from './icon-border'; diff --git a/ui/app/components/ui/icon-button/icon-button.js b/ui/app/components/ui/icon-button/icon-button.js index 7d95fa8d4..dacd1ef25 100644 --- a/ui/app/components/ui/icon-button/icon-button.js +++ b/ui/app/components/ui/icon-button/icon-button.js @@ -1,8 +1,8 @@ -import React from 'react' -import PropTypes from 'prop-types' -import classNames from 'classnames' +import React from 'react'; +import PropTypes from 'prop-types'; +import classNames from 'classnames'; -const defaultRender = (inner) => inner +const defaultRender = (inner) => inner; export default function IconButton({ onClick, @@ -13,7 +13,7 @@ export default function IconButton({ className, ...props }) { - const renderWrapper = tooltipRender ?? defaultRender + const renderWrapper = tooltipRender ?? defaultRender; return ( - ) + ); } IconButton.propTypes = { @@ -43,4 +43,4 @@ IconButton.propTypes = { tooltipRender: PropTypes.func, className: PropTypes.string, 'data-testid': PropTypes.string, -} +}; diff --git a/ui/app/components/ui/icon-button/index.js b/ui/app/components/ui/icon-button/index.js index 5e3ded37f..06569218c 100644 --- a/ui/app/components/ui/icon-button/index.js +++ b/ui/app/components/ui/icon-button/index.js @@ -1 +1 @@ -export { default } from './icon-button' +export { default } from './icon-button'; diff --git a/ui/app/components/ui/icon-with-fallback/icon-with-fallback.component.js b/ui/app/components/ui/icon-with-fallback/icon-with-fallback.component.js index 27e16d28e..fec573cd0 100644 --- a/ui/app/components/ui/icon-with-fallback/icon-with-fallback.component.js +++ b/ui/app/components/ui/icon-with-fallback/icon-with-fallback.component.js @@ -1,6 +1,6 @@ -import React, { PureComponent } from 'react' -import PropTypes from 'prop-types' -import classnames from 'classnames' +import React, { PureComponent } from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; export default class IconWithFallback extends PureComponent { static propTypes = { @@ -9,20 +9,20 @@ export default class IconWithFallback extends PureComponent { size: PropTypes.number, className: PropTypes.string, fallbackClassName: PropTypes.string, - } + }; static defaultProps = { name: '', icon: null, - } + }; state = { iconError: false, - } + }; render() { - const { icon, name, size, className, fallbackClassName } = this.props - const style = size ? { height: `${size}px`, width: `${size}px` } : {} + const { icon, name, size, className, fallbackClassName } = this.props; + const style = size ? { height: `${size}px`, width: `${size}px` } : {}; return !this.state.iconError && icon ? ( {name.length ? name.charAt(0).toUpperCase() : ''}
    - ) + ); } } diff --git a/ui/app/components/ui/icon-with-fallback/index.js b/ui/app/components/ui/icon-with-fallback/index.js index 8c1f9a154..ef5111107 100644 --- a/ui/app/components/ui/icon-with-fallback/index.js +++ b/ui/app/components/ui/icon-with-fallback/index.js @@ -1 +1 @@ -export { default } from './icon-with-fallback.component' +export { default } from './icon-with-fallback.component'; diff --git a/ui/app/components/ui/icon-with-label/icon-with-label.js b/ui/app/components/ui/icon-with-label/icon-with-label.js index 1cb69d66f..3551d10a5 100644 --- a/ui/app/components/ui/icon-with-label/icon-with-label.js +++ b/ui/app/components/ui/icon-with-label/icon-with-label.js @@ -1,6 +1,6 @@ -import React from 'react' -import classnames from 'classnames' -import PropTypes from 'prop-types' +import React from 'react'; +import classnames from 'classnames'; +import PropTypes from 'prop-types'; export default function IconWithLabel({ icon, label, className }) { return ( @@ -8,11 +8,11 @@ export default function IconWithLabel({ icon, label, className }) { {icon} {label && {label}} - ) + ); } IconWithLabel.propTypes = { icon: PropTypes.node.isRequired, className: PropTypes.string, label: PropTypes.string, -} +}; diff --git a/ui/app/components/ui/icon-with-label/index.js b/ui/app/components/ui/icon-with-label/index.js index 10432ac8f..3cadb2d12 100644 --- a/ui/app/components/ui/icon-with-label/index.js +++ b/ui/app/components/ui/icon-with-label/index.js @@ -1 +1 @@ -export { default } from './icon-with-label' +export { default } from './icon-with-label'; diff --git a/ui/app/components/ui/icon/approve-icon.component.js b/ui/app/components/ui/icon/approve-icon.component.js index 79127a85a..e60d604da 100644 --- a/ui/app/components/ui/icon/approve-icon.component.js +++ b/ui/app/components/ui/icon/approve-icon.component.js @@ -1,5 +1,5 @@ -import React from 'react' -import PropTypes from 'prop-types' +import React from 'react'; +import PropTypes from 'prop-types'; const Approve = ({ className, size, color }) => ( ( fill={color} /> -) +); Approve.defaultProps = { className: undefined, -} +}; Approve.propTypes = { className: PropTypes.string, size: PropTypes.number.isRequired, color: PropTypes.string.isRequired, -} +}; -export default Approve +export default Approve; diff --git a/ui/app/components/ui/icon/copy-icon.component.js b/ui/app/components/ui/icon/copy-icon.component.js index dc0d4cd1c..e9b2dc78c 100644 --- a/ui/app/components/ui/icon/copy-icon.component.js +++ b/ui/app/components/ui/icon/copy-icon.component.js @@ -1,5 +1,5 @@ -import React from 'react' -import PropTypes from 'prop-types' +import React from 'react'; +import PropTypes from 'prop-types'; const Copy = ({ className, size, color }) => ( ( fill={color} /> -) +); Copy.defaultProps = { className: undefined, -} +}; Copy.propTypes = { className: PropTypes.string, size: PropTypes.number.isRequired, color: PropTypes.string.isRequired, -} +}; -export default Copy +export default Copy; diff --git a/ui/app/components/ui/icon/icon.stories.js b/ui/app/components/ui/icon/icon.stories.js index ff750bc5d..6f2e35ddf 100644 --- a/ui/app/components/ui/icon/icon.stories.js +++ b/ui/app/components/ui/icon/icon.stories.js @@ -1,55 +1,55 @@ -import React from 'react' -import { color, number, select } from '@storybook/addon-knobs' -import { SEVERITIES } from '../../../helpers/constants/design-system' -import Approve from './approve-icon.component' -import Copy from './copy-icon.component' -import Interaction from './interaction-icon.component' -import Preloader from './preloader' -import Receive from './receive-icon.component' -import Send from './send-icon.component' -import InfoIcon from './info-icon.component' -import InfoIconInverted from './info-icon-inverted.component' +import React from 'react'; +import { color, number, select } from '@storybook/addon-knobs'; +import { SEVERITIES } from '../../../helpers/constants/design-system'; +import Approve from './approve-icon.component'; +import Copy from './copy-icon.component'; +import Interaction from './interaction-icon.component'; +import Preloader from './preloader'; +import Receive from './receive-icon.component'; +import Send from './send-icon.component'; +import InfoIcon from './info-icon.component'; +import InfoIconInverted from './info-icon-inverted.component'; export default { title: 'Icon', -} +}; export const copy = () => ( -) +); export const send = () => ( -) +); export const receive = () => ( -) +); export const siteInteraction = () => ( -) +); export const approveSpendLimit = () => ( -) +); -export const preloader = () => +export const preloader = () => ; export const PaperAirplane = () => ( -) +); export const info = () => ( -) +); export const infoInverted = () => ( -) +); diff --git a/ui/app/components/ui/icon/info-icon-inverted.component.js b/ui/app/components/ui/icon/info-icon-inverted.component.js index df057aa07..3eef46cc0 100644 --- a/ui/app/components/ui/icon/info-icon-inverted.component.js +++ b/ui/app/components/ui/icon/info-icon-inverted.component.js @@ -1,7 +1,7 @@ -import React from 'react' -import classnames from 'classnames' -import PropTypes from 'prop-types' -import { SEVERITIES } from '../../../helpers/constants/design-system' +import React from 'react'; +import classnames from 'classnames'; +import PropTypes from 'prop-types'; +import { SEVERITIES } from '../../../helpers/constants/design-system'; export default function InfoIconInverted({ severity }) { const className = classnames('info-icon', { @@ -9,7 +9,7 @@ export default function InfoIconInverted({ severity }) { 'info-icon--warning': severity === SEVERITIES.WARNING, 'info-icon--danger': severity === SEVERITIES.DANGER, 'info-icon--info': severity === SEVERITIES.INFO, - }) + }); return ( - ) + ); } InfoIconInverted.propTypes = { severity: PropTypes.oneOf(Object.values(SEVERITIES)), -} +}; diff --git a/ui/app/components/ui/icon/info-icon.component.js b/ui/app/components/ui/icon/info-icon.component.js index 3d2ec7e7d..824a81a40 100644 --- a/ui/app/components/ui/icon/info-icon.component.js +++ b/ui/app/components/ui/icon/info-icon.component.js @@ -1,7 +1,7 @@ -import React from 'react' -import classnames from 'classnames' -import PropTypes from 'prop-types' -import { SEVERITIES } from '../../../helpers/constants/design-system' +import React from 'react'; +import classnames from 'classnames'; +import PropTypes from 'prop-types'; +import { SEVERITIES } from '../../../helpers/constants/design-system'; export default function InfoIcon({ severity }) { const className = classnames('info-icon', { @@ -9,7 +9,7 @@ export default function InfoIcon({ severity }) { 'info-icon--warning': severity === SEVERITIES.WARNING, 'info-icon--danger': severity === SEVERITIES.DANGER, 'info-icon--info': severity === SEVERITIES.INFO, - }) + }); return ( - ) + ); } InfoIcon.propTypes = { severity: PropTypes.oneOf(Object.values(SEVERITIES)), -} +}; diff --git a/ui/app/components/ui/icon/interaction-icon.component.js b/ui/app/components/ui/icon/interaction-icon.component.js index 0d96c8753..93ef6e08e 100644 --- a/ui/app/components/ui/icon/interaction-icon.component.js +++ b/ui/app/components/ui/icon/interaction-icon.component.js @@ -1,5 +1,5 @@ -import React from 'react' -import PropTypes from 'prop-types' +import React from 'react'; +import PropTypes from 'prop-types'; const Interaction = ({ className, size, color }) => ( ( fill={color} /> -) +); Interaction.defaultProps = { className: undefined, -} +}; Interaction.propTypes = { className: PropTypes.string, size: PropTypes.number.isRequired, color: PropTypes.string.isRequired, -} +}; -export default Interaction +export default Interaction; diff --git a/ui/app/components/ui/icon/overview-buy-icon.component.js b/ui/app/components/ui/icon/overview-buy-icon.component.js index aca33efb2..c7be24b95 100644 --- a/ui/app/components/ui/icon/overview-buy-icon.component.js +++ b/ui/app/components/ui/icon/overview-buy-icon.component.js @@ -1,5 +1,5 @@ -import React from 'react' -import PropTypes from 'prop-types' +import React from 'react'; +import PropTypes from 'prop-types'; export default function BuyIcon({ width = '17', @@ -27,11 +27,11 @@ export default function BuyIcon({ fill="white" /> - ) + ); } BuyIcon.propTypes = { width: PropTypes.string, height: PropTypes.string, fill: PropTypes.string, -} +}; diff --git a/ui/app/components/ui/icon/overview-send-icon.component.js b/ui/app/components/ui/icon/overview-send-icon.component.js index 310e9ebeb..05879ed2f 100644 --- a/ui/app/components/ui/icon/overview-send-icon.component.js +++ b/ui/app/components/ui/icon/overview-send-icon.component.js @@ -1,5 +1,5 @@ -import React from 'react' -import PropTypes from 'prop-types' +import React from 'react'; +import PropTypes from 'prop-types'; export default function SwapIcon({ width = '15', @@ -19,11 +19,11 @@ export default function SwapIcon({ fill={fill} /> - ) + ); } SwapIcon.propTypes = { width: PropTypes.string, height: PropTypes.string, fill: PropTypes.string, -} +}; diff --git a/ui/app/components/ui/icon/paper-airplane-icon.js b/ui/app/components/ui/icon/paper-airplane-icon.js index 0db6a424e..5bd156704 100644 --- a/ui/app/components/ui/icon/paper-airplane-icon.js +++ b/ui/app/components/ui/icon/paper-airplane-icon.js @@ -1,5 +1,5 @@ -import React from 'react' -import PropTypes from 'prop-types' +import React from 'react'; +import PropTypes from 'prop-types'; export default function PaperAirplane({ size, className, color }) { return ( @@ -18,15 +18,15 @@ export default function PaperAirplane({ size, className, color }) { fill={color} /> - ) + ); } PaperAirplane.defaultProps = { color: '#FFFFFF', -} +}; PaperAirplane.propTypes = { className: PropTypes.string, size: PropTypes.number.isRequired, color: PropTypes.string, -} +}; diff --git a/ui/app/components/ui/icon/preloader/index.js b/ui/app/components/ui/icon/preloader/index.js index b8c7793d6..c9387865a 100644 --- a/ui/app/components/ui/icon/preloader/index.js +++ b/ui/app/components/ui/icon/preloader/index.js @@ -1,3 +1,3 @@ -import preloader from './preloader-icon.component' +import preloader from './preloader-icon.component'; -export default preloader +export default preloader; diff --git a/ui/app/components/ui/icon/preloader/preloader-icon.component.js b/ui/app/components/ui/icon/preloader/preloader-icon.component.js index fc7cb5707..87ca7f299 100644 --- a/ui/app/components/ui/icon/preloader/preloader-icon.component.js +++ b/ui/app/components/ui/icon/preloader/preloader-icon.component.js @@ -1,6 +1,6 @@ -import React from 'react' -import PropTypes from 'prop-types' -import classnames from 'classnames' +import React from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; const Preloader = ({ className, size }) => ( ( /> -) +); Preloader.defaultProps = { className: undefined, -} +}; Preloader.propTypes = { className: PropTypes.string, size: PropTypes.number.isRequired, -} +}; -export default Preloader +export default Preloader; diff --git a/ui/app/components/ui/icon/receive-icon.component.js b/ui/app/components/ui/icon/receive-icon.component.js index 67317d7ed..530fd5170 100644 --- a/ui/app/components/ui/icon/receive-icon.component.js +++ b/ui/app/components/ui/icon/receive-icon.component.js @@ -1,5 +1,5 @@ -import React from 'react' -import PropTypes from 'prop-types' +import React from 'react'; +import PropTypes from 'prop-types'; const Receive = ({ className, size, color }) => ( ( fill={color} /> -) +); Receive.defaultProps = { className: undefined, -} +}; Receive.propTypes = { className: PropTypes.string, size: PropTypes.number.isRequired, color: PropTypes.string.isRequired, -} +}; -export default Receive +export default Receive; diff --git a/ui/app/components/ui/icon/send-icon.component.js b/ui/app/components/ui/icon/send-icon.component.js index c8ec227ae..d1ee9d24f 100644 --- a/ui/app/components/ui/icon/send-icon.component.js +++ b/ui/app/components/ui/icon/send-icon.component.js @@ -1,5 +1,5 @@ -import React from 'react' -import PropTypes from 'prop-types' +import React from 'react'; +import PropTypes from 'prop-types'; const Send = ({ className, size, color }) => ( ( fill={color} /> -) +); Send.defaultProps = { className: undefined, -} +}; Send.propTypes = { className: PropTypes.string, size: PropTypes.number.isRequired, color: PropTypes.string.isRequired, -} +}; -export default Send +export default Send; diff --git a/ui/app/components/ui/icon/sign-icon.component.js b/ui/app/components/ui/icon/sign-icon.component.js index f3bf6e2d7..887085826 100644 --- a/ui/app/components/ui/icon/sign-icon.component.js +++ b/ui/app/components/ui/icon/sign-icon.component.js @@ -1,5 +1,5 @@ -import React from 'react' -import PropTypes from 'prop-types' +import React from 'react'; +import PropTypes from 'prop-types'; export default function Sign({ className, size, color }) { return ( @@ -24,11 +24,11 @@ export default function Sign({ className, size, color }) { fill={color} /> - ) + ); } Sign.propTypes = { className: PropTypes.string, size: PropTypes.number.isRequired, color: PropTypes.string.isRequired, -} +}; diff --git a/ui/app/components/ui/icon/sun-check-icon.component.js b/ui/app/components/ui/icon/sun-check-icon.component.js index c6029e37c..31dd19404 100644 --- a/ui/app/components/ui/icon/sun-check-icon.component.js +++ b/ui/app/components/ui/icon/sun-check-icon.component.js @@ -1,9 +1,9 @@ -import React from 'react' -import PropTypes from 'prop-types' +import React from 'react'; +import PropTypes from 'prop-types'; export default function SunCheck({ reverseColors }) { - const sunColor = reverseColors ? '#037DD6' : 'white' - const checkColor = reverseColors ? 'white' : '#037DD6' + const sunColor = reverseColors ? '#037DD6' : 'white'; + const checkColor = reverseColors ? 'white' : '#037DD6'; return ( - ) + ); } SunCheck.propTypes = { reverseColors: PropTypes.bool, -} +}; diff --git a/ui/app/components/ui/icon/swap-icon-for-list.component.js b/ui/app/components/ui/icon/swap-icon-for-list.component.js index 1e2d5453a..5c20b51f5 100644 --- a/ui/app/components/ui/icon/swap-icon-for-list.component.js +++ b/ui/app/components/ui/icon/swap-icon-for-list.component.js @@ -1,5 +1,5 @@ -import React from 'react' -import PropTypes from 'prop-types' +import React from 'react'; +import PropTypes from 'prop-types'; const Swap = ({ className, size, color }) => ( ( fill={color} /> -) +); Swap.defaultProps = { className: undefined, -} +}; Swap.propTypes = { className: PropTypes.string, size: PropTypes.number.isRequired, color: PropTypes.string.isRequired, -} +}; -export default Swap +export default Swap; diff --git a/ui/app/components/ui/icon/swap-icon.component.js b/ui/app/components/ui/icon/swap-icon.component.js index f8c147580..32dd6f916 100644 --- a/ui/app/components/ui/icon/swap-icon.component.js +++ b/ui/app/components/ui/icon/swap-icon.component.js @@ -1,5 +1,5 @@ -import React from 'react' -import PropTypes from 'prop-types' +import React from 'react'; +import PropTypes from 'prop-types'; export default function SwapIcon({ width = '17', @@ -21,11 +21,11 @@ export default function SwapIcon({ strokeWidth="0.1" /> - ) + ); } SwapIcon.propTypes = { width: PropTypes.string, height: PropTypes.string, color: PropTypes.string, -} +}; diff --git a/ui/app/components/ui/identicon/blockieIdenticon/blockieIdenticon.component.js b/ui/app/components/ui/identicon/blockieIdenticon/blockieIdenticon.component.js index 05d201e22..341abe441 100644 --- a/ui/app/components/ui/identicon/blockieIdenticon/blockieIdenticon.component.js +++ b/ui/app/components/ui/identicon/blockieIdenticon/blockieIdenticon.component.js @@ -1,33 +1,33 @@ -import React, { useEffect, useRef, useState } from 'react' -import PropTypes from 'prop-types' -import { renderIcon } from '@download/blockies' +import React, { useEffect, useRef, useState } from 'react'; +import PropTypes from 'prop-types'; +import { renderIcon } from '@download/blockies'; const BlockieIdenticon = ({ address, diameter, alt }) => { - const [dataUrl, setDataUrl] = useState(null) - const canvasRef = useRef(null) + const [dataUrl, setDataUrl] = useState(null); + const canvasRef = useRef(null); useEffect(() => { - const canvas = canvasRef.current - renderIcon({ seed: address.toLowerCase() }, canvas) - const updatedDataUrl = canvas.toDataURL() + const canvas = canvasRef.current; + renderIcon({ seed: address.toLowerCase() }, canvas); + const updatedDataUrl = canvas.toDataURL(); if (updatedDataUrl !== dataUrl) { - setDataUrl(updatedDataUrl) + setDataUrl(updatedDataUrl); } - }, [dataUrl, address]) + }, [dataUrl, address]); return ( <> {alt - ) -} + ); +}; BlockieIdenticon.propTypes = { address: PropTypes.string.isRequired, diameter: PropTypes.number.isRequired, alt: PropTypes.string, -} +}; -export default BlockieIdenticon +export default BlockieIdenticon; diff --git a/ui/app/components/ui/identicon/blockieIdenticon/index.js b/ui/app/components/ui/identicon/blockieIdenticon/index.js index a87ff9323..63c88d064 100644 --- a/ui/app/components/ui/identicon/blockieIdenticon/index.js +++ b/ui/app/components/ui/identicon/blockieIdenticon/index.js @@ -1 +1 @@ -export { default } from './blockieIdenticon.component' +export { default } from './blockieIdenticon.component'; diff --git a/ui/app/components/ui/identicon/identicon.component.js b/ui/app/components/ui/identicon/identicon.component.js index 09a731eca..91f3a11f5 100644 --- a/ui/app/components/ui/identicon/identicon.component.js +++ b/ui/app/components/ui/identicon/identicon.component.js @@ -1,17 +1,17 @@ -import React, { PureComponent } from 'react' -import PropTypes from 'prop-types' -import classnames from 'classnames' -import contractMap from '@metamask/contract-metadata' +import React, { PureComponent } from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; +import contractMap from '@metamask/contract-metadata'; -import { checksumAddress } from '../../../helpers/utils/util' -import Jazzicon from '../jazzicon' -import BlockieIdenticon from './blockieIdenticon' +import { checksumAddress } from '../../../helpers/utils/util'; +import Jazzicon from '../jazzicon'; +import BlockieIdenticon from './blockieIdenticon'; const getStyles = (diameter) => ({ height: diameter, width: diameter, borderRadius: diameter / 2, -}) +}); export default class Identicon extends PureComponent { static propTypes = { @@ -22,7 +22,7 @@ export default class Identicon extends PureComponent { image: PropTypes.string, useBlockie: PropTypes.bool, alt: PropTypes.string, - } + }; static defaultProps = { addBorder: false, @@ -32,10 +32,10 @@ export default class Identicon extends PureComponent { image: undefined, useBlockie: false, alt: '', - } + }; renderImage() { - const { className, diameter, image, alt } = this.props + const { className, diameter, image, alt } = this.props; return ( {alt} - ) + ); } renderJazzicon() { - const { address, className, diameter, alt } = this.props + const { address, className, diameter, alt } = this.props; return ( - ) + ); } renderBlockie() { - const { address, className, diameter, alt } = this.props + const { address, className, diameter, alt } = this.props; return (
    - ) + ); } render() { @@ -83,17 +83,17 @@ export default class Identicon extends PureComponent { useBlockie, addBorder, alt, - } = this.props + } = this.props; if (image) { - return this.renderImage() + return this.renderImage(); } if (address) { - const checksummedAddress = checksumAddress(address) + const checksummedAddress = checksumAddress(address); if (contractMap[checksummedAddress]?.logo) { - return this.renderJazzicon() + return this.renderJazzicon(); } return ( @@ -102,7 +102,7 @@ export default class Identicon extends PureComponent { > {useBlockie ? this.renderBlockie() : this.renderJazzicon()} - ) + ); } return ( @@ -112,6 +112,6 @@ export default class Identicon extends PureComponent { style={getStyles(diameter)} alt={alt} /> - ) + ); } } diff --git a/ui/app/components/ui/identicon/identicon.container.js b/ui/app/components/ui/identicon/identicon.container.js index 0ee6f7841..2ed017abb 100644 --- a/ui/app/components/ui/identicon/identicon.container.js +++ b/ui/app/components/ui/identicon/identicon.container.js @@ -1,14 +1,14 @@ -import { connect } from 'react-redux' -import Identicon from './identicon.component' +import { connect } from 'react-redux'; +import Identicon from './identicon.component'; const mapStateToProps = (state) => { const { metamask: { useBlockie }, - } = state + } = state; return { useBlockie, - } -} + }; +}; -export default connect(mapStateToProps)(Identicon) +export default connect(mapStateToProps)(Identicon); diff --git a/ui/app/components/ui/identicon/identicon.stories.js b/ui/app/components/ui/identicon/identicon.stories.js index 0dbefe0ff..a71928bfd 100644 --- a/ui/app/components/ui/identicon/identicon.stories.js +++ b/ui/app/components/ui/identicon/identicon.stories.js @@ -1,15 +1,15 @@ -import React from 'react' -import { text, boolean, number } from '@storybook/addon-knobs' -import Identicon from './identicon.component' +import React from 'react'; +import { text, boolean, number } from '@storybook/addon-knobs'; +import Identicon from './identicon.component'; -export default { title: 'Identicon' } +export default { title: 'Identicon' }; const diameterOptions = { range: true, min: 10, max: 200, step: 1, -} +}; export const standard = () => ( ( )} useBlockie={boolean('Use Blockie', Identicon.defaultProps.useBlockie)} /> -) +); -export const image = () => +export const image = () => ; export const blockie = () => ( -) +); // The border size is hard-coded in CSS, and was designed with this size identicon in mind -const withBorderDiameter = 32 +const withBorderDiameter = 32; export const withBorder = () => ( ( address={text('Address', '0x5CfE73b6021E818B776b421B1c4Db2474086a7e1')} diameter={number('Diameter', withBorderDiameter, diameterOptions)} /> -) +); diff --git a/ui/app/components/ui/identicon/index.js b/ui/app/components/ui/identicon/index.js index 799c886f2..5bc3a4285 100644 --- a/ui/app/components/ui/identicon/index.js +++ b/ui/app/components/ui/identicon/index.js @@ -1 +1 @@ -export { default } from './identicon.container' +export { default } from './identicon.container'; diff --git a/ui/app/components/ui/identicon/tests/identicon.component.test.js b/ui/app/components/ui/identicon/tests/identicon.component.test.js index c938657ab..3d33397ea 100644 --- a/ui/app/components/ui/identicon/tests/identicon.component.test.js +++ b/ui/app/components/ui/identicon/tests/identicon.component.test.js @@ -1,50 +1,53 @@ -import assert from 'assert' -import React from 'react' -import thunk from 'redux-thunk' -import configureMockStore from 'redux-mock-store' -import { mount } from 'enzyme' -import Identicon from '../identicon.component' +import assert from 'assert'; +import React from 'react'; +import thunk from 'redux-thunk'; +import configureMockStore from 'redux-mock-store'; +import { mount } from 'enzyme'; +import Identicon from '../identicon.component'; describe('Identicon', function () { const state = { metamask: { useBlockie: false, }, - } + }; - const middlewares = [thunk] - const mockStore = configureMockStore(middlewares) - const store = mockStore(state) + const middlewares = [thunk]; + const mockStore = configureMockStore(middlewares); + const store = mockStore(state); it('renders default eth_logo identicon with no props', function () { - const wrapper = mount() + const wrapper = mount(); assert.strictEqual( wrapper.find('img.identicon__eth-logo').prop('src'), './images/eth_logo.svg', - ) - }) + ); + }); it('renders custom image and add className props', function () { const wrapper = mount( , - ) + ); assert.strictEqual( wrapper.find('img.test-image').prop('className'), 'identicon test-image', - ) - assert.strictEqual(wrapper.find('img.test-image').prop('src'), 'test-image') - }) + ); + assert.strictEqual( + wrapper.find('img.test-image').prop('src'), + 'test-image', + ); + }); it('renders div with address prop', function () { const wrapper = mount( , - ) + ); assert.strictEqual( wrapper.find('div.test-address').prop('className'), 'identicon test-address', - ) - }) -}) + ); + }); +}); diff --git a/ui/app/components/ui/info-tooltip/index.js b/ui/app/components/ui/info-tooltip/index.js index 2fe0f2786..87014d15c 100644 --- a/ui/app/components/ui/info-tooltip/index.js +++ b/ui/app/components/ui/info-tooltip/index.js @@ -1 +1 @@ -export { default } from './info-tooltip' +export { default } from './info-tooltip'; diff --git a/ui/app/components/ui/info-tooltip/info-tooltip.js b/ui/app/components/ui/info-tooltip/info-tooltip.js index af2537f0c..4c67eefd0 100644 --- a/ui/app/components/ui/info-tooltip/info-tooltip.js +++ b/ui/app/components/ui/info-tooltip/info-tooltip.js @@ -1,14 +1,14 @@ -import React from 'react' -import PropTypes from 'prop-types' -import classnames from 'classnames' -import Tooltip from '../tooltip' +import React from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; +import Tooltip from '../tooltip'; const positionArrowClassMap = { top: 'info-tooltip__top-tooltip-arrow', bottom: 'info-tooltip__bottom-tooltip-arrow', left: 'info-tooltip__left-tooltip-arrow', right: 'info-tooltip__right-tooltip-arrow', -} +}; export default function InfoTooltip({ contentText = '', @@ -35,7 +35,7 @@ export default function InfoTooltip({ - ) + ); } InfoTooltip.propTypes = { @@ -44,4 +44,4 @@ InfoTooltip.propTypes = { wide: PropTypes.bool, containerClassName: PropTypes.string, wrapperClassName: PropTypes.string, -} +}; diff --git a/ui/app/components/ui/info-tooltip/info-tooltip.stories.js b/ui/app/components/ui/info-tooltip/info-tooltip.stories.js index dfe44e2cf..77756f9b3 100644 --- a/ui/app/components/ui/info-tooltip/info-tooltip.stories.js +++ b/ui/app/components/ui/info-tooltip/info-tooltip.stories.js @@ -1,10 +1,10 @@ -import React from 'react' -import { text } from '@storybook/addon-knobs' -import InfoTooltip from './info-tooltip' +import React from 'react'; +import { text } from '@storybook/addon-knobs'; +import InfoTooltip from './info-tooltip'; export default { title: 'InfoTooltip', -} +}; export const Top = () => ( ( 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut gravida dictum diam et sagittis. Sed lorem arcu, consectetur consectetur et, lacinia hendrerit sapien.', )} /> -) +); export const Bottom = () => ( ( 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut gravida dictum diam et sagittis. Sed lorem arcu, consectetur consectetur et, lacinia hendrerit sapien.', )} /> -) +); export const Left = () => ( ( 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut gravida dictum diam et sagittis. Sed lorem arcu, consectetur consectetur et, lacinia hendrerit sapien.', )} /> -) +); export const Right = () => ( ( 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut gravida dictum diam et sagittis. Sed lorem arcu, consectetur consectetur et, lacinia hendrerit sapien.', )} /> -) +); diff --git a/ui/app/components/ui/jazzicon/index.js b/ui/app/components/ui/jazzicon/index.js index bea900ab9..0ded7d437 100644 --- a/ui/app/components/ui/jazzicon/index.js +++ b/ui/app/components/ui/jazzicon/index.js @@ -1 +1 @@ -export { default } from './jazzicon.component' +export { default } from './jazzicon.component'; diff --git a/ui/app/components/ui/jazzicon/jazzicon.component.js b/ui/app/components/ui/jazzicon/jazzicon.component.js index 098b08507..5d1953009 100644 --- a/ui/app/components/ui/jazzicon/jazzicon.component.js +++ b/ui/app/components/ui/jazzicon/jazzicon.component.js @@ -1,9 +1,9 @@ -import React, { createRef, PureComponent } from 'react' -import PropTypes from 'prop-types' -import jazzicon from '@metamask/jazzicon' -import iconFactoryGenerator from '../../../../lib/icon-factory' +import React, { createRef, PureComponent } from 'react'; +import PropTypes from 'prop-types'; +import jazzicon from '@metamask/jazzicon'; +import iconFactoryGenerator from '../../../../lib/icon-factory'; -const iconFactory = iconFactoryGenerator(jazzicon) +const iconFactory = iconFactoryGenerator(jazzicon); /** * Wrapper around the jazzicon library to return a React component, as the library returns an @@ -15,45 +15,45 @@ export default class Jazzicon extends PureComponent { className: PropTypes.string, diameter: PropTypes.number, style: PropTypes.object, - } + }; static defaultProps = { diameter: 46, - } + }; - container = createRef() + container = createRef(); componentDidMount() { - this.appendJazzicon() + this.appendJazzicon(); } componentDidUpdate(prevProps) { - const { address: prevAddress, diameter: prevDiameter } = prevProps - const { address, diameter } = this.props + const { address: prevAddress, diameter: prevDiameter } = prevProps; + const { address, diameter } = this.props; if (address !== prevAddress || diameter !== prevDiameter) { - this.removeExistingChildren() - this.appendJazzicon() + this.removeExistingChildren(); + this.appendJazzicon(); } } removeExistingChildren() { - const { children } = this.container.current + const { children } = this.container.current; for (let i = 0; i < children.length; i++) { - this.container.current.removeChild(children[i]) + this.container.current.removeChild(children[i]); } } appendJazzicon() { - const { address, diameter } = this.props - const image = iconFactory.iconForAddress(address, diameter) - this.container.current.appendChild(image) + const { address, diameter } = this.props; + const image = iconFactory.iconForAddress(address, diameter); + this.container.current.appendChild(image); } render() { - const { className, style } = this.props + const { className, style } = this.props; - return
    + return
    ; } } diff --git a/ui/app/components/ui/list-item/index.js b/ui/app/components/ui/list-item/index.js index 867edb4df..c76dfda2f 100644 --- a/ui/app/components/ui/list-item/index.js +++ b/ui/app/components/ui/list-item/index.js @@ -1 +1 @@ -export { default } from './list-item.component' +export { default } from './list-item.component'; diff --git a/ui/app/components/ui/list-item/list-item.component.js b/ui/app/components/ui/list-item/list-item.component.js index 8ac979dd5..79649d672 100644 --- a/ui/app/components/ui/list-item/list-item.component.js +++ b/ui/app/components/ui/list-item/list-item.component.js @@ -1,6 +1,6 @@ -import React from 'react' -import PropTypes from 'prop-types' -import classnames from 'classnames' +import React from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; export default function ListItem({ title, @@ -14,7 +14,7 @@ export default function ListItem({ className, 'data-testid': dataTestId, }) { - const primaryClassName = classnames('list-item', className) + const primaryClassName = classnames('list-item', className); return (
    {rightContent}
    )}
    - ) + ); } ListItem.propTypes = { @@ -56,4 +56,4 @@ ListItem.propTypes = { className: PropTypes.string, onClick: PropTypes.func, 'data-testid': PropTypes.string, -} +}; diff --git a/ui/app/components/ui/list-item/list-item.stories.js b/ui/app/components/ui/list-item/list-item.stories.js index ce9f3d4af..93054a267 100644 --- a/ui/app/components/ui/list-item/list-item.stories.js +++ b/ui/app/components/ui/list-item/list-item.stories.js @@ -1,17 +1,17 @@ -import React from 'react' -import PropTypes from 'prop-types' -import { text } from '@storybook/addon-knobs' -import Send from '../icon/send-icon.component' -import Interaction from '../icon/interaction-icon.component' -import Approve from '../icon/approve-icon.component' -import Receive from '../icon/receive-icon.component' -import Preloader from '../icon/preloader' -import Button from '../button' -import ListItem from './list-item.component' +import React from 'react'; +import PropTypes from 'prop-types'; +import { text } from '@storybook/addon-knobs'; +import Send from '../icon/send-icon.component'; +import Interaction from '../icon/interaction-icon.component'; +import Approve from '../icon/approve-icon.component'; +import Receive from '../icon/receive-icon.component'; +import Preloader from '../icon/preloader'; +import Button from '../button'; +import ListItem from './list-item.component'; export default { title: 'ListItem', -} +}; function Currencies({ primary, secondary }) { return ( @@ -19,16 +19,16 @@ function Currencies({ primary, secondary }) {
    {primary}
    {secondary}
    - ) + ); } Currencies.propTypes = { primary: PropTypes.string, secondary: PropTypes.string, -} +}; -const okColor = '#2F80ED' -const failColor = '#D73A49' +const okColor = '#2F80ED'; +const failColor = '#D73A49'; export const send = () => ( ( -) +); export const pending = () => ( ( /> } /> -) +); export const approve = () => ( ( /> } /> -) +); export const receive = () => ( ( /> } /> -) +); diff --git a/ui/app/components/ui/list-item/tests/list-item.test.js b/ui/app/components/ui/list-item/tests/list-item.test.js index 6f9e132cd..488ee9039 100644 --- a/ui/app/components/ui/list-item/tests/list-item.test.js +++ b/ui/app/components/ui/list-item/tests/list-item.test.js @@ -1,23 +1,23 @@ -import assert from 'assert' -import { shallow } from 'enzyme' -import React from 'react' -import Sinon from 'sinon' -import ListItem from '../list-item.component' -import Preloader from '../../icon/preloader/preloader-icon.component' -import Send from '../../icon/send-icon.component' +import assert from 'assert'; +import { shallow } from 'enzyme'; +import React from 'react'; +import Sinon from 'sinon'; +import ListItem from '../list-item.component'; +import Preloader from '../../icon/preloader/preloader-icon.component'; +import Send from '../../icon/send-icon.component'; -const TITLE = 'Hello World' -const SUBTITLE =

    I am a list item

    -const CLASSNAME = 'list-item-test' -const RIGHT_CONTENT =

    Content rendered to the right

    -const CHILDREN = -const MID_CONTENT =

    Content rendered in the middle

    +const TITLE = 'Hello World'; +const SUBTITLE =

    I am a list item

    ; +const CLASSNAME = 'list-item-test'; +const RIGHT_CONTENT =

    Content rendered to the right

    ; +const CHILDREN = ; +const MID_CONTENT =

    Content rendered in the middle

    ; describe('ListItem', function () { - let wrapper - let clickHandler + let wrapper; + let clickHandler; before(function () { - clickHandler = Sinon.fake() + clickHandler = Sinon.fake(); wrapper = shallow( {CHILDREN} , - ) - }) + ); + }); it('includes the data-testid', function () { - assert.strictEqual(wrapper.props()['data-testid'], 'test-id') - }) + assert.strictEqual(wrapper.props()['data-testid'], 'test-id'); + }); it(`renders "${TITLE}" title`, function () { - assert.strictEqual(wrapper.find('.list-item__heading h2').text(), TITLE) - }) + assert.strictEqual(wrapper.find('.list-item__heading h2').text(), TITLE); + }); it(`renders "I am a list item" subtitle`, function () { assert.strictEqual( wrapper.find('.list-item__subheading').text(), 'I am a list item', - ) - }) + ); + }); it('attaches external className', function () { - assert(wrapper.props().className.includes(CLASSNAME)) - }) + assert(wrapper.props().className.includes(CLASSNAME)); + }); it('renders content on the right side of the list item', function () { assert.strictEqual( wrapper.find('.list-item__right-content p').text(), 'Content rendered to the right', - ) - }) + ); + }); it('renders content in the middle of the list item', function () { assert.strictEqual( wrapper.find('.list-item__mid-content p').text(), 'Content rendered in the middle', - ) - }) + ); + }); it('renders list item actions', function () { assert.strictEqual( wrapper.find('.list-item__actions button').text(), 'I am a button', - ) - }) + ); + }); it('renders the title icon', function () { - assert(wrapper.find(Preloader)) - }) + assert(wrapper.find(Preloader)); + }); it('renders the list item icon', function () { - assert(wrapper.find(Send)) - }) + assert(wrapper.find(Send)); + }); it('handles click action and fires onClick', function () { - wrapper.simulate('click') - assert.strictEqual(clickHandler.callCount, 1) - }) + wrapper.simulate('click'); + assert.strictEqual(clickHandler.callCount, 1); + }); after(function () { - Sinon.restore() - }) -}) + Sinon.restore(); + }); +}); diff --git a/ui/app/components/ui/loading-indicator/index.js b/ui/app/components/ui/loading-indicator/index.js index 69b932c0f..a11357e30 100644 --- a/ui/app/components/ui/loading-indicator/index.js +++ b/ui/app/components/ui/loading-indicator/index.js @@ -1 +1 @@ -export { default } from './loading-indicator' +export { default } from './loading-indicator'; diff --git a/ui/app/components/ui/loading-indicator/loading-indicator.js b/ui/app/components/ui/loading-indicator/loading-indicator.js index f5e81d76e..665439987 100644 --- a/ui/app/components/ui/loading-indicator/loading-indicator.js +++ b/ui/app/components/ui/loading-indicator/loading-indicator.js @@ -1,5 +1,5 @@ -import React from 'react' -import PropTypes from 'prop-types' +import React from 'react'; +import PropTypes from 'prop-types'; export default function LoadingIndicator({ alt, @@ -18,7 +18,7 @@ export default function LoadingIndicator({ ) : ( children - ) + ); } LoadingIndicator.propTypes = { @@ -26,4 +26,4 @@ LoadingIndicator.propTypes = { alt: PropTypes.string.isRequired, title: PropTypes.string.isRequired, children: PropTypes.node, -} +}; diff --git a/ui/app/components/ui/loading-screen/index.js b/ui/app/components/ui/loading-screen/index.js index e6ea29114..c5ea45289 100644 --- a/ui/app/components/ui/loading-screen/index.js +++ b/ui/app/components/ui/loading-screen/index.js @@ -1,3 +1,3 @@ -import LoadingScreen from './loading-screen.component' +import LoadingScreen from './loading-screen.component'; -export default LoadingScreen +export default LoadingScreen; diff --git a/ui/app/components/ui/loading-screen/loading-screen.component.js b/ui/app/components/ui/loading-screen/loading-screen.component.js index 279d54c12..2940f8c62 100644 --- a/ui/app/components/ui/loading-screen/loading-screen.component.js +++ b/ui/app/components/ui/loading-screen/loading-screen.component.js @@ -1,31 +1,31 @@ -import React, { Component, isValidElement } from 'react' -import PropTypes from 'prop-types' -import Spinner from '../spinner' +import React, { Component, isValidElement } from 'react'; +import PropTypes from 'prop-types'; +import Spinner from '../spinner'; class LoadingScreen extends Component { static defaultProps = { loadingMessage: null, showLoadingSpinner: true, - } + }; static propTypes = { loadingMessage: PropTypes.oneOfType([PropTypes.string, PropTypes.element]), showLoadingSpinner: PropTypes.bool, header: PropTypes.element, - } + }; renderMessage() { - const { loadingMessage } = this.props + const { loadingMessage } = this.props; if (!loadingMessage) { - return null + return null; } return isValidElement(loadingMessage) ? ( loadingMessage ) : ( {loadingMessage} - ) + ); } render() { @@ -39,8 +39,8 @@ class LoadingScreen extends Component { {this.renderMessage()} - ) + ); } } -export default LoadingScreen +export default LoadingScreen; diff --git a/ui/app/components/ui/lock-icon/index.js b/ui/app/components/ui/lock-icon/index.js index 6b4df0e58..8ab512f5b 100644 --- a/ui/app/components/ui/lock-icon/index.js +++ b/ui/app/components/ui/lock-icon/index.js @@ -1 +1 @@ -export { default } from './lock-icon.component' +export { default } from './lock-icon.component'; diff --git a/ui/app/components/ui/lock-icon/lock-icon.component.js b/ui/app/components/ui/lock-icon/lock-icon.component.js index bc8828e20..472d8d7ba 100644 --- a/ui/app/components/ui/lock-icon/lock-icon.component.js +++ b/ui/app/components/ui/lock-icon/lock-icon.component.js @@ -1,4 +1,4 @@ -import React from 'react' +import React from 'react'; export default function LockIcon(props) { return ( @@ -28,5 +28,5 @@ export default function LockIcon(props) { /> - ) + ); } diff --git a/ui/app/components/ui/mascot/index.js b/ui/app/components/ui/mascot/index.js index ad6ece331..9a263ffa1 100644 --- a/ui/app/components/ui/mascot/index.js +++ b/ui/app/components/ui/mascot/index.js @@ -1 +1 @@ -export { default } from './mascot.component' +export { default } from './mascot.component'; diff --git a/ui/app/components/ui/mascot/mascot.component.js b/ui/app/components/ui/mascot/mascot.component.js index dcffdc247..2002f15e6 100644 --- a/ui/app/components/ui/mascot/mascot.component.js +++ b/ui/app/components/ui/mascot/mascot.component.js @@ -1,19 +1,19 @@ -import PropTypes from 'prop-types' -import React, { createRef, Component } from 'react' -import MetaMaskLogo from '@metamask/logo' -import { debounce } from 'lodash' +import PropTypes from 'prop-types'; +import React, { createRef, Component } from 'react'; +import MetaMaskLogo from '@metamask/logo'; +import { debounce } from 'lodash'; const directionTargetGenerator = ({ top, left, height, width }) => { - const horizontalMiddle = left + width / 2 - const verticalMiddle = top + height / 2 + const horizontalMiddle = left + width / 2; + const verticalMiddle = top + height / 2; return { up: { x: horizontalMiddle, y: top - height }, down: { x: horizontalMiddle, y: top + height * 2 }, left: { x: left - width, y: verticalMiddle }, right: { x: left + width * 2, y: verticalMiddle }, middle: { x: horizontalMiddle, y: verticalMiddle }, - } -} + }; +}; export default class Mascot extends Component { static propTypes = { @@ -23,7 +23,7 @@ export default class Mascot extends Component { followMouse: PropTypes.bool, lookAtTarget: PropTypes.object, lookAtDirection: PropTypes.oneOf(['up', 'down', 'left', 'right', 'middle']), - } + }; static defaultProps = { width: '200', @@ -31,60 +31,60 @@ export default class Mascot extends Component { followMouse: true, lookAtTarget: {}, lookAtDirection: null, - } + }; constructor(props) { - super(props) + super(props); - const { width, height, followMouse } = props + const { width, height, followMouse } = props; this.logo = MetaMaskLogo({ followMouse, pxNotRatio: true, width, height, - }) + }); - this.mascotContainer = createRef() + this.mascotContainer = createRef(); this.refollowMouse = debounce( this.logo.setFollowMouse.bind(this.logo, true), 1000, - ) - this.unfollowMouse = this.logo.setFollowMouse.bind(this.logo, false) + ); + this.unfollowMouse = this.logo.setFollowMouse.bind(this.logo, false); } handleAnimationEvents() { // only setup listeners once if (this.animations) { - return + return; } - this.animations = this.props.animationEventEmitter - this.animations.on('point', this.lookAt.bind(this)) + this.animations = this.props.animationEventEmitter; + this.animations.on('point', this.lookAt.bind(this)); this.animations.on( 'setFollowMouse', this.logo.setFollowMouse.bind(this.logo), - ) + ); } lookAt(target) { - this.unfollowMouse() - this.logo.lookAt(target) - this.refollowMouse() + this.unfollowMouse(); + this.logo.lookAt(target); + this.refollowMouse(); } componentDidMount() { - this.mascotContainer.current.appendChild(this.logo.container) + this.mascotContainer.current.appendChild(this.logo.container); this.directionTargetMap = directionTargetGenerator( this.mascotContainer.current.getBoundingClientRect(), - ) + ); - const { lookAtTarget, lookAtDirection } = this.props + const { lookAtTarget, lookAtDirection } = this.props; if (lookAtTarget?.x && lookAtTarget?.y) { - this.logo.lookAtAndRender(lookAtTarget) + this.logo.lookAtAndRender(lookAtTarget); } else if (lookAtDirection) { - this.logo.lookAtAndRender(this.directionTargetMap[lookAtDirection]) + this.logo.lookAtAndRender(this.directionTargetMap[lookAtDirection]); } } @@ -93,35 +93,35 @@ export default class Mascot extends Component { lookAtTarget: prevTarget = {}, lookAtDirection: prevDirection = null, followMouse: prevFollowMouse, - } = prevProps - const { lookAtTarget = {}, followMouse, lookAtDirection } = this.props + } = prevProps; + const { lookAtTarget = {}, followMouse, lookAtDirection } = this.props; if (lookAtDirection && prevDirection !== lookAtDirection) { - this.logo.lookAtAndRender(this.directionTargetMap[lookAtDirection]) + this.logo.lookAtAndRender(this.directionTargetMap[lookAtDirection]); } else if ( lookAtTarget?.x !== prevTarget?.x || lookAtTarget?.y !== prevTarget?.y ) { - this.logo.lookAtAndRender(lookAtTarget) + this.logo.lookAtAndRender(lookAtTarget); } if (prevFollowMouse !== followMouse) { - this.unfollowMouse() - followMouse && this.refollowMouse() + this.unfollowMouse(); + followMouse && this.refollowMouse(); } } componentWillUnmount() { - this.animations = this.props.animationEventEmitter - this.animations.removeAllListeners() - this.logo.container.remove() - this.logo.stopAnimation() + this.animations = this.props.animationEventEmitter; + this.animations.removeAllListeners(); + this.logo.container.remove(); + this.logo.stopAnimation(); } render() { // this is a bit hacky // the event emitter is on `this.props` // and we dont get that until render - this.handleAnimationEvents() - return
    + this.handleAnimationEvents(); + return
    ; } } diff --git a/ui/app/components/ui/mascot/mascot.stories.js b/ui/app/components/ui/mascot/mascot.stories.js index ad698370b..aae108b05 100644 --- a/ui/app/components/ui/mascot/mascot.stories.js +++ b/ui/app/components/ui/mascot/mascot.stories.js @@ -1,10 +1,10 @@ -import EventEmitter from 'events' -import React, { useState } from 'react' -import Button from '../button' -import ButtonGroup from '../button-group' -import Mascot from './mascot.component' +import EventEmitter from 'events'; +import React, { useState } from 'react'; +import Button from '../button'; +import ButtonGroup from '../button-group'; +import Mascot from './mascot.component'; -const animationEventEmitter = new EventEmitter() +const animationEventEmitter = new EventEmitter(); const containerStyle = { height: '600px', @@ -14,27 +14,27 @@ const containerStyle = { flexFlow: 'column', justifyContent: 'center', alignItems: 'center', -} +}; const buttonStyle = { marginTop: '16px', -} +}; export default { title: 'Mascot', -} +}; export function Demo() { - const [lookAtDirection, setLookAtDirection] = useState(null) - const [followMouseMode, setFollowMouseMode] = useState(false) - const [clickToLookMode, setClickToLookMode] = useState(false) - const [clickedTarget, setClickedTarget] = useState(null) + const [lookAtDirection, setLookAtDirection] = useState(null); + const [followMouseMode, setFollowMouseMode] = useState(false); + const [clickToLookMode, setClickToLookMode] = useState(false); + const [clickedTarget, setClickedTarget] = useState(null); const createDirectionOnClick = (direction) => () => { - setFollowMouseMode(false) - setClickToLookMode(false) - setLookAtDirection(direction) - } + setFollowMouseMode(false); + setClickToLookMode(false); + setLookAtDirection(direction); + }; return (
    { const isButtonClick = event.target.classList.contains( 'button-group__button', - ) + ); if (clickToLookMode && !isButtonClick) { - setLookAtDirection(null) - setClickedTarget({ x: event.clientX, y: event.clientY }) + setLookAtDirection(null); + setClickedTarget({ x: event.clientX, y: event.clientY }); } }} > @@ -69,16 +69,16 @@ export function Demo() {
    - ) + ); } diff --git a/ui/app/components/ui/menu/index.js b/ui/app/components/ui/menu/index.js index 2d624ff68..4032224fb 100644 --- a/ui/app/components/ui/menu/index.js +++ b/ui/app/components/ui/menu/index.js @@ -1,2 +1,2 @@ -export { default as Menu } from './menu' -export { default as MenuItem } from './menu-item' +export { default as Menu } from './menu'; +export { default as MenuItem } from './menu-item'; diff --git a/ui/app/components/ui/menu/menu-item.js b/ui/app/components/ui/menu/menu-item.js index db84f7a1c..f62c76ba9 100644 --- a/ui/app/components/ui/menu/menu-item.js +++ b/ui/app/components/ui/menu/menu-item.js @@ -1,6 +1,6 @@ -import React from 'react' -import PropTypes from 'prop-types' -import classnames from 'classnames' +import React from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; const MenuItem = ({ children, @@ -21,7 +21,7 @@ const MenuItem = ({ {children} {subtitle} -) +); MenuItem.propTypes = { children: PropTypes.node.isRequired, @@ -30,7 +30,7 @@ MenuItem.propTypes = { iconClassName: PropTypes.string, onClick: PropTypes.func, subtitle: PropTypes.node, -} +}; MenuItem.defaultProps = { className: undefined, @@ -38,6 +38,6 @@ MenuItem.defaultProps = { iconClassName: undefined, onClick: undefined, subtitle: undefined, -} +}; -export default MenuItem +export default MenuItem; diff --git a/ui/app/components/ui/menu/menu.js b/ui/app/components/ui/menu/menu.js index c093cf80c..b76771ac9 100644 --- a/ui/app/components/ui/menu/menu.js +++ b/ui/app/components/ui/menu/menu.js @@ -1,8 +1,8 @@ -import PropTypes from 'prop-types' -import React, { useRef, useState } from 'react' -import { createPortal } from 'react-dom' -import { usePopper } from 'react-popper' -import classnames from 'classnames' +import PropTypes from 'prop-types'; +import React, { useRef, useState } from 'react'; +import { createPortal } from 'react-dom'; +import { usePopper } from 'react-popper'; +import classnames from 'classnames'; const Menu = ({ anchorElement, @@ -11,16 +11,16 @@ const Menu = ({ onHide, popperOptions, }) => { - const [popperElement, setPopperElement] = useState(null) + const [popperElement, setPopperElement] = useState(null); const popoverContainerElement = useRef( document.getElementById('popover-content'), - ) + ); const { attributes, styles } = usePopper( anchorElement, popperElement, popperOptions, - ) + ); return createPortal( <> @@ -35,8 +35,8 @@ const Menu = ({
    , popoverContainerElement.current, - ) -} + ); +}; Menu.propTypes = { anchorElement: PropTypes.instanceOf(window.Element), @@ -44,12 +44,12 @@ Menu.propTypes = { className: PropTypes.string, onHide: PropTypes.func.isRequired, popperOptions: PropTypes.object, -} +}; Menu.defaultProps = { anchorElement: undefined, className: undefined, popperOptions: undefined, -} +}; -export default Menu +export default Menu; diff --git a/ui/app/components/ui/menu/menu.stories.js b/ui/app/components/ui/menu/menu.stories.js index 59b73b701..e067e29d4 100644 --- a/ui/app/components/ui/menu/menu.stories.js +++ b/ui/app/components/ui/menu/menu.stories.js @@ -1,10 +1,10 @@ -import React, { useState } from 'react' -import { action } from '@storybook/addon-actions' -import { Menu, MenuItem } from '.' +import React, { useState } from 'react'; +import { action } from '@storybook/addon-actions'; +import { Menu, MenuItem } from '.'; export default { title: 'Menu', -} +}; export const Basic = () => { return ( @@ -17,11 +17,11 @@ export const Basic = () => { Menu Item 3 - ) -} + ); +}; export const Anchored = () => { - const [anchorElement, setAnchorElement] = useState(null) + const [anchorElement, setAnchorElement] = useState(null); return ( <> @@ -38,5 +38,5 @@ export const Anchored = () => { - ) -} + ); +}; diff --git a/ui/app/components/ui/metafox-logo/index.js b/ui/app/components/ui/metafox-logo/index.js index 0aeaed743..7c00c523f 100644 --- a/ui/app/components/ui/metafox-logo/index.js +++ b/ui/app/components/ui/metafox-logo/index.js @@ -1 +1 @@ -export { default } from './metafox-logo.component' +export { default } from './metafox-logo.component'; diff --git a/ui/app/components/ui/metafox-logo/metafox-logo.component.js b/ui/app/components/ui/metafox-logo/metafox-logo.component.js index faae1eb8e..363bf422c 100644 --- a/ui/app/components/ui/metafox-logo/metafox-logo.component.js +++ b/ui/app/components/ui/metafox-logo/metafox-logo.component.js @@ -1,20 +1,20 @@ -import React, { PureComponent } from 'react' -import PropTypes from 'prop-types' -import classnames from 'classnames' +import React, { PureComponent } from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; export default class MetaFoxLogo extends PureComponent { static propTypes = { onClick: PropTypes.func, unsetIconHeight: PropTypes.bool, - } + }; static defaultProps = { onClick: undefined, - } + }; render() { - const { onClick, unsetIconHeight } = this.props - const iconProps = unsetIconHeight ? {} : { height: 42, width: 42 } + const { onClick, unsetIconHeight } = this.props; + const iconProps = unsetIconHeight ? {} : { height: 42, width: 42 }; return (
    - ) + ); } } diff --git a/ui/app/components/ui/metafox-logo/tests/metafox-logo.component.test.js b/ui/app/components/ui/metafox-logo/tests/metafox-logo.component.test.js index 5ea89c620..3c0f725a4 100644 --- a/ui/app/components/ui/metafox-logo/tests/metafox-logo.component.test.js +++ b/ui/app/components/ui/metafox-logo/tests/metafox-logo.component.test.js @@ -1,32 +1,32 @@ -import assert from 'assert' -import React from 'react' -import { mount } from 'enzyme' -import MetaFoxLogo from '..' +import assert from 'assert'; +import React from 'react'; +import { mount } from 'enzyme'; +import MetaFoxLogo from '..'; describe('MetaFoxLogo', function () { it('sets icon height and width to 42 by default', function () { - const wrapper = mount() + const wrapper = mount(); assert.strictEqual( wrapper.find('img.app-header__metafox-logo--icon').prop('width'), 42, - ) + ); assert.strictEqual( wrapper.find('img.app-header__metafox-logo--icon').prop('height'), 42, - ) - }) + ); + }); it('does not set icon height and width when unsetIconHeight is true', function () { - const wrapper = mount() + const wrapper = mount(); assert.strictEqual( wrapper.find('img.app-header__metafox-logo--icon').prop('width'), undefined, - ) + ); assert.strictEqual( wrapper.find('img.app-header__metafox-logo--icon').prop('height'), undefined, - ) - }) -}) + ); + }); +}); diff --git a/ui/app/components/ui/page-container/index.js b/ui/app/components/ui/page-container/index.js index 1c423e870..18a34048d 100644 --- a/ui/app/components/ui/page-container/index.js +++ b/ui/app/components/ui/page-container/index.js @@ -1,5 +1,5 @@ -import PageContainerHeader from './page-container-header' -import PageContainerFooter from './page-container-footer' +import PageContainerHeader from './page-container-header'; +import PageContainerFooter from './page-container-footer'; -export { default } from './page-container.component' -export { PageContainerHeader, PageContainerFooter } +export { default } from './page-container.component'; +export { PageContainerHeader, PageContainerFooter }; diff --git a/ui/app/components/ui/page-container/page-container-content.component.js b/ui/app/components/ui/page-container/page-container-content.component.js index c833c76bf..bb1279e58 100644 --- a/ui/app/components/ui/page-container/page-container-content.component.js +++ b/ui/app/components/ui/page-container/page-container-content.component.js @@ -1,12 +1,12 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; export default class PageContainerContent extends Component { static propTypes = { children: PropTypes.node.isRequired, - } + }; render() { - return
    {this.props.children}
    + return
    {this.props.children}
    ; } } diff --git a/ui/app/components/ui/page-container/page-container-footer/index.js b/ui/app/components/ui/page-container/page-container-footer/index.js index 7825c4520..b08280499 100644 --- a/ui/app/components/ui/page-container/page-container-footer/index.js +++ b/ui/app/components/ui/page-container/page-container-footer/index.js @@ -1 +1 @@ -export { default } from './page-container-footer.component' +export { default } from './page-container-footer.component'; diff --git a/ui/app/components/ui/page-container/page-container-footer/page-container-footer.component.js b/ui/app/components/ui/page-container/page-container-footer/page-container-footer.component.js index 9278f4e25..cc5384817 100644 --- a/ui/app/components/ui/page-container/page-container-footer/page-container-footer.component.js +++ b/ui/app/components/ui/page-container/page-container-footer/page-container-footer.component.js @@ -1,7 +1,7 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import classnames from 'classnames' -import Button from '../../button' +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; +import Button from '../../button'; export default class PageContainerFooter extends Component { static propTypes = { @@ -17,11 +17,11 @@ export default class PageContainerFooter extends Component { buttonSizeLarge: PropTypes.bool, footerClassName: PropTypes.string, footerButtonClassName: PropTypes.string, - } + }; static contextTypes = { t: PropTypes.func, - } + }; render() { const { @@ -37,7 +37,7 @@ export default class PageContainerFooter extends Component { buttonSizeLarge = false, footerClassName, footerButtonClassName, - } = this.props + } = this.props; return (
    @@ -76,6 +76,6 @@ export default class PageContainerFooter extends Component {
    {children}
    )}
    - ) + ); } } diff --git a/ui/app/components/ui/page-container/page-container-footer/tests/page-container-footer.component.test.js b/ui/app/components/ui/page-container/page-container-footer/tests/page-container-footer.component.test.js index 4fd9b039c..56c798f65 100644 --- a/ui/app/components/ui/page-container/page-container-footer/tests/page-container-footer.component.test.js +++ b/ui/app/components/ui/page-container/page-container-footer/tests/page-container-footer.component.test.js @@ -1,14 +1,14 @@ -import assert from 'assert' -import React from 'react' -import { shallow } from 'enzyme' -import sinon from 'sinon' -import Button from '../../../button' -import PageFooter from '../page-container-footer.component' +import assert from 'assert'; +import React from 'react'; +import { shallow } from 'enzyme'; +import sinon from 'sinon'; +import Button from '../../../button'; +import PageFooter from '../page-container-footer.component'; describe('Page Footer', function () { - let wrapper - const onCancel = sinon.spy() - const onSubmit = sinon.spy() + let wrapper; + const onCancel = sinon.spy(); + const onSubmit = sinon.spy(); beforeEach(function () { wrapper = shallow( @@ -20,12 +20,12 @@ describe('Page Footer', function () { disabled={false} submitButtonType="Test Type" />, - ) - }) + ); + }); it('renders page container footer', function () { - assert.strictEqual(wrapper.find('.page-container__footer').length, 1) - }) + assert.strictEqual(wrapper.find('.page-container__footer').length, 1); + }); it('should render a secondary footer inside page-container__footer when given children', function () { wrapper = shallow( @@ -33,64 +33,64 @@ describe('Page Footer', function () {
    Works
    , { context: { t: sinon.spy((k) => `[${k}]`) } }, - ) + ); assert.strictEqual( wrapper.find('.page-container__footer-secondary').length, 1, - ) - }) + ); + }); it('renders two button components', function () { - assert.strictEqual(wrapper.find(Button).length, 2) - }) + assert.strictEqual(wrapper.find(Button).length, 2); + }); describe('Cancel Button', function () { it('has button type of default', function () { assert.strictEqual( wrapper.find('.page-container__footer-button').first().prop('type'), 'default', - ) - }) + ); + }); it('has children text of Cancel', function () { assert.strictEqual( wrapper.find('.page-container__footer-button').first().prop('children'), 'Cancel', - ) - }) + ); + }); it('should call cancel when click is simulated', function () { - wrapper.find('.page-container__footer-button').first().prop('onClick')() - assert.strictEqual(onCancel.callCount, 1) - }) - }) + wrapper.find('.page-container__footer-button').first().prop('onClick')(); + assert.strictEqual(onCancel.callCount, 1); + }); + }); describe('Submit Button', function () { it('assigns button type based on props', function () { assert.strictEqual( wrapper.find('.page-container__footer-button').last().prop('type'), 'Test Type', - ) - }) + ); + }); it('has disabled prop', function () { assert.strictEqual( wrapper.find('.page-container__footer-button').last().prop('disabled'), false, - ) - }) + ); + }); it('has children text when submitText prop exists', function () { assert.strictEqual( wrapper.find('.page-container__footer-button').last().prop('children'), 'Submit', - ) - }) + ); + }); it('should call submit when click is simulated', function () { - wrapper.find('.page-container__footer-button').last().prop('onClick')() - assert.strictEqual(onSubmit.callCount, 1) - }) - }) -}) + wrapper.find('.page-container__footer-button').last().prop('onClick')(); + assert.strictEqual(onSubmit.callCount, 1); + }); + }); +}); diff --git a/ui/app/components/ui/page-container/page-container-header/index.js b/ui/app/components/ui/page-container/page-container-header/index.js index b194af057..14f4c01c2 100644 --- a/ui/app/components/ui/page-container/page-container-header/index.js +++ b/ui/app/components/ui/page-container/page-container-header/index.js @@ -1 +1 @@ -export { default } from './page-container-header.component' +export { default } from './page-container-header.component'; diff --git a/ui/app/components/ui/page-container/page-container-header/page-container-header.component.js b/ui/app/components/ui/page-container/page-container-header/page-container-header.component.js index 0f715a027..3717b7450 100644 --- a/ui/app/components/ui/page-container/page-container-header/page-container-header.component.js +++ b/ui/app/components/ui/page-container/page-container-header/page-container-header.component.js @@ -1,7 +1,7 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import classnames from 'classnames' -import Button from '../../button' +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; +import Button from '../../button'; export default class PageContainerHeader extends Component { static propTypes = { @@ -15,12 +15,12 @@ export default class PageContainerHeader extends Component { tabs: PropTypes.node, headerCloseText: PropTypes.string, className: PropTypes.string, - } + }; renderTabs() { - const { tabs } = this.props + const { tabs } = this.props; - return tabs &&
      {tabs}
    + return tabs &&
      {tabs}
    ; } renderHeaderRow() { @@ -29,7 +29,7 @@ export default class PageContainerHeader extends Component { onBackButtonClick, backButtonStyles, backButtonString, - } = this.props + } = this.props; return ( showBackButton && ( @@ -43,7 +43,7 @@ export default class PageContainerHeader extends Component { ) - ) + ); } render() { @@ -54,7 +54,7 @@ export default class PageContainerHeader extends Component { tabs, headerCloseText, className, - } = this.props + } = this.props; return (
    - ) + ); } } diff --git a/ui/app/components/ui/page-container/page-container-header/tests/page-container-header.component.test.js b/ui/app/components/ui/page-container/page-container-header/tests/page-container-header.component.test.js index c686e3490..1c96ee0e5 100644 --- a/ui/app/components/ui/page-container/page-container-header/tests/page-container-header.component.test.js +++ b/ui/app/components/ui/page-container/page-container-header/tests/page-container-header.component.test.js @@ -1,16 +1,16 @@ -import assert from 'assert' -import React from 'react' -import { shallow } from 'enzyme' -import sinon from 'sinon' -import PageContainerHeader from '../page-container-header.component' +import assert from 'assert'; +import React from 'react'; +import { shallow } from 'enzyme'; +import sinon from 'sinon'; +import PageContainerHeader from '../page-container-header.component'; describe('Page Container Header', function () { - let wrapper, style, onBackButtonClick, onClose + let wrapper, style, onBackButtonClick, onClose; beforeEach(function () { - style = { test: 'style' } - onBackButtonClick = sinon.spy() - onClose = sinon.spy() + style = { test: 'style' }; + onBackButtonClick = sinon.spy(); + onClose = sinon.spy(); wrapper = shallow( , - ) - }) + ); + }); describe('Render Header Row', function () { it('renders back button', function () { - assert.strictEqual(wrapper.find('.page-container__back-button').length, 1) + assert.strictEqual( + wrapper.find('.page-container__back-button').length, + 1, + ); assert.strictEqual( wrapper.find('.page-container__back-button').text(), 'Back', - ) - }) + ); + }); it('ensures style prop', function () { assert.strictEqual( wrapper.find('.page-container__back-button').props().style, style, - ) - }) + ); + }); it('should call back button when click is simulated', function () { - wrapper.find('.page-container__back-button').prop('onClick')() - assert.strictEqual(onBackButtonClick.callCount, 1) - }) - }) + wrapper.find('.page-container__back-button').prop('onClick')(); + assert.strictEqual(onBackButtonClick.callCount, 1); + }); + }); describe('Render', function () { - let header, headerRow, pageTitle, pageSubtitle, pageClose, pageTab + let header, headerRow, pageTitle, pageSubtitle, pageClose, pageTab; beforeEach(function () { - header = wrapper.find('.page-container__header--no-padding-bottom') - headerRow = wrapper.find('.page-container__header-row') - pageTitle = wrapper.find('.page-container__title') - pageSubtitle = wrapper.find('.page-container__subtitle') - pageClose = wrapper.find('.page-container__header-close') - pageTab = wrapper.find('.page-container__tabs') - }) + header = wrapper.find('.page-container__header--no-padding-bottom'); + headerRow = wrapper.find('.page-container__header-row'); + pageTitle = wrapper.find('.page-container__title'); + pageSubtitle = wrapper.find('.page-container__subtitle'); + pageClose = wrapper.find('.page-container__header-close'); + pageTab = wrapper.find('.page-container__tabs'); + }); it('renders page container', function () { - assert.strictEqual(header.length, 1) - assert.strictEqual(headerRow.length, 1) - assert.strictEqual(pageTitle.length, 1) - assert.strictEqual(pageSubtitle.length, 1) - assert.strictEqual(pageClose.length, 1) - assert.strictEqual(pageTab.length, 1) - }) + assert.strictEqual(header.length, 1); + assert.strictEqual(headerRow.length, 1); + assert.strictEqual(pageTitle.length, 1); + assert.strictEqual(pageSubtitle.length, 1); + assert.strictEqual(pageClose.length, 1); + assert.strictEqual(pageTab.length, 1); + }); it('renders title', function () { - assert.strictEqual(pageTitle.text(), 'Test Title') - }) + assert.strictEqual(pageTitle.text(), 'Test Title'); + }); it('renders subtitle', function () { - assert.strictEqual(pageSubtitle.text(), 'Test Subtitle') - }) + assert.strictEqual(pageSubtitle.text(), 'Test Subtitle'); + }); it('renders tabs', function () { - assert.strictEqual(pageTab.text(), 'Test Tab') - }) + assert.strictEqual(pageTab.text(), 'Test Tab'); + }); it('should call close when click is simulated', function () { - pageClose.prop('onClick')() - assert.strictEqual(onClose.callCount, 1) - }) - }) -}) + pageClose.prop('onClick')(); + assert.strictEqual(onClose.callCount, 1); + }); + }); +}); diff --git a/ui/app/components/ui/page-container/page-container.component.js b/ui/app/components/ui/page-container/page-container.component.js index 79126e454..3cefb2273 100644 --- a/ui/app/components/ui/page-container/page-container.component.js +++ b/ui/app/components/ui/page-container/page-container.component.js @@ -1,8 +1,8 @@ -import React, { PureComponent } from 'react' -import PropTypes from 'prop-types' +import React, { PureComponent } from 'react'; +import PropTypes from 'prop-types'; -import PageContainerHeader from './page-container-header' -import PageContainerFooter from './page-container-footer' +import PageContainerHeader from './page-container-header'; +import PageContainerFooter from './page-container-footer'; export default class PageContainer extends PureComponent { static propTypes = { @@ -27,24 +27,24 @@ export default class PageContainer extends PureComponent { onCancel: PropTypes.func, onSubmit: PropTypes.func, submitText: PropTypes.string, - } + }; state = { activeTabIndex: this.props.defaultActiveTabIndex || 0, - } + }; handleTabClick(activeTabIndex) { - this.setState({ activeTabIndex }) + this.setState({ activeTabIndex }); } renderTabs() { - const { tabsComponent } = this.props + const { tabsComponent } = this.props; if (!tabsComponent) { - return null + return null; } - const numberOfTabs = React.Children.count(tabsComponent.props.children) + const numberOfTabs = React.Children.count(tabsComponent.props.children); return React.Children.map( tabsComponent.props.children, @@ -59,31 +59,31 @@ export default class PageContainer extends PureComponent { key: tabIndex, className: 'page-container__tab', }) - ) + ); }, - ) + ); } renderActiveTabContent() { - const { tabsComponent } = this.props - let { children } = tabsComponent.props - children = children.filter(Boolean) - const { activeTabIndex } = this.state + const { tabsComponent } = this.props; + let { children } = tabsComponent.props; + children = children.filter(Boolean); + const { activeTabIndex } = this.state; return children[activeTabIndex] ? children[activeTabIndex].props.children - : children.props.children + : children.props.children; } renderContent() { - const { contentComponent, tabsComponent } = this.props + const { contentComponent, tabsComponent } = this.props; if (contentComponent) { - return contentComponent + return contentComponent; } else if (tabsComponent) { - return this.renderActiveTabContent() + return this.renderActiveTabContent(); } - return null + return null; } render() { @@ -102,7 +102,7 @@ export default class PageContainer extends PureComponent { disabled, headerCloseText, hideCancel, - } = this.props + } = this.props; return (
    @@ -129,6 +129,6 @@ export default class PageContainer extends PureComponent { />
    - ) + ); } } diff --git a/ui/app/components/ui/popover/index.js b/ui/app/components/ui/popover/index.js index 416fee51a..6c51559dd 100644 --- a/ui/app/components/ui/popover/index.js +++ b/ui/app/components/ui/popover/index.js @@ -1,3 +1,3 @@ -import Item from './popover.component' +import Item from './popover.component'; -export default Item +export default Item; diff --git a/ui/app/components/ui/popover/popover.component.js b/ui/app/components/ui/popover/popover.component.js index 43d95449d..0f93c7183 100644 --- a/ui/app/components/ui/popover/popover.component.js +++ b/ui/app/components/ui/popover/popover.component.js @@ -1,8 +1,8 @@ -import React, { PureComponent } from 'react' -import ReactDOM from 'react-dom' -import PropTypes from 'prop-types' -import classnames from 'classnames' -import { useI18nContext } from '../../../hooks/useI18nContext' +import React, { PureComponent } from 'react'; +import ReactDOM from 'react-dom'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; +import { useI18nContext } from '../../../hooks/useI18nContext'; const Popover = ({ title, @@ -17,7 +17,7 @@ const Popover = ({ showArrow, CustomBackground, }) => { - const t = useI18nContext() + const t = useI18nContext(); return (
    {CustomBackground ? ( @@ -61,8 +61,8 @@ const Popover = ({ ) : null}
    - ) -} + ); +}; Popover.propTypes = { title: PropTypes.string.isRequired, @@ -76,35 +76,35 @@ Popover.propTypes = { contentClassName: PropTypes.string, className: PropTypes.string, showArrow: PropTypes.bool, -} +}; export default class PopoverPortal extends PureComponent { - static propTypes = Popover.propTypes + static propTypes = Popover.propTypes; - rootNode = document.getElementById('popover-content') + rootNode = document.getElementById('popover-content'); - instanceNode = document.createElement('div') + instanceNode = document.createElement('div'); componentDidMount() { if (!this.rootNode) { - return + return; } - this.rootNode.appendChild(this.instanceNode) + this.rootNode.appendChild(this.instanceNode); } componentWillUnmount() { if (!this.rootNode) { - return + return; } - this.rootNode.removeChild(this.instanceNode) + this.rootNode.removeChild(this.instanceNode); } render() { - const children = + const children = ; return this.rootNode ? ReactDOM.createPortal(children, this.instanceNode) - : children + : children; } } diff --git a/ui/app/components/ui/popover/popover.stories.js b/ui/app/components/ui/popover/popover.stories.js index be713f0dc..e7029d17f 100644 --- a/ui/app/components/ui/popover/popover.stories.js +++ b/ui/app/components/ui/popover/popover.stories.js @@ -1,22 +1,22 @@ -import React from 'react' -import { text } from '@storybook/addon-knobs' -import { action } from '@storybook/addon-actions' -import Popover from './popover.component' +import React from 'react'; +import { text } from '@storybook/addon-knobs'; +import { action } from '@storybook/addon-actions'; +import Popover from './popover.component'; const containerStyle = { width: 800, height: 600, background: 'pink', position: 'relative', -} +}; const mainWrapperStyle = { padding: '0 24px 24px', -} +}; export default { title: 'Popover', -} +}; export const approve = () => (
    @@ -61,4 +61,4 @@ export const approve = () => (
    -) +); diff --git a/ui/app/components/ui/pulse-loader/index.js b/ui/app/components/ui/pulse-loader/index.js index 1fad53e56..b626bdda4 100644 --- a/ui/app/components/ui/pulse-loader/index.js +++ b/ui/app/components/ui/pulse-loader/index.js @@ -1 +1 @@ -export { default } from './pulse-loader' +export { default } from './pulse-loader'; diff --git a/ui/app/components/ui/pulse-loader/pulse-loader.js b/ui/app/components/ui/pulse-loader/pulse-loader.js index afc8af89d..d4d542d71 100644 --- a/ui/app/components/ui/pulse-loader/pulse-loader.js +++ b/ui/app/components/ui/pulse-loader/pulse-loader.js @@ -1,4 +1,4 @@ -import React from 'react' +import React from 'react'; export default function PulseLoader() { return ( @@ -7,5 +7,5 @@ export default function PulseLoader() {
    - ) + ); } diff --git a/ui/app/components/ui/pulse-loader/pulse-loader.stories.js b/ui/app/components/ui/pulse-loader/pulse-loader.stories.js index 6adb4f441..a3878d27d 100644 --- a/ui/app/components/ui/pulse-loader/pulse-loader.stories.js +++ b/ui/app/components/ui/pulse-loader/pulse-loader.stories.js @@ -1,8 +1,8 @@ -import React from 'react' -import PulseLoader from '.' +import React from 'react'; +import PulseLoader from '.'; export default { title: 'PulseLoader', -} +}; -export const common = () => +export const common = () => ; diff --git a/ui/app/components/ui/qr-code/index.js b/ui/app/components/ui/qr-code/index.js index f638ae4fb..632ac037f 100644 --- a/ui/app/components/ui/qr-code/index.js +++ b/ui/app/components/ui/qr-code/index.js @@ -1 +1 @@ -export { default } from './qr-code' +export { default } from './qr-code'; diff --git a/ui/app/components/ui/qr-code/qr-code.js b/ui/app/components/ui/qr-code/qr-code.js index b8990186e..6c00f33fc 100644 --- a/ui/app/components/ui/qr-code/qr-code.js +++ b/ui/app/components/ui/qr-code/qr-code.js @@ -1,31 +1,31 @@ -import PropTypes from 'prop-types' -import React from 'react' -import qrCode from 'qrcode-generator' -import { connect } from 'react-redux' -import { isHexPrefixed } from 'ethereumjs-util' -import ReadOnlyInput from '../readonly-input/readonly-input' -import { checksumAddress } from '../../../helpers/utils/util' +import PropTypes from 'prop-types'; +import React from 'react'; +import qrCode from 'qrcode-generator'; +import { connect } from 'react-redux'; +import { isHexPrefixed } from 'ethereumjs-util'; +import ReadOnlyInput from '../readonly-input/readonly-input'; +import { checksumAddress } from '../../../helpers/utils/util'; -export default connect(mapStateToProps)(QrCodeView) +export default connect(mapStateToProps)(QrCodeView); function mapStateToProps(state) { - const { buyView, warning } = state.appState + const { buyView, warning } = state.appState; return { // Qr code is not fetched from state. 'message' and 'data' props are passed instead. buyView, warning, - } + }; } function QrCodeView(props) { - const { Qr, warning } = props - const { message, data } = Qr + const { Qr, warning } = props; + const { message, data } = Qr; const address = `${isHexPrefixed(data) ? 'ethereum:' : ''}${checksumAddress( data, - )}` - const qrImage = qrCode(4, 'M') - qrImage.addData(address) - qrImage.make() + )}`; + const qrImage = qrCode(4, 'M'); + qrImage.addData(address); + qrImage.make(); return (
    @@ -53,7 +53,7 @@ function QrCodeView(props) { value={checksumAddress(data)} />
    - ) + ); } QrCodeView.propTypes = { @@ -65,4 +65,4 @@ QrCodeView.propTypes = { ]), data: PropTypes.string.isRequired, }).isRequired, -} +}; diff --git a/ui/app/components/ui/readonly-input/index.js b/ui/app/components/ui/readonly-input/index.js index 151a02ee8..f944d6a89 100644 --- a/ui/app/components/ui/readonly-input/index.js +++ b/ui/app/components/ui/readonly-input/index.js @@ -1 +1 @@ -export { default } from './readonly-input' +export { default } from './readonly-input'; diff --git a/ui/app/components/ui/readonly-input/readonly-input.js b/ui/app/components/ui/readonly-input/readonly-input.js index a64aaf054..30fbce0e2 100644 --- a/ui/app/components/ui/readonly-input/readonly-input.js +++ b/ui/app/components/ui/readonly-input/readonly-input.js @@ -1,6 +1,6 @@ -import PropTypes from 'prop-types' -import React from 'react' -import classnames from 'classnames' +import PropTypes from 'prop-types'; +import React from 'react'; +import classnames from 'classnames'; export default function ReadOnlyInput(props) { const { @@ -10,9 +10,9 @@ export default function ReadOnlyInput(props) { textarea, onClick, autoFocus = false, - } = props + } = props; - const InputType = textarea ? 'textarea' : 'input' + const InputType = textarea ? 'textarea' : 'input'; return (
    @@ -25,7 +25,7 @@ export default function ReadOnlyInput(props) { autoFocus={autoFocus} />
    - ) + ); } ReadOnlyInput.propTypes = { @@ -35,4 +35,4 @@ ReadOnlyInput.propTypes = { textarea: PropTypes.bool, onClick: PropTypes.func, autoFocus: PropTypes.bool, -} +}; diff --git a/ui/app/components/ui/search-icon/index.js b/ui/app/components/ui/search-icon/index.js index f6078b7be..7583cbf6b 100644 --- a/ui/app/components/ui/search-icon/index.js +++ b/ui/app/components/ui/search-icon/index.js @@ -1 +1 @@ -export { default } from './search-icon.component' +export { default } from './search-icon.component'; diff --git a/ui/app/components/ui/search-icon/search-icon.component.js b/ui/app/components/ui/search-icon/search-icon.component.js index a0bf8aa54..957c499bf 100644 --- a/ui/app/components/ui/search-icon/search-icon.component.js +++ b/ui/app/components/ui/search-icon/search-icon.component.js @@ -1,4 +1,4 @@ -import React from 'react' +import React from 'react'; export default function SearchIcon() { return ( @@ -13,5 +13,5 @@ export default function SearchIcon() { - ) + ); } diff --git a/ui/app/components/ui/sender-to-recipient/index.js b/ui/app/components/ui/sender-to-recipient/index.js index f515c4ac4..b19de3f80 100644 --- a/ui/app/components/ui/sender-to-recipient/index.js +++ b/ui/app/components/ui/sender-to-recipient/index.js @@ -1 +1 @@ -export { default } from './sender-to-recipient.component' +export { default } from './sender-to-recipient.component'; diff --git a/ui/app/components/ui/sender-to-recipient/sender-to-recipient.component.js b/ui/app/components/ui/sender-to-recipient/sender-to-recipient.component.js index 5c4ae7991..00e099e24 100644 --- a/ui/app/components/ui/sender-to-recipient/sender-to-recipient.component.js +++ b/ui/app/components/ui/sender-to-recipient/sender-to-recipient.component.js @@ -1,23 +1,23 @@ -import React, { useState } from 'react' -import PropTypes from 'prop-types' -import classnames from 'classnames' -import copyToClipboard from 'copy-to-clipboard' -import Tooltip from '../tooltip' -import Identicon from '../identicon' -import { checksumAddress, shortenAddress } from '../../../helpers/utils/util' -import AccountMismatchWarning from '../account-mismatch-warning/account-mismatch-warning.component' -import { useI18nContext } from '../../../hooks/useI18nContext' +import React, { useState } from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; +import copyToClipboard from 'copy-to-clipboard'; +import Tooltip from '../tooltip'; +import Identicon from '../identicon'; +import { checksumAddress, shortenAddress } from '../../../helpers/utils/util'; +import AccountMismatchWarning from '../account-mismatch-warning/account-mismatch-warning.component'; +import { useI18nContext } from '../../../hooks/useI18nContext'; import { DEFAULT_VARIANT, CARDS_VARIANT, FLAT_VARIANT, -} from './sender-to-recipient.constants' +} from './sender-to-recipient.constants'; const variantHash = { [DEFAULT_VARIANT]: 'sender-to-recipient--default', [CARDS_VARIANT]: 'sender-to-recipient--cards', [FLAT_VARIANT]: 'sender-to-recipient--flat', -} +}; function SenderAddress({ addressOnly, @@ -27,9 +27,9 @@ function SenderAddress({ senderAddress, warnUserOnAccountMismatch, }) { - const t = useI18nContext() - const [addressCopied, setAddressCopied] = useState(false) - let tooltipHtml =

    {t('copiedExclamation')}

    + const t = useI18nContext(); + const [addressCopied, setAddressCopied] = useState(false); + let tooltipHtml =

    {t('copiedExclamation')}

    ; if (!addressCopied) { tooltipHtml = addressOnly ? (

    {t('copyAddress')}

    @@ -39,7 +39,7 @@ function SenderAddress({
    {t('copyAddress')}

    - ) + ); } return (
    { - setAddressCopied(true) - copyToClipboard(checksummedSenderAddress) + setAddressCopied(true); + copyToClipboard(checksummedSenderAddress); if (onSenderClick) { - onSenderClick() + onSenderClick(); } }} > @@ -80,7 +80,7 @@ function SenderAddress({ )}
    - ) + ); } SenderAddress.propTypes = { @@ -90,7 +90,7 @@ SenderAddress.propTypes = { senderAddress: PropTypes.string, onSenderClick: PropTypes.func, warnUserOnAccountMismatch: PropTypes.bool, -} +}; function RecipientWithAddress({ checksummedRecipientAddress, @@ -101,13 +101,13 @@ function RecipientWithAddress({ recipientEns, recipientName, }) { - const t = useI18nContext() - const [addressCopied, setAddressCopied] = useState(false) + const t = useI18nContext(); + const [addressCopied, setAddressCopied] = useState(false); - let tooltipHtml =

    {t('copiedExclamation')}

    + let tooltipHtml =

    {t('copiedExclamation')}

    ; if (!addressCopied) { if (addressOnly && !recipientNickname && !recipientEns) { - tooltipHtml =

    {t('copyAddress')}

    + tooltipHtml =

    {t('copyAddress')}

    ; } else { tooltipHtml = (

    @@ -115,17 +115,17 @@ function RecipientWithAddress({
    {t('copyAddress')}

    - ) + ); } } return (
    { - setAddressCopied(true) - copyToClipboard(checksummedRecipientAddress) + setAddressCopied(true); + copyToClipboard(checksummedRecipientAddress); if (onRecipientClick) { - onRecipientClick() + onRecipientClick(); } }} > @@ -157,7 +157,7 @@ function RecipientWithAddress({
    - ) + ); } RecipientWithAddress.propTypes = { @@ -168,7 +168,7 @@ RecipientWithAddress.propTypes = { addressOnly: PropTypes.bool, assetImage: PropTypes.string, onRecipientClick: PropTypes.func, -} +}; function Arrow({ variant }) { return variant === DEFAULT_VARIANT ? ( @@ -181,12 +181,12 @@ function Arrow({ variant }) {
    - ) + ); } Arrow.propTypes = { variant: PropTypes.oneOf([DEFAULT_VARIANT, CARDS_VARIANT, FLAT_VARIANT]), -} +}; export default function SenderToRecipient({ senderAddress, @@ -202,9 +202,9 @@ export default function SenderToRecipient({ variant, warnUserOnAccountMismatch, }) { - const t = useI18nContext() - const checksummedSenderAddress = checksumAddress(senderAddress) - const checksummedRecipientAddress = checksumAddress(recipientAddress) + const t = useI18nContext(); + const checksummedSenderAddress = checksumAddress(senderAddress); + const checksummedRecipientAddress = checksumAddress(recipientAddress); return (
    @@ -234,13 +234,13 @@ export default function SenderToRecipient({
    )} - ) + ); } SenderToRecipient.defaultProps = { variant: DEFAULT_VARIANT, warnUserOnAccountMismatch: true, -} +}; SenderToRecipient.propTypes = { senderName: PropTypes.string, @@ -255,4 +255,4 @@ SenderToRecipient.propTypes = { onRecipientClick: PropTypes.func, onSenderClick: PropTypes.func, warnUserOnAccountMismatch: PropTypes.bool, -} +}; diff --git a/ui/app/components/ui/sender-to-recipient/sender-to-recipient.constants.js b/ui/app/components/ui/sender-to-recipient/sender-to-recipient.constants.js index f53a5115d..5b7b53f46 100644 --- a/ui/app/components/ui/sender-to-recipient/sender-to-recipient.constants.js +++ b/ui/app/components/ui/sender-to-recipient/sender-to-recipient.constants.js @@ -1,4 +1,4 @@ // Component design variants -export const DEFAULT_VARIANT = 'DEFAULT_VARIANT' -export const CARDS_VARIANT = 'CARDS_VARIANT' -export const FLAT_VARIANT = 'FLAT_VARIANT' +export const DEFAULT_VARIANT = 'DEFAULT_VARIANT'; +export const CARDS_VARIANT = 'CARDS_VARIANT'; +export const FLAT_VARIANT = 'FLAT_VARIANT'; diff --git a/ui/app/components/ui/site-icon/index.js b/ui/app/components/ui/site-icon/index.js index a68d9779d..1097b3c64 100644 --- a/ui/app/components/ui/site-icon/index.js +++ b/ui/app/components/ui/site-icon/index.js @@ -1 +1 @@ -export { default } from './site-icon' +export { default } from './site-icon'; diff --git a/ui/app/components/ui/site-icon/site-icon.js b/ui/app/components/ui/site-icon/site-icon.js index e0a690c6e..4101b7b30 100644 --- a/ui/app/components/ui/site-icon/site-icon.js +++ b/ui/app/components/ui/site-icon/site-icon.js @@ -1,24 +1,24 @@ -import React from 'react' -import PropTypes from 'prop-types' -import IconBorder from '../icon-border' -import IconWithFallback from '../icon-with-fallback' +import React from 'react'; +import PropTypes from 'prop-types'; +import IconBorder from '../icon-border'; +import IconWithFallback from '../icon-with-fallback'; export default function SiteIcon({ icon, name, size }) { - const iconSize = Math.floor(size * 0.75) + const iconSize = Math.floor(size * 0.75); return ( - ) + ); } SiteIcon.propTypes = { icon: PropTypes.string, name: PropTypes.string, size: PropTypes.number.isRequired, -} +}; SiteIcon.defaultProps = { icon: undefined, name: undefined, -} +}; diff --git a/ui/app/components/ui/snackbar/index.js b/ui/app/components/ui/snackbar/index.js index 3d3e0394d..3fe5015d6 100644 --- a/ui/app/components/ui/snackbar/index.js +++ b/ui/app/components/ui/snackbar/index.js @@ -1 +1 @@ -export { default } from './snackbar.component' +export { default } from './snackbar.component'; diff --git a/ui/app/components/ui/snackbar/snackbar.component.js b/ui/app/components/ui/snackbar/snackbar.component.js index c9da15dba..87fa7c003 100644 --- a/ui/app/components/ui/snackbar/snackbar.component.js +++ b/ui/app/components/ui/snackbar/snackbar.component.js @@ -1,14 +1,14 @@ -import React from 'react' -import PropTypes from 'prop-types' -import classnames from 'classnames' +import React from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; const Snackbar = ({ className = '', content }) => { - return
    {content}
    -} + return
    {content}
    ; +}; Snackbar.propTypes = { className: PropTypes.string, content: PropTypes.string.isRequired, -} +}; -export default Snackbar +export default Snackbar; diff --git a/ui/app/components/ui/spinner/index.js b/ui/app/components/ui/spinner/index.js index d302d535b..ce78e9c96 100644 --- a/ui/app/components/ui/spinner/index.js +++ b/ui/app/components/ui/spinner/index.js @@ -1,3 +1,3 @@ -import Spinner from './spinner.component' +import Spinner from './spinner.component'; -export default Spinner +export default Spinner; diff --git a/ui/app/components/ui/spinner/spinner.component.js b/ui/app/components/ui/spinner/spinner.component.js index 4e002bfb2..634398823 100644 --- a/ui/app/components/ui/spinner/spinner.component.js +++ b/ui/app/components/ui/spinner/spinner.component.js @@ -1,5 +1,5 @@ -import React from 'react' -import PropTypes from 'prop-types' +import React from 'react'; +import PropTypes from 'prop-types'; const Spinner = ({ className = '', color = '#000000' }) => { return ( @@ -148,12 +148,12 @@ const Spinner = ({ className = '', color = '#000000' }) => { - ) -} + ); +}; Spinner.propTypes = { className: PropTypes.string, color: PropTypes.string, -} +}; -export default Spinner +export default Spinner; diff --git a/ui/app/components/ui/tabs/index.js b/ui/app/components/ui/tabs/index.js index 46f0b18a5..43366ec6f 100644 --- a/ui/app/components/ui/tabs/index.js +++ b/ui/app/components/ui/tabs/index.js @@ -1,4 +1,4 @@ -import Tabs from './tabs.component' -import Tab from './tab' +import Tabs from './tabs.component'; +import Tab from './tab'; -export { Tabs, Tab } +export { Tabs, Tab }; diff --git a/ui/app/components/ui/tabs/tab/index.js b/ui/app/components/ui/tabs/tab/index.js index c6ef9bb68..06ffef1a5 100644 --- a/ui/app/components/ui/tabs/tab/index.js +++ b/ui/app/components/ui/tabs/tab/index.js @@ -1,3 +1,3 @@ -import Tab from './tab.component' +import Tab from './tab.component'; -export default Tab +export default Tab; diff --git a/ui/app/components/ui/tabs/tab/tab.component.js b/ui/app/components/ui/tabs/tab/tab.component.js index e88deaca4..63325c025 100644 --- a/ui/app/components/ui/tabs/tab/tab.component.js +++ b/ui/app/components/ui/tabs/tab/tab.component.js @@ -1,6 +1,6 @@ -import React from 'react' -import PropTypes from 'prop-types' -import classnames from 'classnames' +import React from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; const Tab = (props) => { const { @@ -11,7 +11,7 @@ const Tab = (props) => { name, onClick, tabIndex, - } = props + } = props; return (
  • { })} data-testid={dataTestId} onClick={(event) => { - event.preventDefault() - onClick(tabIndex) + event.preventDefault(); + onClick(tabIndex); }} >
  • - ) -} + ); +}; Tab.propTypes = { activeClassName: PropTypes.string, @@ -38,12 +38,12 @@ Tab.propTypes = { name: PropTypes.string.isRequired, onClick: PropTypes.func, tabIndex: PropTypes.number, // required, but added using React.cloneElement -} +}; Tab.defaultProps = { activeClassName: undefined, className: undefined, onClick: undefined, -} +}; -export default Tab +export default Tab; diff --git a/ui/app/components/ui/tabs/tabs.component.js b/ui/app/components/ui/tabs/tabs.component.js index 2f1f7583e..6c091e5a2 100644 --- a/ui/app/components/ui/tabs/tabs.component.js +++ b/ui/app/components/ui/tabs/tabs.component.js @@ -1,31 +1,31 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import classnames from 'classnames' +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; export default class Tabs extends Component { static defaultProps = { defaultActiveTabName: null, onTabClick: null, tabsClassName: undefined, - } + }; static propTypes = { defaultActiveTabName: PropTypes.string, onTabClick: PropTypes.func, children: PropTypes.node.isRequired, tabsClassName: PropTypes.string, - } + }; state = { activeTabIndex: Math.max( this._findChildByName(this.props.defaultActiveTabName), 0, ), - } + }; handleTabClick(tabIndex, tabName) { - const { onTabClick } = this.props - const { activeTabIndex } = this.state + const { onTabClick } = this.props; + const { activeTabIndex } = this.state; if (tabIndex !== activeTabIndex) { this.setState( @@ -34,18 +34,18 @@ export default class Tabs extends Component { }, () => { if (onTabClick) { - onTabClick(tabName) + onTabClick(tabName); } }, - ) + ); } } renderTabs() { - const numberOfTabs = React.Children.count(this.props.children) + const numberOfTabs = React.Children.count(this.props.children); return React.Children.map(this.props.children, (child, index) => { - const tabName = child?.props.name + const tabName = child?.props.name; return ( child && React.cloneElement(child, { @@ -53,28 +53,28 @@ export default class Tabs extends Component { tabIndex: index, isActive: numberOfTabs > 1 && index === this.state.activeTabIndex, }) - ) - }) + ); + }); } renderActiveTabContent() { - const { children } = this.props - const { activeTabIndex } = this.state + const { children } = this.props; + const { activeTabIndex } = this.state; if ( (Array.isArray(children) && !children[activeTabIndex]) || (!Array.isArray(children) && activeTabIndex !== 0) ) { - throw new Error(`Tab at index '${activeTabIndex}' does not exist`) + throw new Error(`Tab at index '${activeTabIndex}' does not exist`); } return children[activeTabIndex] ? children[activeTabIndex].props.children - : children.props.children + : children.props.children; } render() { - const { tabsClassName } = this.props + const { tabsClassName } = this.props; return (
      @@ -82,7 +82,7 @@ export default class Tabs extends Component {
    {this.renderActiveTabContent()}
    - ) + ); } /** @@ -94,6 +94,6 @@ export default class Tabs extends Component { _findChildByName(name) { return React.Children.toArray(this.props.children).findIndex( (c) => c?.props.name === name, - ) + ); } } diff --git a/ui/app/components/ui/tabs/tabs.stories.js b/ui/app/components/ui/tabs/tabs.stories.js index 1cdc9044c..ee656845d 100644 --- a/ui/app/components/ui/tabs/tabs.stories.js +++ b/ui/app/components/ui/tabs/tabs.stories.js @@ -1,27 +1,27 @@ -import React from 'react' -import { text } from '@storybook/addon-knobs' -import Tab from './tab/tab.component' -import Tabs from './tabs.component' +import React from 'react'; +import { text } from '@storybook/addon-knobs'; +import Tab from './tab/tab.component'; +import Tabs from './tabs.component'; export default { title: 'Tabs', -} +}; function renderTab(id) { return ( {text(`Tab ${id} Contents`, `Contents of Tab ${id}`)} - ) + ); } export const twoTabs = () => { - return {['A', 'B'].map(renderTab)} -} + return {['A', 'B'].map(renderTab)}; +}; export const manyTabs = () => { - return {['A', 'B', 'C', 'D', 'E'].map(renderTab)} -} + return {['A', 'B', 'C', 'D', 'E'].map(renderTab)}; +}; export const singleTab = () => { return ( @@ -30,5 +30,5 @@ export const singleTab = () => { {text('Contents', 'Contents of tab')} - ) -} + ); +}; diff --git a/ui/app/components/ui/text-field/index.js b/ui/app/components/ui/text-field/index.js index adc0669b8..262be3c0e 100644 --- a/ui/app/components/ui/text-field/index.js +++ b/ui/app/components/ui/text-field/index.js @@ -1,3 +1,3 @@ -import TextField from './text-field.component' +import TextField from './text-field.component'; -export default TextField +export default TextField; diff --git a/ui/app/components/ui/text-field/text-field.component.js b/ui/app/components/ui/text-field/text-field.component.js index 88d51d6e6..49e6ca785 100644 --- a/ui/app/components/ui/text-field/text-field.component.js +++ b/ui/app/components/ui/text-field/text-field.component.js @@ -1,14 +1,14 @@ -import React from 'react' -import PropTypes from 'prop-types' -import { withStyles } from '@material-ui/core/styles' -import MaterialTextField from '@material-ui/core/TextField' +import React from 'react'; +import PropTypes from 'prop-types'; +import { withStyles } from '@material-ui/core/styles'; +import MaterialTextField from '@material-ui/core/TextField'; const inputLabelBase = { transform: 'none', transition: 'none', position: 'initial', color: '#5b5b5b', -} +}; const styles = { materialLabel: { @@ -82,7 +82,7 @@ const styles = { inputMultiline: { lineHeight: 'initial !important', }, -} +}; const getMaterialThemeInputProps = ({ dir, @@ -105,7 +105,7 @@ const getMaterialThemeInputProps = ({ dir, }, }, -}) +}); const getMaterialWhitePaddedThemeInputProps = ({ dir, @@ -129,7 +129,7 @@ const getMaterialWhitePaddedThemeInputProps = ({ dir, }, }, -}) +}); const getBorderedThemeInputProps = ({ dir, @@ -167,13 +167,13 @@ const getBorderedThemeInputProps = ({ dir, }, }, -}) +}); const themeToInputProps = { material: getMaterialThemeInputProps, bordered: getBorderedThemeInputProps, 'material-white-padded': getMaterialWhitePaddedThemeInputProps, -} +}; const TextField = ({ error, @@ -189,7 +189,7 @@ const TextField = ({ startAdornment, largeLabel, dir, - }) + }); return ( - ) -} + ); +}; TextField.defaultProps = { error: null, dir: 'auto', theme: 'bordered', -} +}; TextField.propTypes = { error: PropTypes.string, @@ -214,6 +214,6 @@ TextField.propTypes = { theme: PropTypes.oneOf(['bordered', 'material', 'material-white-padded']), startAdornment: PropTypes.element, largeLabel: PropTypes.bool, -} +}; -export default withStyles(styles)(TextField) +export default withStyles(styles)(TextField); diff --git a/ui/app/components/ui/text-field/text-field.stories.js b/ui/app/components/ui/text-field/text-field.stories.js index ed905163d..2b5cb3018 100644 --- a/ui/app/components/ui/text-field/text-field.stories.js +++ b/ui/app/components/ui/text-field/text-field.stories.js @@ -1,30 +1,30 @@ -import React from 'react' -import TextField from '.' +import React from 'react'; +import TextField from '.'; export default { title: 'TextField', -} +}; -export const text = () => +export const text = () => ; -export const password = () => +export const password = () => ; export const error = () => ( -) +); export const mascaraText = () => ( -) +); export const materialText = () => ( -) +); export const materialPassword = () => ( -) +); export const materialError = () => ( -) +); diff --git a/ui/app/components/ui/toggle-button/index.js b/ui/app/components/ui/toggle-button/index.js index b0c4141e7..445c963ce 100644 --- a/ui/app/components/ui/toggle-button/index.js +++ b/ui/app/components/ui/toggle-button/index.js @@ -1,3 +1,3 @@ -import ToggleButton from './toggle-button.component' +import ToggleButton from './toggle-button.component'; -export default ToggleButton +export default ToggleButton; diff --git a/ui/app/components/ui/toggle-button/toggle-button.component.js b/ui/app/components/ui/toggle-button/toggle-button.component.js index 3809b7877..86e6074f1 100644 --- a/ui/app/components/ui/toggle-button/toggle-button.component.js +++ b/ui/app/components/ui/toggle-button/toggle-button.component.js @@ -1,6 +1,6 @@ -import React from 'react' -import PropTypes from 'prop-types' -import ReactToggleButton from 'react-toggle-button' +import React from 'react'; +import PropTypes from 'prop-types'; +import ReactToggleButton from 'react-toggle-button'; const trackStyle = { width: '40px', @@ -11,12 +11,12 @@ const trackStyle = { display: 'flex', alignItems: 'center', justifyContent: 'center', -} +}; const offTrackStyle = { ...trackStyle, border: '2px solid #8E8E8E', -} +}; const thumbStyle = { width: '18px', @@ -26,7 +26,7 @@ const thumbStyle = { alignSelf: 'center', borderRadius: '50%', position: 'relative', -} +}; const colors = { activeThumb: { @@ -43,12 +43,12 @@ const colors = { base: '#DADADA', hover: '#DADADA', }, -} +}; const ToggleButton = (props) => { - const { value, onToggle, offLabel, onLabel } = props + const { value, onToggle, offLabel, onLabel } = props; - const modifier = value ? 'on' : 'off' + const modifier = value ? 'on' : 'off'; return (
    @@ -67,14 +67,14 @@ const ToggleButton = (props) => { {onLabel}
    - ) -} + ); +}; ToggleButton.propTypes = { value: PropTypes.bool, onToggle: PropTypes.func, offLabel: PropTypes.string, onLabel: PropTypes.string, -} +}; -export default ToggleButton +export default ToggleButton; diff --git a/ui/app/components/ui/token-balance/index.js b/ui/app/components/ui/token-balance/index.js index 97bc9bbc2..e18b4653f 100644 --- a/ui/app/components/ui/token-balance/index.js +++ b/ui/app/components/ui/token-balance/index.js @@ -1 +1 @@ -export { default } from './token-balance' +export { default } from './token-balance'; diff --git a/ui/app/components/ui/token-balance/token-balance.js b/ui/app/components/ui/token-balance/token-balance.js index dcb7aaa99..2a972a7f3 100644 --- a/ui/app/components/ui/token-balance/token-balance.js +++ b/ui/app/components/ui/token-balance/token-balance.js @@ -1,19 +1,19 @@ -import React from 'react' -import PropTypes from 'prop-types' -import CurrencyDisplay from '../currency-display' -import { useTokenTracker } from '../../../hooks/useTokenTracker' +import React from 'react'; +import PropTypes from 'prop-types'; +import CurrencyDisplay from '../currency-display'; +import { useTokenTracker } from '../../../hooks/useTokenTracker'; export default function TokenBalance({ className, token }) { - const { tokensWithBalances } = useTokenTracker([token]) + const { tokensWithBalances } = useTokenTracker([token]); - const { string, symbol } = tokensWithBalances[0] || {} + const { string, symbol } = tokensWithBalances[0] || {}; return ( - ) + ); } TokenBalance.propTypes = { @@ -23,8 +23,8 @@ TokenBalance.propTypes = { decimals: PropTypes.number, symbol: PropTypes.string, }).isRequired, -} +}; TokenBalance.defaultProps = { className: undefined, -} +}; diff --git a/ui/app/components/ui/token-currency-display/index.js b/ui/app/components/ui/token-currency-display/index.js index 6065cae1f..c4c28291a 100644 --- a/ui/app/components/ui/token-currency-display/index.js +++ b/ui/app/components/ui/token-currency-display/index.js @@ -1 +1 @@ -export { default } from './token-currency-display.component' +export { default } from './token-currency-display.component'; diff --git a/ui/app/components/ui/token-currency-display/token-currency-display.component.js b/ui/app/components/ui/token-currency-display/token-currency-display.component.js index 69a314e47..4d9cb01d0 100644 --- a/ui/app/components/ui/token-currency-display/token-currency-display.component.js +++ b/ui/app/components/ui/token-currency-display/token-currency-display.component.js @@ -1,7 +1,7 @@ -import React from 'react' -import PropTypes from 'prop-types' -import CurrencyDisplay from '../currency-display' -import { useTokenDisplayValue } from '../../../hooks/useTokenDisplayValue' +import React from 'react'; +import PropTypes from 'prop-types'; +import CurrencyDisplay from '../currency-display'; +import { useTokenDisplayValue } from '../../../hooks/useTokenDisplayValue'; export default function TokenCurrencyDisplay({ className, @@ -9,7 +9,7 @@ export default function TokenCurrencyDisplay({ token, prefix, }) { - const displayValue = useTokenDisplayValue(transactionData, token) + const displayValue = useTokenDisplayValue(transactionData, token); return ( - ) + ); } TokenCurrencyDisplay.propTypes = { @@ -26,4 +26,4 @@ TokenCurrencyDisplay.propTypes = { transactionData: PropTypes.string, token: PropTypes.object, prefix: PropTypes.string, -} +}; diff --git a/ui/app/components/ui/token-input/index.js b/ui/app/components/ui/token-input/index.js index 22c06111e..fb5bafb90 100644 --- a/ui/app/components/ui/token-input/index.js +++ b/ui/app/components/ui/token-input/index.js @@ -1 +1 @@ -export { default } from './token-input.container' +export { default } from './token-input.container'; diff --git a/ui/app/components/ui/token-input/tests/token-input.component.test.js b/ui/app/components/ui/token-input/tests/token-input.component.test.js index e6542b3e2..479d63b0e 100644 --- a/ui/app/components/ui/token-input/tests/token-input.component.test.js +++ b/ui/app/components/ui/token-input/tests/token-input.component.test.js @@ -1,16 +1,16 @@ -import assert from 'assert' -import React from 'react' -import PropTypes from 'prop-types' -import { shallow, mount } from 'enzyme' -import sinon from 'sinon' -import { Provider } from 'react-redux' -import configureMockStore from 'redux-mock-store' -import TokenInput from '../token-input.component' -import UnitInput from '../../unit-input' -import CurrencyDisplay from '../../currency-display' +import assert from 'assert'; +import React from 'react'; +import PropTypes from 'prop-types'; +import { shallow, mount } from 'enzyme'; +import sinon from 'sinon'; +import { Provider } from 'react-redux'; +import configureMockStore from 'redux-mock-store'; +import TokenInput from '../token-input.component'; +import UnitInput from '../../unit-input'; +import CurrencyDisplay from '../../currency-display'; describe('TokenInput Component', function () { - const t = (key) => `translate ${key}` + const t = (key) => `translate ${key}`; describe('rendering', function () { it('should render properly', function () { @@ -19,8 +19,8 @@ describe('TokenInput Component', function () { currentCurrency: 'usd', conversionRate: 231.06, }, - } - const store = configureMockStore()(mockStore) + }; + const store = configureMockStore()(mockStore); const wrapper = mount( @@ -38,20 +38,20 @@ describe('TokenInput Component', function () { t: PropTypes.func, }, }, - ) + ); - assert.ok(wrapper) - assert.strictEqual(wrapper.find('.unit-input__suffix').length, 1) - assert.strictEqual(wrapper.find('.unit-input__suffix').text(), 'ABC') + assert.ok(wrapper); + assert.strictEqual(wrapper.find('.unit-input__suffix').length, 1); + assert.strictEqual(wrapper.find('.unit-input__suffix').text(), 'ABC'); assert.strictEqual( wrapper.find('.currency-input__conversion-component').length, 1, - ) + ); assert.strictEqual( wrapper.find('.currency-input__conversion-component').text(), 'translate noConversionRateAvailable', - ) - }) + ); + }); it('should render properly with tokenExchangeRates', function () { const mockStore = { @@ -59,8 +59,8 @@ describe('TokenInput Component', function () { currentCurrency: 'usd', conversionRate: 231.06, }, - } - const store = configureMockStore()(mockStore) + }; + const store = configureMockStore()(mockStore); const wrapper = mount( @@ -79,13 +79,13 @@ describe('TokenInput Component', function () { t: PropTypes.func, }, }, - ) + ); - assert.ok(wrapper) - assert.strictEqual(wrapper.find('.unit-input__suffix').length, 1) - assert.strictEqual(wrapper.find('.unit-input__suffix').text(), 'ABC') - assert.strictEqual(wrapper.find(CurrencyDisplay).length, 1) - }) + assert.ok(wrapper); + assert.strictEqual(wrapper.find('.unit-input__suffix').length, 1); + assert.strictEqual(wrapper.find('.unit-input__suffix').text(), 'ABC'); + assert.strictEqual(wrapper.find(CurrencyDisplay).length, 1); + }); it('should render properly with a token value for ETH', function () { const mockStore = { @@ -93,8 +93,8 @@ describe('TokenInput Component', function () { currentCurrency: 'usd', conversionRate: 231.06, }, - } - const store = configureMockStore()(mockStore) + }; + const store = configureMockStore()(mockStore); const wrapper = mount( @@ -108,20 +108,20 @@ describe('TokenInput Component', function () { tokenExchangeRates={{ '0x1': 2 }} /> , - ) + ); - assert.ok(wrapper) - const tokenInputInstance = wrapper.find(TokenInput).at(0).instance() - assert.strictEqual(tokenInputInstance.state.decimalValue, '1') - assert.strictEqual(tokenInputInstance.state.hexValue, '2710') - assert.strictEqual(wrapper.find('.unit-input__suffix').length, 1) - assert.strictEqual(wrapper.find('.unit-input__suffix').text(), 'ABC') - assert.strictEqual(wrapper.find('.unit-input__input').props().value, '1') + assert.ok(wrapper); + const tokenInputInstance = wrapper.find(TokenInput).at(0).instance(); + assert.strictEqual(tokenInputInstance.state.decimalValue, '1'); + assert.strictEqual(tokenInputInstance.state.hexValue, '2710'); + assert.strictEqual(wrapper.find('.unit-input__suffix').length, 1); + assert.strictEqual(wrapper.find('.unit-input__suffix').text(), 'ABC'); + assert.strictEqual(wrapper.find('.unit-input__input').props().value, '1'); assert.strictEqual( wrapper.find('.currency-display-component').text(), '2ETH', - ) - }) + ); + }); it('should render properly with a token value for fiat', function () { const mockStore = { @@ -129,8 +129,8 @@ describe('TokenInput Component', function () { currentCurrency: 'usd', conversionRate: 231.06, }, - } - const store = configureMockStore()(mockStore) + }; + const store = configureMockStore()(mockStore); const wrapper = mount( @@ -145,20 +145,20 @@ describe('TokenInput Component', function () { showFiat /> , - ) + ); - assert.ok(wrapper) - const tokenInputInstance = wrapper.find(TokenInput).at(0).instance() - assert.strictEqual(tokenInputInstance.state.decimalValue, '1') - assert.strictEqual(tokenInputInstance.state.hexValue, '2710') - assert.strictEqual(wrapper.find('.unit-input__suffix').length, 1) - assert.strictEqual(wrapper.find('.unit-input__suffix').text(), 'ABC') - assert.strictEqual(wrapper.find('.unit-input__input').props().value, '1') + assert.ok(wrapper); + const tokenInputInstance = wrapper.find(TokenInput).at(0).instance(); + assert.strictEqual(tokenInputInstance.state.decimalValue, '1'); + assert.strictEqual(tokenInputInstance.state.hexValue, '2710'); + assert.strictEqual(wrapper.find('.unit-input__suffix').length, 1); + assert.strictEqual(wrapper.find('.unit-input__suffix').text(), 'ABC'); + assert.strictEqual(wrapper.find('.unit-input__input').props().value, '1'); assert.strictEqual( wrapper.find('.currency-display-component').text(), '$462.12USD', - ) - }) + ); + }); it('should render properly with a token value for fiat, but hideConversion is true', function () { const mockStore = { @@ -166,8 +166,8 @@ describe('TokenInput Component', function () { currentCurrency: 'usd', conversionRate: 231.06, }, - } - const store = configureMockStore()(mockStore) + }; + const store = configureMockStore()(mockStore); const wrapper = mount( @@ -189,30 +189,30 @@ describe('TokenInput Component', function () { t: PropTypes.func, }, }, - ) + ); - assert.ok(wrapper) - const tokenInputInstance = wrapper.find(TokenInput).at(0).instance() - assert.strictEqual(tokenInputInstance.state.decimalValue, '1') - assert.strictEqual(tokenInputInstance.state.hexValue, '2710') - assert.strictEqual(wrapper.find('.unit-input__suffix').length, 1) - assert.strictEqual(wrapper.find('.unit-input__suffix').text(), 'ABC') - assert.strictEqual(wrapper.find('.unit-input__input').props().value, '1') + assert.ok(wrapper); + const tokenInputInstance = wrapper.find(TokenInput).at(0).instance(); + assert.strictEqual(tokenInputInstance.state.decimalValue, '1'); + assert.strictEqual(tokenInputInstance.state.hexValue, '2710'); + assert.strictEqual(wrapper.find('.unit-input__suffix').length, 1); + assert.strictEqual(wrapper.find('.unit-input__suffix').text(), 'ABC'); + assert.strictEqual(wrapper.find('.unit-input__input').props().value, '1'); assert.strictEqual( wrapper.find('.currency-input__conversion-component').text(), 'translate noConversionRateAvailable', - ) - }) - }) + ); + }); + }); describe('handling actions', function () { - const handleChangeSpy = sinon.spy() - const handleBlurSpy = sinon.spy() + const handleChangeSpy = sinon.spy(); + const handleBlurSpy = sinon.spy(); afterEach(function () { - handleChangeSpy.resetHistory() - handleBlurSpy.resetHistory() - }) + handleChangeSpy.resetHistory(); + handleBlurSpy.resetHistory(); + }); it('should call onChange on input changes with the hex value for ETH', function () { const mockStore = { @@ -220,8 +220,8 @@ describe('TokenInput Component', function () { currentCurrency: 'usd', conversionRate: 231.06, }, - } - const store = configureMockStore()(mockStore) + }; + const store = configureMockStore()(mockStore); const wrapper = mount( , - ) + ); - assert.ok(wrapper) - assert.strictEqual(handleChangeSpy.callCount, 0) - assert.strictEqual(handleBlurSpy.callCount, 0) + assert.ok(wrapper); + assert.strictEqual(handleChangeSpy.callCount, 0); + assert.strictEqual(handleBlurSpy.callCount, 0); - const tokenInputInstance = wrapper.find(TokenInput).at(0).instance() - assert.strictEqual(tokenInputInstance.state.decimalValue, 0) - assert.strictEqual(tokenInputInstance.state.hexValue, undefined) + const tokenInputInstance = wrapper.find(TokenInput).at(0).instance(); + assert.strictEqual(tokenInputInstance.state.decimalValue, 0); + assert.strictEqual(tokenInputInstance.state.hexValue, undefined); assert.strictEqual( wrapper.find('.currency-display-component').text(), '0ETH', - ) - const input = wrapper.find('input') - assert.strictEqual(input.props().value, 0) + ); + const input = wrapper.find('input'); + assert.strictEqual(input.props().value, 0); - input.simulate('change', { target: { value: 1 } }) - assert.strictEqual(handleChangeSpy.callCount, 1) - assert.ok(handleChangeSpy.calledWith('2710')) + input.simulate('change', { target: { value: 1 } }); + assert.strictEqual(handleChangeSpy.callCount, 1); + assert.ok(handleChangeSpy.calledWith('2710')); assert.strictEqual( wrapper.find('.currency-display-component').text(), '2ETH', - ) - assert.strictEqual(tokenInputInstance.state.decimalValue, 1) - assert.strictEqual(tokenInputInstance.state.hexValue, '2710') - }) + ); + assert.strictEqual(tokenInputInstance.state.decimalValue, 1); + assert.strictEqual(tokenInputInstance.state.hexValue, '2710'); + }); it('should call onChange on input changes with the hex value for fiat', function () { const mockStore = { @@ -267,8 +267,8 @@ describe('TokenInput Component', function () { currentCurrency: 'usd', conversionRate: 231.06, }, - } - const store = configureMockStore()(mockStore) + }; + const store = configureMockStore()(mockStore); const wrapper = mount( , - ) + ); - assert.ok(wrapper) - assert.strictEqual(handleChangeSpy.callCount, 0) - assert.strictEqual(handleBlurSpy.callCount, 0) + assert.ok(wrapper); + assert.strictEqual(handleChangeSpy.callCount, 0); + assert.strictEqual(handleBlurSpy.callCount, 0); - const tokenInputInstance = wrapper.find(TokenInput).at(0).instance() - assert.strictEqual(tokenInputInstance.state.decimalValue, 0) - assert.strictEqual(tokenInputInstance.state.hexValue, undefined) + const tokenInputInstance = wrapper.find(TokenInput).at(0).instance(); + assert.strictEqual(tokenInputInstance.state.decimalValue, 0); + assert.strictEqual(tokenInputInstance.state.hexValue, undefined); assert.strictEqual( wrapper.find('.currency-display-component').text(), '$0.00USD', - ) - const input = wrapper.find('input') - assert.strictEqual(input.props().value, 0) + ); + const input = wrapper.find('input'); + assert.strictEqual(input.props().value, 0); - input.simulate('change', { target: { value: 1 } }) - assert.strictEqual(handleChangeSpy.callCount, 1) - assert.ok(handleChangeSpy.calledWith('2710')) + input.simulate('change', { target: { value: 1 } }); + assert.strictEqual(handleChangeSpy.callCount, 1); + assert.ok(handleChangeSpy.calledWith('2710')); assert.strictEqual( wrapper.find('.currency-display-component').text(), '$462.12USD', - ) - assert.strictEqual(tokenInputInstance.state.decimalValue, 1) - assert.strictEqual(tokenInputInstance.state.hexValue, '2710') - }) + ); + assert.strictEqual(tokenInputInstance.state.decimalValue, 1); + assert.strictEqual(tokenInputInstance.state.hexValue, '2710'); + }); it('should change the state and pass in a new decimalValue when props.value changes', function () { const mockStore = { @@ -315,8 +315,8 @@ describe('TokenInput Component', function () { currentCurrency: 'usd', conversionRate: 231.06, }, - } - const store = configureMockStore()(mockStore) + }; + const store = configureMockStore()(mockStore); const wrapper = shallow( , - ) + ); - assert.ok(wrapper) - const tokenInputInstance = wrapper.find(TokenInput).dive() - assert.strictEqual(tokenInputInstance.state('decimalValue'), 0) - assert.strictEqual(tokenInputInstance.state('hexValue'), undefined) - assert.strictEqual(tokenInputInstance.find(UnitInput).props().value, 0) + assert.ok(wrapper); + const tokenInputInstance = wrapper.find(TokenInput).dive(); + assert.strictEqual(tokenInputInstance.state('decimalValue'), 0); + assert.strictEqual(tokenInputInstance.state('hexValue'), undefined); + assert.strictEqual(tokenInputInstance.find(UnitInput).props().value, 0); - tokenInputInstance.setProps({ value: '2710' }) - tokenInputInstance.update() - assert.strictEqual(tokenInputInstance.state('decimalValue'), '1') - assert.strictEqual(tokenInputInstance.state('hexValue'), '2710') - assert.strictEqual(tokenInputInstance.find(UnitInput).props().value, '1') - }) - }) -}) + tokenInputInstance.setProps({ value: '2710' }); + tokenInputInstance.update(); + assert.strictEqual(tokenInputInstance.state('decimalValue'), '1'); + assert.strictEqual(tokenInputInstance.state('hexValue'), '2710'); + assert.strictEqual(tokenInputInstance.find(UnitInput).props().value, '1'); + }); + }); +}); diff --git a/ui/app/components/ui/token-input/token-input.component.js b/ui/app/components/ui/token-input/token-input.component.js index 4d85ed4a5..fe7001d4f 100644 --- a/ui/app/components/ui/token-input/token-input.component.js +++ b/ui/app/components/ui/token-input/token-input.component.js @@ -1,14 +1,14 @@ -import React, { PureComponent } from 'react' -import PropTypes from 'prop-types' -import UnitInput from '../unit-input' -import CurrencyDisplay from '../currency-display' -import { getWeiHexFromDecimalValue } from '../../../helpers/utils/conversions.util' +import React, { PureComponent } from 'react'; +import PropTypes from 'prop-types'; +import UnitInput from '../unit-input'; +import CurrencyDisplay from '../currency-display'; +import { getWeiHexFromDecimalValue } from '../../../helpers/utils/conversions.util'; import { conversionUtil, multiplyCurrencies, -} from '../../../helpers/utils/conversion-util' -import { ETH } from '../../../helpers/constants/common' -import { addHexPrefix } from '../../../../../app/scripts/lib/util' +} from '../../../helpers/utils/conversion-util'; +import { ETH } from '../../../helpers/constants/common'; +import { addHexPrefix } from '../../../../../app/scripts/lib/util'; /** * Component that allows user to enter token values as a number, and props receive a converted @@ -18,7 +18,7 @@ import { addHexPrefix } from '../../../../../app/scripts/lib/util' export default class TokenInput extends PureComponent { static contextTypes = { t: PropTypes.func, - } + }; static propTypes = { currentCurrency: PropTypes.string, @@ -32,62 +32,62 @@ export default class TokenInput extends PureComponent { symbol: PropTypes.string, }).isRequired, tokenExchangeRates: PropTypes.object, - } + }; constructor(props) { - super(props) + super(props); - const { value: hexValue } = props - const decimalValue = hexValue ? this.getValue(props) : 0 + const { value: hexValue } = props; + const decimalValue = hexValue ? this.getValue(props) : 0; this.state = { decimalValue, hexValue, - } + }; } componentDidUpdate(prevProps) { - const { value: prevPropsHexValue } = prevProps - const { value: propsHexValue } = this.props - const { hexValue: stateHexValue } = this.state + const { value: prevPropsHexValue } = prevProps; + const { value: propsHexValue } = this.props; + const { hexValue: stateHexValue } = this.state; if ( prevPropsHexValue !== propsHexValue && propsHexValue !== stateHexValue ) { - const decimalValue = this.getValue(this.props) - this.setState({ hexValue: propsHexValue, decimalValue }) + const decimalValue = this.getValue(this.props); + this.setState({ hexValue: propsHexValue, decimalValue }); } } getValue(props) { - const { value: hexValue, token: { decimals, symbol } = {} } = props + const { value: hexValue, token: { decimals, symbol } = {} } = props; - const multiplier = Math.pow(10, Number(decimals || 0)) + const multiplier = Math.pow(10, Number(decimals || 0)); const decimalValueString = conversionUtil(addHexPrefix(hexValue), { fromNumericBase: 'hex', toNumericBase: 'dec', toCurrency: symbol, conversionRate: multiplier, invertConversionRate: true, - }) + }); - return Number(decimalValueString) ? decimalValueString : '' + return Number(decimalValueString) ? decimalValueString : ''; } handleChange = (decimalValue) => { - const { token: { decimals } = {}, onChange } = this.props + const { token: { decimals } = {}, onChange } = this.props; - const multiplier = Math.pow(10, Number(decimals || 0)) + const multiplier = Math.pow(10, Number(decimals || 0)); const hexValue = multiplyCurrencies(decimalValue || 0, multiplier, { multiplicandBase: 10, multiplierBase: 10, toNumericBase: 'hex', - }) + }); - this.setState({ hexValue, decimalValue }) - onChange(hexValue) - } + this.setState({ hexValue, decimalValue }); + onChange(hexValue); + }; renderConversionComponent() { const { @@ -96,36 +96,36 @@ export default class TokenInput extends PureComponent { currentCurrency, hideConversion, token, - } = this.props - const { decimalValue } = this.state + } = this.props; + const { decimalValue } = this.state; - const tokenExchangeRate = tokenExchangeRates?.[token.address] || 0 - let currency, numberOfDecimals + const tokenExchangeRate = tokenExchangeRates?.[token.address] || 0; + let currency, numberOfDecimals; if (hideConversion) { return (
    {this.context.t('noConversionRateAvailable')}
    - ) + ); } if (showFiat) { // Display Fiat - currency = currentCurrency - numberOfDecimals = 2 + currency = currentCurrency; + numberOfDecimals = 2; } else { // Display ETH - currency = ETH - numberOfDecimals = 6 + currency = ETH; + numberOfDecimals = 6; } - const decimalEthValue = decimalValue * tokenExchangeRate || 0 + const decimalEthValue = decimalValue * tokenExchangeRate || 0; const hexWeiValue = getWeiHexFromDecimalValue({ value: decimalEthValue, fromCurrency: ETH, fromDenomination: ETH, - }) + }); return tokenExchangeRate ? ( {this.context.t('noConversionRateAvailable')} - ) + ); } render() { - const { token, ...restProps } = this.props - const { decimalValue } = this.state + const { token, ...restProps } = this.props; + const { decimalValue } = this.state; return ( {this.renderConversionComponent()} - ) + ); } } diff --git a/ui/app/components/ui/token-input/token-input.container.js b/ui/app/components/ui/token-input/token-input.container.js index eac410000..a34c2d247 100644 --- a/ui/app/components/ui/token-input/token-input.container.js +++ b/ui/app/components/ui/token-input/token-input.container.js @@ -1,27 +1,27 @@ -import { connect } from 'react-redux' -import PropTypes from 'prop-types' +import { connect } from 'react-redux'; +import PropTypes from 'prop-types'; import { getIsMainnet, getTokenExchangeRates, getPreferences, -} from '../../../selectors' -import TokenInput from './token-input.component' +} from '../../../selectors'; +import TokenInput from './token-input.component'; const mapStateToProps = (state) => { const { metamask: { currentCurrency }, - } = state - const { showFiatInTestnets } = getPreferences(state) - const isMainnet = getIsMainnet(state) + } = state; + const { showFiatInTestnets } = getPreferences(state); + const isMainnet = getIsMainnet(state); return { currentCurrency, tokenExchangeRates: getTokenExchangeRates(state), hideConversion: !isMainnet && !showFiatInTestnets, - } -} + }; +}; -const TokenInputContainer = connect(mapStateToProps)(TokenInput) +const TokenInputContainer = connect(mapStateToProps)(TokenInput); TokenInputContainer.propTypes = { token: PropTypes.shape({ @@ -29,6 +29,6 @@ TokenInputContainer.propTypes = { decimals: PropTypes.number, symbol: PropTypes.string, }).isRequired, -} +}; -export default TokenInputContainer +export default TokenInputContainer; diff --git a/ui/app/components/ui/tooltip/index.js b/ui/app/components/ui/tooltip/index.js index 00a8d178a..bb106e207 100644 --- a/ui/app/components/ui/tooltip/index.js +++ b/ui/app/components/ui/tooltip/index.js @@ -1 +1 @@ -export { default } from './tooltip' +export { default } from './tooltip'; diff --git a/ui/app/components/ui/tooltip/tooltip.js b/ui/app/components/ui/tooltip/tooltip.js index b9319f166..4c01eaade 100644 --- a/ui/app/components/ui/tooltip/tooltip.js +++ b/ui/app/components/ui/tooltip/tooltip.js @@ -1,6 +1,6 @@ -import PropTypes from 'prop-types' -import React, { PureComponent } from 'react' -import { Tooltip as ReactTippy } from 'react-tippy' +import PropTypes from 'prop-types'; +import React, { PureComponent } from 'react'; +import { Tooltip as ReactTippy } from 'react-tippy'; export default class Tooltip extends PureComponent { static defaultProps = { @@ -17,7 +17,7 @@ export default class Tooltip extends PureComponent { trigger: 'mouseenter', wrapperClassName: undefined, theme: '', - } + }; static propTypes = { arrow: PropTypes.bool, @@ -35,7 +35,7 @@ export default class Tooltip extends PureComponent { wrapperClassName: PropTypes.string, style: PropTypes.object, theme: PropTypes.string, - } + }; render() { const { @@ -54,10 +54,10 @@ export default class Tooltip extends PureComponent { wrapperClassName, style, theme, - } = this.props + } = this.props; if (!title && !html) { - return
    {children}
    + return
    {children}
    ; } return ( @@ -81,6 +81,6 @@ export default class Tooltip extends PureComponent { {children} - ) + ); } } diff --git a/ui/app/components/ui/truncated-definition-list/index.js b/ui/app/components/ui/truncated-definition-list/index.js index 427109d63..cabe7da11 100644 --- a/ui/app/components/ui/truncated-definition-list/index.js +++ b/ui/app/components/ui/truncated-definition-list/index.js @@ -1 +1 @@ -export { default } from './truncated-definition-list' +export { default } from './truncated-definition-list'; diff --git a/ui/app/components/ui/truncated-definition-list/truncated-definition-list.js b/ui/app/components/ui/truncated-definition-list/truncated-definition-list.js index 356f1aed1..2382b045b 100644 --- a/ui/app/components/ui/truncated-definition-list/truncated-definition-list.js +++ b/ui/app/components/ui/truncated-definition-list/truncated-definition-list.js @@ -1,12 +1,12 @@ -import { pick } from 'lodash' -import React, { useState } from 'react' -import PropTypes from 'prop-types' -import { COLORS, SIZES } from '../../../helpers/constants/design-system' -import Box from '../box' -import Button from '../button' -import DefinitionList from '../definition-list/definition-list' -import Popover from '../popover' -import { useI18nContext } from '../../../hooks/useI18nContext' +import { pick } from 'lodash'; +import React, { useState } from 'react'; +import PropTypes from 'prop-types'; +import { COLORS, SIZES } from '../../../helpers/constants/design-system'; +import Box from '../box'; +import Button from '../button'; +import DefinitionList from '../definition-list/definition-list'; +import Popover from '../popover'; +import { useI18nContext } from '../../../hooks/useI18nContext'; export default function TruncatedDefinitionList({ dictionary, @@ -14,8 +14,8 @@ export default function TruncatedDefinitionList({ prefaceKeys, title, }) { - const [isPopoverOpen, setIsPopoverOpen] = useState(false) - const t = useI18nContext() + const [isPopoverOpen, setIsPopoverOpen] = useState(false); + const t = useI18nContext(); return ( <> @@ -67,7 +67,7 @@ export default function TruncatedDefinitionList({
    )} - ) + ); } TruncatedDefinitionList.propTypes = { @@ -75,4 +75,4 @@ TruncatedDefinitionList.propTypes = { tooltips: DefinitionList.propTypes.dictionary, title: PropTypes.string, prefaceKeys: PropTypes.arrayOf(PropTypes.string), -} +}; diff --git a/ui/app/components/ui/truncated-definition-list/truncated-definition-list.stories.js b/ui/app/components/ui/truncated-definition-list/truncated-definition-list.stories.js index 68101ef0d..01c9977e1 100644 --- a/ui/app/components/ui/truncated-definition-list/truncated-definition-list.stories.js +++ b/ui/app/components/ui/truncated-definition-list/truncated-definition-list.stories.js @@ -1,11 +1,11 @@ -import React from 'react' -import { object, text } from '@storybook/addon-knobs' +import React from 'react'; +import { object, text } from '@storybook/addon-knobs'; -import TruncatedDefinitionList from './truncated-definition-list' +import TruncatedDefinitionList from './truncated-definition-list'; export default { title: 'Truncated Definition List', -} +}; const basic = { term: @@ -15,19 +15,19 @@ const basic = { dl: 'HTML tag denoting a definition list', dt: 'HTML tag denoting a definition list term', dd: 'HTML tag denoting a definition list definition', -} +}; const advanced = { 'Network Name': 'Ethereum Mainnet', 'Chain ID': '1', Ticker: 'ETH', -} +}; const tooltips = { 'Network Name': 'The name that is associated with this network', 'Chain ID': 'The numeric value representing the ID of this network', Ticker: 'The currency symbol of the primary currency for this network', -} +}; export const truncatedDefinitionList = () => ( ( title={text('title', 'Basic definitions')} prefaceKeys={object('prefaceKeys', ['term', 'definition'])} /> -) +); export const withTooltips = () => ( ( tooltips={object('tooltips', tooltips)} prefaceKeys={object('prefaceKeys', ['Chain ID'])} /> -) +); diff --git a/ui/app/components/ui/typography/index.js b/ui/app/components/ui/typography/index.js index 648ce1725..ad5e11bde 100644 --- a/ui/app/components/ui/typography/index.js +++ b/ui/app/components/ui/typography/index.js @@ -1 +1 @@ -export { default } from './typography' +export { default } from './typography'; diff --git a/ui/app/components/ui/typography/typography.js b/ui/app/components/ui/typography/typography.js index c6ca4afe8..b18b53deb 100644 --- a/ui/app/components/ui/typography/typography.js +++ b/ui/app/components/ui/typography/typography.js @@ -1,15 +1,15 @@ -import React from 'react' -import classnames from 'classnames' -import PropTypes from 'prop-types' +import React from 'react'; +import classnames from 'classnames'; +import PropTypes from 'prop-types'; import { COLORS, FONT_WEIGHT, TEXT_ALIGN, TYPOGRAPHY, -} from '../../../helpers/constants/design-system' -import Box from '../box' +} from '../../../helpers/constants/design-system'; +import Box from '../box'; -const { H6, H7, H8, H9 } = TYPOGRAPHY +const { H6, H7, H8, H9 } = TYPOGRAPHY; export default function Typography({ variant = TYPOGRAPHY.Paragraph, @@ -28,14 +28,14 @@ export default function Typography({ `typography--align-${align}`, `typography--color-${color}`, `typography--weight-${fontWeight}`, - ) + ); - let Tag = tag ?? variant + let Tag = tag ?? variant; if (Tag === TYPOGRAPHY.Paragraph) { - Tag = 'p' + Tag = 'p'; } else if ([H7, H8, H9].includes(Tag)) { - Tag = H6 + Tag = H6; } return ( @@ -46,7 +46,7 @@ export default function Typography({ )}
    - ) + ); } Typography.propTypes = { @@ -72,4 +72,4 @@ Typography.propTypes = { 'dt', 'dd', ]), -} +}; diff --git a/ui/app/components/ui/typography/typography.stories.js b/ui/app/components/ui/typography/typography.stories.js index 0d0d486b8..bd39982a4 100644 --- a/ui/app/components/ui/typography/typography.stories.js +++ b/ui/app/components/ui/typography/typography.stories.js @@ -1,16 +1,16 @@ -import React from 'react' -import { number, select, text } from '@storybook/addon-knobs' +import React from 'react'; +import { number, select, text } from '@storybook/addon-knobs'; import { COLORS, FONT_WEIGHT, TEXT_ALIGN, TYPOGRAPHY, -} from '../../../helpers/constants/design-system' -import Typography from '.' +} from '../../../helpers/constants/design-system'; +import Typography from '.'; export default { title: 'Typography', -} +}; export const list = () => (
    @@ -32,7 +32,7 @@ export const list = () => (
    ))} -) +); export const TheQuickOrangeFox = () => (
    @@ -48,4 +48,4 @@ export const TheQuickOrangeFox = () => (
    -) +); diff --git a/ui/app/components/ui/unit-input/index.js b/ui/app/components/ui/unit-input/index.js index 7c33c9e5c..4eaa920b3 100644 --- a/ui/app/components/ui/unit-input/index.js +++ b/ui/app/components/ui/unit-input/index.js @@ -1 +1 @@ -export { default } from './unit-input.component' +export { default } from './unit-input.component'; diff --git a/ui/app/components/ui/unit-input/tests/unit-input.component.test.js b/ui/app/components/ui/unit-input/tests/unit-input.component.test.js index 47fdfafde..032b9b76e 100644 --- a/ui/app/components/ui/unit-input/tests/unit-input.component.test.js +++ b/ui/app/components/ui/unit-input/tests/unit-input.component.test.js @@ -1,99 +1,99 @@ -import assert from 'assert' -import React from 'react' -import { shallow, mount } from 'enzyme' -import sinon from 'sinon' -import UnitInput from '../unit-input.component' +import assert from 'assert'; +import React from 'react'; +import { shallow, mount } from 'enzyme'; +import sinon from 'sinon'; +import UnitInput from '../unit-input.component'; describe('UnitInput Component', function () { describe('rendering', function () { it('should render properly without a suffix', function () { - const wrapper = shallow() + const wrapper = shallow(); - assert.ok(wrapper) - assert.strictEqual(wrapper.find('.unit-input__suffix').length, 0) - }) + assert.ok(wrapper); + assert.strictEqual(wrapper.find('.unit-input__suffix').length, 0); + }); it('should render properly with a suffix', function () { - const wrapper = shallow() + const wrapper = shallow(); - assert.ok(wrapper) - assert.strictEqual(wrapper.find('.unit-input__suffix').length, 1) - assert.strictEqual(wrapper.find('.unit-input__suffix').text(), 'ETH') - }) + assert.ok(wrapper); + assert.strictEqual(wrapper.find('.unit-input__suffix').length, 1); + assert.strictEqual(wrapper.find('.unit-input__suffix').text(), 'ETH'); + }); it('should render properly with a child component', function () { const wrapper = shallow(
    TESTCOMPONENT
    , - ) + ); - assert.ok(wrapper) - assert.strictEqual(wrapper.find('.testing').length, 1) - assert.strictEqual(wrapper.find('.testing').text(), 'TESTCOMPONENT') - }) + assert.ok(wrapper); + assert.strictEqual(wrapper.find('.testing').length, 1); + assert.strictEqual(wrapper.find('.testing').text(), 'TESTCOMPONENT'); + }); it('should render with an error class when props.error === true', function () { - const wrapper = shallow() + const wrapper = shallow(); - assert.ok(wrapper) - assert.strictEqual(wrapper.find('.unit-input--error').length, 1) - }) - }) + assert.ok(wrapper); + assert.strictEqual(wrapper.find('.unit-input--error').length, 1); + }); + }); describe('handling actions', function () { - const handleChangeSpy = sinon.spy() - const handleBlurSpy = sinon.spy() + const handleChangeSpy = sinon.spy(); + const handleBlurSpy = sinon.spy(); afterEach(function () { - handleChangeSpy.resetHistory() - handleBlurSpy.resetHistory() - }) + handleChangeSpy.resetHistory(); + handleBlurSpy.resetHistory(); + }); it('should focus the input on component click', function () { - const wrapper = mount() + const wrapper = mount(); - assert.ok(wrapper) - const handleFocusSpy = sinon.spy(wrapper.instance(), 'handleFocus') - wrapper.instance().forceUpdate() - wrapper.update() - assert.strictEqual(handleFocusSpy.callCount, 0) - wrapper.find('.unit-input').simulate('click') - assert.strictEqual(handleFocusSpy.callCount, 1) - }) + assert.ok(wrapper); + const handleFocusSpy = sinon.spy(wrapper.instance(), 'handleFocus'); + wrapper.instance().forceUpdate(); + wrapper.update(); + assert.strictEqual(handleFocusSpy.callCount, 0); + wrapper.find('.unit-input').simulate('click'); + assert.strictEqual(handleFocusSpy.callCount, 1); + }); it('should call onChange on input changes with the value', function () { - const wrapper = mount() + const wrapper = mount(); - assert.ok(wrapper) - assert.strictEqual(handleChangeSpy.callCount, 0) - const input = wrapper.find('input') - input.simulate('change', { target: { value: 123 } }) - assert.strictEqual(handleChangeSpy.callCount, 1) - assert.ok(handleChangeSpy.calledWith(123)) - assert.strictEqual(wrapper.state('value'), 123) - }) + assert.ok(wrapper); + assert.strictEqual(handleChangeSpy.callCount, 0); + const input = wrapper.find('input'); + input.simulate('change', { target: { value: 123 } }); + assert.strictEqual(handleChangeSpy.callCount, 1); + assert.ok(handleChangeSpy.calledWith(123)); + assert.strictEqual(wrapper.state('value'), 123); + }); it('should set the component state value with props.value', function () { - const wrapper = mount() + const wrapper = mount(); - assert.ok(wrapper) - assert.strictEqual(wrapper.state('value'), 123) - }) + assert.ok(wrapper); + assert.strictEqual(wrapper.state('value'), 123); + }); it('should update the component state value with props.value', function () { - const wrapper = mount() + const wrapper = mount(); - assert.ok(wrapper) - assert.strictEqual(handleChangeSpy.callCount, 0) - const input = wrapper.find('input') - input.simulate('change', { target: { value: 123 } }) - assert.strictEqual(wrapper.state('value'), 123) - assert.strictEqual(handleChangeSpy.callCount, 1) - assert.ok(handleChangeSpy.calledWith(123)) - wrapper.setProps({ value: 456 }) - assert.strictEqual(wrapper.state('value'), 456) - assert.strictEqual(handleChangeSpy.callCount, 1) - }) - }) -}) + assert.ok(wrapper); + assert.strictEqual(handleChangeSpy.callCount, 0); + const input = wrapper.find('input'); + input.simulate('change', { target: { value: 123 } }); + assert.strictEqual(wrapper.state('value'), 123); + assert.strictEqual(handleChangeSpy.callCount, 1); + assert.ok(handleChangeSpy.calledWith(123)); + wrapper.setProps({ value: 456 }); + assert.strictEqual(wrapper.state('value'), 456); + assert.strictEqual(handleChangeSpy.callCount, 1); + }); + }); +}); diff --git a/ui/app/components/ui/unit-input/unit-input.component.js b/ui/app/components/ui/unit-input/unit-input.component.js index 8155e242b..8eeb39e1b 100644 --- a/ui/app/components/ui/unit-input/unit-input.component.js +++ b/ui/app/components/ui/unit-input/unit-input.component.js @@ -1,7 +1,7 @@ -import React, { PureComponent } from 'react' -import PropTypes from 'prop-types' -import classnames from 'classnames' -import { removeLeadingZeroes } from '../../../pages/send/send.utils' +import React, { PureComponent } from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; +import { removeLeadingZeroes } from '../../../pages/send/send.utils'; /** * Component that attaches a suffix or unit of measurement trailing user input, ex. 'ETH'. Also @@ -17,53 +17,59 @@ export default class UnitInput extends PureComponent { placeholder: PropTypes.string, suffix: PropTypes.string, value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), - } + }; static defaultProps = { value: '', placeholder: '0', - } + }; state = { value: this.props.value, - } + }; componentDidUpdate(prevProps) { - const { value: prevPropsValue } = prevProps - const { value: propsValue } = this.props - const { value: stateValue } = this.state + const { value: prevPropsValue } = prevProps; + const { value: propsValue } = this.props; + const { value: stateValue } = this.state; if (prevPropsValue !== propsValue && propsValue !== stateValue) { - this.setState({ value: propsValue }) + this.setState({ value: propsValue }); } } handleFocus = () => { - this.unitInput.focus() - } + this.unitInput.focus(); + }; handleChange = (event) => { - const { value: userInput } = event.target - let value = userInput + const { value: userInput } = event.target; + let value = userInput; if (userInput.length && userInput.length > 1) { - value = removeLeadingZeroes(userInput) + value = removeLeadingZeroes(userInput); } - this.setState({ value }) - this.props.onChange(value) - } + this.setState({ value }); + this.props.onChange(value); + }; getInputWidth(value) { - const valueString = String(value) - const valueLength = valueString.length || 1 - const decimalPointDeficit = valueString.match(/\./u) ? -0.5 : 0 - return `${valueLength + decimalPointDeficit + 0.5}ch` + const valueString = String(value); + const valueLength = valueString.length || 1; + const decimalPointDeficit = valueString.match(/\./u) ? -0.5 : 0; + return `${valueLength + decimalPointDeficit + 0.5}ch`; } render() { - const { error, placeholder, suffix, actionComponent, children } = this.props - const { value } = this.state + const { + error, + placeholder, + suffix, + actionComponent, + children, + } = this.props; + const { value } = this.state; return (
    { - this.unitInput = ref + this.unitInput = ref; }} /> {suffix &&
    {suffix}
    } @@ -90,6 +96,6 @@ export default class UnitInput extends PureComponent {
    {actionComponent} - ) + ); } } diff --git a/ui/app/components/ui/url-icon/index.js b/ui/app/components/ui/url-icon/index.js index c1bfd9fd7..6211d9f07 100644 --- a/ui/app/components/ui/url-icon/index.js +++ b/ui/app/components/ui/url-icon/index.js @@ -1 +1 @@ -export { default } from './url-icon' +export { default } from './url-icon'; diff --git a/ui/app/components/ui/url-icon/url-icon.js b/ui/app/components/ui/url-icon/url-icon.js index 115eb5fe1..b8381fd87 100644 --- a/ui/app/components/ui/url-icon/url-icon.js +++ b/ui/app/components/ui/url-icon/url-icon.js @@ -1,7 +1,7 @@ -import React from 'react' -import PropTypes from 'prop-types' -import classnames from 'classnames' -import IconWithFallback from '../icon-with-fallback' +import React from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; +import IconWithFallback from '../icon-with-fallback'; export default function UrlIcon({ url, className, name, fallbackClassName }) { return ( @@ -11,7 +11,7 @@ export default function UrlIcon({ url, className, name, fallbackClassName }) { name={name} fallbackClassName={classnames('url-icon__fallback', fallbackClassName)} /> - ) + ); } UrlIcon.propTypes = { @@ -19,4 +19,4 @@ UrlIcon.propTypes = { className: PropTypes.string, name: PropTypes.string, fallbackClassName: PropTypes.string, -} +}; diff --git a/ui/app/contexts/i18n.js b/ui/app/contexts/i18n.js index 86abd3fa0..0c64815aa 100644 --- a/ui/app/contexts/i18n.js +++ b/ui/app/contexts/i18n.js @@ -1,59 +1,61 @@ -import React, { Component, createContext, useMemo } from 'react' -import PropTypes from 'prop-types' -import { useSelector } from 'react-redux' -import { getMessage } from '../helpers/utils/i18n-helper' -import { getCurrentLocale } from '../ducks/metamask/metamask' +import React, { Component, createContext, useMemo } from 'react'; +import PropTypes from 'prop-types'; +import { useSelector } from 'react-redux'; +import { getMessage } from '../helpers/utils/i18n-helper'; +import { getCurrentLocale } from '../ducks/metamask/metamask'; import { getCurrentLocaleMessages, getEnLocaleMessages, -} from '../ducks/locale/locale' +} from '../ducks/locale/locale'; -export const I18nContext = createContext((key) => `[${key}]`) +export const I18nContext = createContext((key) => `[${key}]`); export const I18nProvider = (props) => { - const currentLocale = useSelector(getCurrentLocale) - const current = useSelector(getCurrentLocaleMessages) - const en = useSelector(getEnLocaleMessages) + const currentLocale = useSelector(getCurrentLocale); + const current = useSelector(getCurrentLocaleMessages); + const en = useSelector(getEnLocaleMessages); const t = useMemo(() => { return (key, ...args) => getMessage(currentLocale, current, key, ...args) || - getMessage(currentLocale, en, key, ...args) - }, [currentLocale, current, en]) + getMessage(currentLocale, en, key, ...args); + }, [currentLocale, current, en]); - return {props.children} -} + return ( + {props.children} + ); +}; I18nProvider.propTypes = { children: PropTypes.node, -} +}; I18nProvider.defaultProps = { children: undefined, -} +}; export class LegacyI18nProvider extends Component { static propTypes = { children: PropTypes.node, - } + }; static defaultProps = { children: undefined, - } + }; - static contextType = I18nContext + static contextType = I18nContext; static childContextTypes = { t: PropTypes.func, - } + }; getChildContext() { return { t: this.context, - } + }; } render() { - return this.props.children + return this.props.children; } } diff --git a/ui/app/contexts/metametrics.js b/ui/app/contexts/metametrics.js index 80d383a54..5940f1088 100644 --- a/ui/app/contexts/metametrics.js +++ b/ui/app/contexts/metametrics.js @@ -4,45 +4,45 @@ import React, { useEffect, useCallback, useState, -} from 'react' -import { useSelector } from 'react-redux' -import PropTypes from 'prop-types' -import { useHistory } from 'react-router-dom' -import { captureException } from '@sentry/browser' +} from 'react'; +import { useSelector } from 'react-redux'; +import PropTypes from 'prop-types'; +import { useHistory } from 'react-router-dom'; +import { captureException } from '@sentry/browser'; import { getAccountType, getNumberOfAccounts, getNumberOfTokens, -} from '../selectors/selectors' -import { getSendToken } from '../selectors/send' -import { txDataSelector } from '../selectors/confirm-transaction' -import { getEnvironmentType } from '../../../app/scripts/lib/util' -import { trackMetaMetricsEvent } from '../store/actions' +} from '../selectors/selectors'; +import { getSendToken } from '../selectors/send'; +import { txDataSelector } from '../selectors/confirm-transaction'; +import { getEnvironmentType } from '../../../app/scripts/lib/util'; +import { trackMetaMetricsEvent } from '../store/actions'; export const MetaMetricsContext = createContext(() => { captureException( Error( `MetaMetrics context function was called from a react node that is not a descendant of a MetaMetrics context provider`, ), - ) -}) + ); +}); export function MetaMetricsProvider({ children }) { - const txData = useSelector(txDataSelector) || {} - const environmentType = getEnvironmentType() - const activeCurrency = useSelector(getSendToken)?.symbol - const accountType = useSelector(getAccountType) - const confirmTransactionOrigin = txData.origin - const numberOfTokens = useSelector(getNumberOfTokens) - const numberOfAccounts = useSelector(getNumberOfAccounts) - const history = useHistory() + const txData = useSelector(txDataSelector) || {}; + const environmentType = getEnvironmentType(); + const activeCurrency = useSelector(getSendToken)?.symbol; + const accountType = useSelector(getAccountType); + const confirmTransactionOrigin = txData.origin; + const numberOfTokens = useSelector(getNumberOfTokens); + const numberOfAccounts = useSelector(getNumberOfAccounts); + const history = useHistory(); const [state, setState] = useState(() => ({ currentPath: new URL(window.location.href).pathname, previousPath: '', - })) + })); - const { currentPath } = state + const { currentPath } = state; useEffect(() => { const unlisten = history.listen(() => @@ -50,20 +50,20 @@ export function MetaMetricsProvider({ children }) { currentPath: new URL(window.location.href).pathname, previousPath: prevState.currentPath, })), - ) + ); // remove this listener if the component is no longer mounted - return unlisten - }, [history]) + return unlisten; + }, [history]); const metricsEvent = useCallback( (config = {}, overrides = {}) => { - const { eventOpts = {} } = config + const { eventOpts = {} } = config; const referrer = confirmTransactionOrigin ? { url: confirmTransactionOrigin } - : undefined + : undefined; const page = { path: currentPath, - } + }; return trackMetaMetricsEvent( { event: eventOpts.name, @@ -96,7 +96,7 @@ export function MetaMetricsProvider({ children }) { matomoEvent: true, flushImmediately: config.flushImmediately, }, - ) + ); }, [ accountType, @@ -107,39 +107,39 @@ export function MetaMetricsProvider({ children }) { numberOfAccounts, environmentType, ], - ) + ); return ( {children} - ) + ); } -MetaMetricsProvider.propTypes = { children: PropTypes.node } +MetaMetricsProvider.propTypes = { children: PropTypes.node }; export class LegacyMetaMetricsProvider extends Component { static propTypes = { children: PropTypes.node, - } + }; static defaultProps = { children: undefined, - } + }; - static contextType = MetaMetricsContext + static contextType = MetaMetricsContext; static childContextTypes = { metricsEvent: PropTypes.func, - } + }; getChildContext() { return { metricsEvent: this.context, - } + }; } render() { - return this.props.children + return this.props.children; } } diff --git a/ui/app/contexts/metametrics.new.js b/ui/app/contexts/metametrics.new.js index ca39df100..e46638c13 100644 --- a/ui/app/contexts/metametrics.new.js +++ b/ui/app/contexts/metametrics.new.js @@ -9,18 +9,18 @@ import React, { useEffect, useRef, useCallback, -} from 'react' -import { useSelector } from 'react-redux' -import PropTypes from 'prop-types' -import { matchPath, useLocation, useRouteMatch } from 'react-router-dom' -import { captureException, captureMessage } from '@sentry/browser' +} from 'react'; +import { useSelector } from 'react-redux'; +import PropTypes from 'prop-types'; +import { matchPath, useLocation, useRouteMatch } from 'react-router-dom'; +import { captureException, captureMessage } from '@sentry/browser'; -import { omit } from 'lodash' -import { getEnvironmentType } from '../../../app/scripts/lib/util' -import { PATH_NAME_MAP } from '../helpers/constants/routes' -import { txDataSelector } from '../selectors' +import { omit } from 'lodash'; +import { getEnvironmentType } from '../../../app/scripts/lib/util'; +import { PATH_NAME_MAP } from '../helpers/constants/routes'; +import { txDataSelector } from '../selectors'; -import { trackMetaMetricsEvent, trackMetaMetricsPage } from '../store/actions' +import { trackMetaMetricsEvent, trackMetaMetricsPage } from '../store/actions'; // type imports /** @@ -49,10 +49,10 @@ export const MetaMetricsContext = createContext(() => { Error( `MetaMetrics context function was called from a react node that is not a descendant of a MetaMetrics context provider`, ), - ) -}) + ); +}); -const PATHS_TO_CHECK = Object.keys(PATH_NAME_MAP) +const PATHS_TO_CHECK = Object.keys(PATH_NAME_MAP); /** * Returns the current page if it matches out route map, as well as the origin @@ -67,15 +67,15 @@ function useSegmentContext() { path: PATHS_TO_CHECK, exact: true, strict: true, - }) - const txData = useSelector(txDataSelector) || {} - const confirmTransactionOrigin = txData.origin + }); + const txData = useSelector(txDataSelector) || {}; + const confirmTransactionOrigin = txData.origin; const referrer = confirmTransactionOrigin ? { url: confirmTransactionOrigin, } - : undefined + : undefined; const page = match ? { @@ -83,17 +83,17 @@ function useSegmentContext() { title: PATH_NAME_MAP[match.path], url: match.path, } - : undefined + : undefined; return { page, referrer, - } + }; } export function MetaMetricsProvider({ children }) { - const location = useLocation() - const context = useSegmentContext() + const location = useLocation(); + const context = useSegmentContext(); /** * @type {UITrackEventMethod} @@ -107,13 +107,13 @@ export function MetaMetricsProvider({ children }) { ...context, }, options, - ) + ); }, [context], - ) + ); // Used to prevent double tracking page calls - const previousMatch = useRef() + const previousMatch = useRef(); /** * Anytime the location changes, track a page change with segment. @@ -122,12 +122,12 @@ export function MetaMetricsProvider({ children }) { * which page the user is on and their navigation path. */ useEffect(() => { - const environmentType = getEnvironmentType() + const environmentType = getEnvironmentType(); const match = matchPath(location.pathname, { path: PATHS_TO_CHECK, exact: true, strict: true, - }) + }); // Start by checking for a missing match route. If this falls through to // the else if, then we know we have a matched route for tracking. if (!match) { @@ -136,7 +136,7 @@ export function MetaMetricsProvider({ children }) { previousMatch, currentPath: location.pathname, }, - }) + }); } else if ( previousMatch.current !== match.path && !( @@ -150,8 +150,8 @@ export function MetaMetricsProvider({ children }) { // this we keep track of the previousMatch, and we skip the event track // in the event that we are dealing with the initial load of the // homepage - const { path, params } = match - const name = PATH_NAME_MAP[path] + const { path, params } = match; + const name = PATH_NAME_MAP[path]; trackMetaMetricsPage( { name, @@ -165,45 +165,45 @@ export function MetaMetricsProvider({ children }) { { isOptInPath: location.pathname.startsWith('/initialize'), }, - ) + ); } - previousMatch.current = match?.path - }, [location, context]) + previousMatch.current = match?.path; + }, [location, context]); return ( {children} - ) + ); } -MetaMetricsProvider.propTypes = { children: PropTypes.node } +MetaMetricsProvider.propTypes = { children: PropTypes.node }; export class LegacyMetaMetricsProvider extends Component { static propTypes = { children: PropTypes.node, - } + }; static defaultProps = { children: undefined, - } + }; - static contextType = MetaMetricsContext + static contextType = MetaMetricsContext; static childContextTypes = { // This has to be different than the type name for the old metametrics file // using the same name would result in whichever was lower in the tree to be // used. trackEvent: PropTypes.func, - } + }; getChildContext() { return { trackEvent: this.context, - } + }; } render() { - return this.props.children + return this.props.children; } } diff --git a/ui/app/ducks/alerts/enums.js b/ui/app/ducks/alerts/enums.js index 9a2267e52..b9192d846 100644 --- a/ui/app/ducks/alerts/enums.js +++ b/ui/app/ducks/alerts/enums.js @@ -3,4 +3,4 @@ export const ALERT_STATE = { ERROR: 'ERROR', LOADING: 'LOADING', OPEN: 'OPEN', -} +}; diff --git a/ui/app/ducks/alerts/index.js b/ui/app/ducks/alerts/index.js index d7387326b..28dd8c897 100644 --- a/ui/app/ducks/alerts/index.js +++ b/ui/app/ducks/alerts/index.js @@ -1,4 +1,4 @@ -export { default as unconnectedAccount } from './unconnected-account' -export { default as invalidCustomNetwork } from './invalid-custom-network' +export { default as unconnectedAccount } from './unconnected-account'; +export { default as invalidCustomNetwork } from './invalid-custom-network'; -export { ALERT_STATE } from './enums' +export { ALERT_STATE } from './enums'; diff --git a/ui/app/ducks/alerts/invalid-custom-network.js b/ui/app/ducks/alerts/invalid-custom-network.js index be2aa20e1..ab033ed46 100644 --- a/ui/app/ducks/alerts/invalid-custom-network.js +++ b/ui/app/ducks/alerts/invalid-custom-network.js @@ -1,16 +1,16 @@ -import { createSlice } from '@reduxjs/toolkit' +import { createSlice } from '@reduxjs/toolkit'; -import { ALERT_TYPES } from '../../../../shared/constants/alerts' -import { ALERT_STATE } from './enums' +import { ALERT_TYPES } from '../../../../shared/constants/alerts'; +import { ALERT_STATE } from './enums'; // Constants -const name = ALERT_TYPES.invalidCustomNetwork +const name = ALERT_TYPES.invalidCustomNetwork; const initialState = { state: ALERT_STATE.CLOSED, networkName: '', -} +}; // Slice (reducer plus auto-generated actions and action creators) @@ -19,30 +19,30 @@ const slice = createSlice({ initialState, reducers: { openAlert: (state, action) => { - state.state = ALERT_STATE.OPEN - state.networkName = action.payload + state.state = ALERT_STATE.OPEN; + state.networkName = action.payload; }, dismissAlert: (state) => { - state.state = ALERT_STATE.CLOSED - state.networkName = '' + state.state = ALERT_STATE.CLOSED; + state.networkName = ''; }, }, -}) +}); -const { actions, reducer } = slice +const { actions, reducer } = slice; -export default reducer +export default reducer; // Selectors -export const getAlertState = (state) => state[name].state +export const getAlertState = (state) => state[name].state; -export const getNetworkName = (state) => state[name].networkName +export const getNetworkName = (state) => state[name].networkName; -export const alertIsOpen = (state) => state[name].state !== ALERT_STATE.CLOSED +export const alertIsOpen = (state) => state[name].state !== ALERT_STATE.CLOSED; // Actions / action-creators -const { openAlert, dismissAlert } = actions +const { openAlert, dismissAlert } = actions; -export { openAlert, dismissAlert } +export { openAlert, dismissAlert }; diff --git a/ui/app/ducks/alerts/unconnected-account.js b/ui/app/ducks/alerts/unconnected-account.js index 563af43d2..2020def25 100644 --- a/ui/app/ducks/alerts/unconnected-account.js +++ b/ui/app/ducks/alerts/unconnected-account.js @@ -1,23 +1,23 @@ -import { createSlice } from '@reduxjs/toolkit' -import { captureException } from '@sentry/browser' +import { createSlice } from '@reduxjs/toolkit'; +import { captureException } from '@sentry/browser'; -import { ALERT_TYPES } from '../../../../shared/constants/alerts' -import * as actionConstants from '../../store/actionConstants' +import { ALERT_TYPES } from '../../../../shared/constants/alerts'; +import * as actionConstants from '../../store/actionConstants'; import { addPermittedAccount, setAlertEnabledness, setSelectedAddress, -} from '../../store/actions' -import { getOriginOfCurrentTab, getSelectedAddress } from '../../selectors' -import { ALERT_STATE } from './enums' +} from '../../store/actions'; +import { getOriginOfCurrentTab, getSelectedAddress } from '../../selectors'; +import { ALERT_STATE } from './enums'; // Constants -const name = ALERT_TYPES.unconnectedAccount +const name = ALERT_TYPES.unconnectedAccount; const initialState = { state: ALERT_STATE.CLOSED, -} +}; // Slice (reducer plus auto-generated actions and action creators) @@ -26,58 +26,58 @@ const slice = createSlice({ initialState, reducers: { connectAccountFailed: (state) => { - state.state = ALERT_STATE.ERROR + state.state = ALERT_STATE.ERROR; }, connectAccountRequested: (state) => { - state.state = ALERT_STATE.LOADING + state.state = ALERT_STATE.LOADING; }, connectAccountSucceeded: (state) => { - state.state = ALERT_STATE.CLOSED + state.state = ALERT_STATE.CLOSED; }, disableAlertFailed: (state) => { - state.state = ALERT_STATE.ERROR + state.state = ALERT_STATE.ERROR; }, disableAlertRequested: (state) => { - state.state = ALERT_STATE.LOADING + state.state = ALERT_STATE.LOADING; }, disableAlertSucceeded: (state) => { - state.state = ALERT_STATE.CLOSED + state.state = ALERT_STATE.CLOSED; }, dismissAlert: (state) => { - state.state = ALERT_STATE.CLOSED + state.state = ALERT_STATE.CLOSED; }, switchAccountFailed: (state) => { - state.state = ALERT_STATE.ERROR + state.state = ALERT_STATE.ERROR; }, switchAccountRequested: (state) => { - state.state = ALERT_STATE.LOADING + state.state = ALERT_STATE.LOADING; }, switchAccountSucceeded: (state) => { - state.state = ALERT_STATE.CLOSED + state.state = ALERT_STATE.CLOSED; }, switchedToUnconnectedAccount: (state) => { - state.state = ALERT_STATE.OPEN + state.state = ALERT_STATE.OPEN; }, }, extraReducers: { [actionConstants.SELECTED_ADDRESS_CHANGED]: (state) => { // close the alert if the account is switched while it's open if (state.state === ALERT_STATE.OPEN) { - state.state = ALERT_STATE.CLOSED + state.state = ALERT_STATE.CLOSED; } }, }, -}) +}); -const { actions, reducer } = slice +const { actions, reducer } = slice; -export default reducer +export default reducer; // Selectors -export const getAlertState = (state) => state[name].state +export const getAlertState = (state) => state[name].state; -export const alertIsOpen = (state) => state[name].state !== ALERT_STATE.CLOSED +export const alertIsOpen = (state) => state[name].state !== ALERT_STATE.CLOSED; // Actions / action-creators @@ -93,51 +93,51 @@ const { switchAccountRequested, switchAccountSucceeded, switchedToUnconnectedAccount, -} = actions +} = actions; -export { dismissAlert, switchedToUnconnectedAccount } +export { dismissAlert, switchedToUnconnectedAccount }; export const dismissAndDisableAlert = () => { return async (dispatch) => { try { - await dispatch(disableAlertRequested()) - await setAlertEnabledness(name, false) - await dispatch(disableAlertSucceeded()) + await dispatch(disableAlertRequested()); + await setAlertEnabledness(name, false); + await dispatch(disableAlertSucceeded()); } catch (error) { - console.error(error) - captureException(error) - await dispatch(disableAlertFailed()) + console.error(error); + captureException(error); + await dispatch(disableAlertFailed()); } - } -} + }; +}; export const switchToAccount = (address) => { return async (dispatch) => { try { - await dispatch(switchAccountRequested()) - await dispatch(setSelectedAddress(address)) - await dispatch(switchAccountSucceeded()) + await dispatch(switchAccountRequested()); + await dispatch(setSelectedAddress(address)); + await dispatch(switchAccountSucceeded()); } catch (error) { - console.error(error) - captureException(error) - await dispatch(switchAccountFailed()) + console.error(error); + captureException(error); + await dispatch(switchAccountFailed()); } - } -} + }; +}; export const connectAccount = () => { return async (dispatch, getState) => { - const state = getState() - const selectedAddress = getSelectedAddress(state) - const origin = getOriginOfCurrentTab(state) + const state = getState(); + const selectedAddress = getSelectedAddress(state); + const origin = getOriginOfCurrentTab(state); try { - await dispatch(connectAccountRequested()) - await dispatch(addPermittedAccount(origin, selectedAddress)) - await dispatch(connectAccountSucceeded()) + await dispatch(connectAccountRequested()); + await dispatch(addPermittedAccount(origin, selectedAddress)); + await dispatch(connectAccountSucceeded()); } catch (error) { - console.error(error) - captureException(error) - await dispatch(connectAccountFailed()) + console.error(error); + captureException(error); + await dispatch(connectAccountFailed()); } - } -} + }; +}; diff --git a/ui/app/ducks/app/app.js b/ui/app/ducks/app/app.js index 06f194a17..c927e70c9 100644 --- a/ui/app/ducks/app/app.js +++ b/ui/app/ducks/app/app.js @@ -1,7 +1,7 @@ -import * as actionConstants from '../../store/actionConstants' +import * as actionConstants from '../../store/actionConstants'; // actionConstants -const SET_THREEBOX_LAST_UPDATED = 'metamask/app/SET_THREEBOX_LAST_UPDATED' +const SET_THREEBOX_LAST_UPDATED = 'metamask/app/SET_THREEBOX_LAST_UPDATED'; export default function reduceApp(state = {}, action) { // default state @@ -51,7 +51,7 @@ export default function reduceApp(state = {}, action) { openMetaMaskTabs: {}, currentWindowTab: {}, ...state, - } + }; switch (action.type) { // dropdown methods @@ -59,13 +59,13 @@ export default function reduceApp(state = {}, action) { return { ...appState, networkDropdownOpen: true, - } + }; case actionConstants.NETWORK_DROPDOWN_CLOSE: return { ...appState, networkDropdownOpen: false, - } + }; // sidebar methods case actionConstants.SIDEBAR_OPEN: @@ -75,7 +75,7 @@ export default function reduceApp(state = {}, action) { ...action.value, isOpen: true, }, - } + }; case actionConstants.SIDEBAR_CLOSE: return { @@ -84,7 +84,7 @@ export default function reduceApp(state = {}, action) { ...appState.sidebar, isOpen: false, }, - } + }; // alert methods case actionConstants.ALERT_OPEN: @@ -92,25 +92,25 @@ export default function reduceApp(state = {}, action) { ...appState, alertOpen: true, alertMessage: action.value, - } + }; case actionConstants.ALERT_CLOSE: return { ...appState, alertOpen: false, alertMessage: null, - } + }; // qr scanner methods case actionConstants.QR_CODE_DETECTED: return { ...appState, qrCodeData: action.value, - } + }; // modal methods: case actionConstants.MODAL_OPEN: { - const { name, ...modalProps } = action.payload + const { name, ...modalProps } = action.payload; return { ...appState, @@ -122,7 +122,7 @@ export default function reduceApp(state = {}, action) { }, previousModalState: { ...appState.modal.modalState }, }, - } + }; } case actionConstants.MODAL_CLOSE: @@ -134,31 +134,31 @@ export default function reduceApp(state = {}, action) { { modalState: { name: null, props: {} } }, { previousModalState: appState.modal.modalState }, ), - } + }; case actionConstants.CLEAR_ACCOUNT_DETAILS: return { ...appState, accountDetail: {}, - } + }; case actionConstants.FORGOT_PASSWORD: return { ...appState, forgottenPassword: action.value, - } + }; case actionConstants.SHOW_SEND_TOKEN_PAGE: return { ...appState, warning: null, - } + }; case actionConstants.LOCK_METAMASK: return { ...appState, warning: null, - } + }; // accounts @@ -171,7 +171,7 @@ export default function reduceApp(state = {}, action) { privateKey: '', }, warning: null, - } + }; case actionConstants.SHOW_ACCOUNT_DETAIL: return { @@ -184,7 +184,7 @@ export default function reduceApp(state = {}, action) { accountExport: 'none', privateKey: '', }, - } + }; case actionConstants.SHOW_ACCOUNTS_PAGE: return { @@ -193,7 +193,7 @@ export default function reduceApp(state = {}, action) { warning: null, scrollToBottom: false, forgottenPassword: false, - } + }; case actionConstants.SHOW_CONF_TX_PAGE: return { @@ -201,7 +201,7 @@ export default function reduceApp(state = {}, action) { txId: action.id, warning: null, isLoading: false, - } + }; case actionConstants.COMPLETED_TX: if (action.value.unconfirmedActionsCount > 0) { @@ -209,7 +209,7 @@ export default function reduceApp(state = {}, action) { ...appState, txId: null, warning: null, - } + }; } return { ...appState, @@ -220,34 +220,34 @@ export default function reduceApp(state = {}, action) { accountDetail: { subview: 'transactions', }, - } + }; case actionConstants.TRANSACTION_ERROR: return { ...appState, - } + }; case actionConstants.UNLOCK_FAILED: return { ...appState, warning: action.value || 'Incorrect password. Try again.', - } + }; case actionConstants.UNLOCK_SUCCEEDED: return { ...appState, warning: '', - } + }; case actionConstants.SET_HARDWARE_WALLET_DEFAULT_HD_PATH: { - const { device, path } = action.value - const newDefaults = { ...appState.defaultHdPaths } - newDefaults[device] = path + const { device, path } = action.value; + const newDefaults = { ...appState.defaultHdPaths }; + newDefaults[device] = path; return { ...appState, defaultHdPaths: newDefaults, - } + }; } case actionConstants.SHOW_LOADING: @@ -255,26 +255,26 @@ export default function reduceApp(state = {}, action) { ...appState, isLoading: true, loadingMessage: action.value, - } + }; case actionConstants.HIDE_LOADING: return { ...appState, isLoading: false, - } + }; case actionConstants.DISPLAY_WARNING: return { ...appState, warning: action.value, isLoading: false, - } + }; case actionConstants.HIDE_WARNING: return { ...appState, warning: undefined, - } + }; case actionConstants.SHOW_PRIVATE_KEY: return { @@ -284,76 +284,76 @@ export default function reduceApp(state = {}, action) { accountExport: 'completed', privateKey: action.value, }, - } + }; case actionConstants.SET_MOUSE_USER_STATE: return { ...appState, isMouseUser: action.value, - } + }; case actionConstants.GAS_LOADING_STARTED: return { ...appState, gasIsLoading: true, - } + }; case actionConstants.GAS_LOADING_FINISHED: return { ...appState, gasIsLoading: false, - } + }; case actionConstants.SET_SELECTED_SETTINGS_RPC_URL: return { ...appState, networksTabSelectedRpcUrl: action.value, - } + }; case actionConstants.SET_NETWORKS_TAB_ADD_MODE: return { ...appState, networksTabIsInAddMode: action.value, - } + }; case actionConstants.LOADING_METHOD_DATA_STARTED: return { ...appState, loadingMethodData: true, - } + }; case actionConstants.LOADING_METHOD_DATA_FINISHED: return { ...appState, loadingMethodData: false, - } + }; case SET_THREEBOX_LAST_UPDATED: return { ...appState, threeBoxLastUpdated: action.value, - } + }; case actionConstants.SET_REQUEST_ACCOUNT_TABS: return { ...appState, requestAccountTabs: action.value, - } + }; case actionConstants.SET_OPEN_METAMASK_TAB_IDS: return { ...appState, openMetaMaskTabs: action.value, - } + }; case actionConstants.SET_CURRENT_WINDOW_TAB: return { ...appState, currentWindowTab: action.value, - } + }; default: - return appState + return appState; } } @@ -362,5 +362,5 @@ export function setThreeBoxLastUpdated(lastUpdated) { return { type: SET_THREEBOX_LAST_UPDATED, value: lastUpdated, - } + }; } diff --git a/ui/app/ducks/confirm-transaction/confirm-transaction.duck.js b/ui/app/ducks/confirm-transaction/confirm-transaction.duck.js index 5125f17d9..a89eeae36 100644 --- a/ui/app/ducks/confirm-transaction/confirm-transaction.duck.js +++ b/ui/app/ducks/confirm-transaction/confirm-transaction.duck.js @@ -1,10 +1,10 @@ -import { addHexPrefix } from '../../../../app/scripts/lib/util' +import { addHexPrefix } from '../../../../app/scripts/lib/util'; import { conversionRateSelector, currentCurrencySelector, unconfirmedTransactionsHashSelector, getNativeCurrency, -} from '../../selectors' +} from '../../selectors'; import { getValueFromWeiHex, @@ -14,32 +14,32 @@ import { addEth, increaseLastGasPrice, hexGreaterThan, -} from '../../helpers/utils/confirm-tx.util' +} from '../../helpers/utils/confirm-tx.util'; -import { getTokenData, sumHexes } from '../../helpers/utils/transactions.util' +import { getTokenData, sumHexes } from '../../helpers/utils/transactions.util'; -import { conversionUtil } from '../../helpers/utils/conversion-util' +import { conversionUtil } from '../../helpers/utils/conversion-util'; // Actions -const createActionType = (action) => `metamask/confirm-transaction/${action}` +const createActionType = (action) => `metamask/confirm-transaction/${action}`; -const UPDATE_TX_DATA = createActionType('UPDATE_TX_DATA') -const CLEAR_TX_DATA = createActionType('CLEAR_TX_DATA') -const UPDATE_TOKEN_DATA = createActionType('UPDATE_TOKEN_DATA') -const CLEAR_TOKEN_DATA = createActionType('CLEAR_TOKEN_DATA') -const UPDATE_METHOD_DATA = createActionType('UPDATE_METHOD_DATA') -const CLEAR_METHOD_DATA = createActionType('CLEAR_METHOD_DATA') -const CLEAR_CONFIRM_TRANSACTION = createActionType('CLEAR_CONFIRM_TRANSACTION') +const UPDATE_TX_DATA = createActionType('UPDATE_TX_DATA'); +const CLEAR_TX_DATA = createActionType('CLEAR_TX_DATA'); +const UPDATE_TOKEN_DATA = createActionType('UPDATE_TOKEN_DATA'); +const CLEAR_TOKEN_DATA = createActionType('CLEAR_TOKEN_DATA'); +const UPDATE_METHOD_DATA = createActionType('UPDATE_METHOD_DATA'); +const CLEAR_METHOD_DATA = createActionType('CLEAR_METHOD_DATA'); +const CLEAR_CONFIRM_TRANSACTION = createActionType('CLEAR_CONFIRM_TRANSACTION'); const UPDATE_TRANSACTION_AMOUNTS = createActionType( 'UPDATE_TRANSACTION_AMOUNTS', -) -const UPDATE_TRANSACTION_FEES = createActionType('UPDATE_TRANSACTION_FEES') -const UPDATE_TRANSACTION_TOTALS = createActionType('UPDATE_TRANSACTION_TOTALS') -const UPDATE_TOKEN_PROPS = createActionType('UPDATE_TOKEN_PROPS') -const UPDATE_NONCE = createActionType('UPDATE_NONCE') -const UPDATE_TO_SMART_CONTRACT = createActionType('UPDATE_TO_SMART_CONTRACT') -const FETCH_DATA_START = createActionType('FETCH_DATA_START') -const FETCH_DATA_END = createActionType('FETCH_DATA_END') +); +const UPDATE_TRANSACTION_FEES = createActionType('UPDATE_TRANSACTION_FEES'); +const UPDATE_TRANSACTION_TOTALS = createActionType('UPDATE_TRANSACTION_TOTALS'); +const UPDATE_TOKEN_PROPS = createActionType('UPDATE_TOKEN_PROPS'); +const UPDATE_NONCE = createActionType('UPDATE_NONCE'); +const UPDATE_TO_SMART_CONTRACT = createActionType('UPDATE_TO_SMART_CONTRACT'); +const FETCH_DATA_START = createActionType('FETCH_DATA_START'); +const FETCH_DATA_END = createActionType('FETCH_DATA_END'); // Initial state const initState = { @@ -62,7 +62,7 @@ const initState = { nonce: '', toSmartContract: false, fetchingData: false, -} +}; // Reducer export default function reducer(state = initState, action = {}) { @@ -73,42 +73,42 @@ export default function reducer(state = initState, action = {}) { txData: { ...action.payload, }, - } + }; case CLEAR_TX_DATA: return { ...state, txData: {}, - } + }; case UPDATE_TOKEN_DATA: return { ...state, tokenData: { ...action.payload, }, - } + }; case CLEAR_TOKEN_DATA: return { ...state, tokenData: {}, - } + }; case UPDATE_METHOD_DATA: return { ...state, methodData: { ...action.payload, }, - } + }; case CLEAR_METHOD_DATA: return { ...state, methodData: {}, - } + }; case UPDATE_TRANSACTION_AMOUNTS: { const { fiatTransactionAmount, ethTransactionAmount, hexTransactionAmount, - } = action.payload + } = action.payload; return { ...state, fiatTransactionAmount: @@ -117,37 +117,37 @@ export default function reducer(state = initState, action = {}) { ethTransactionAmount || state.ethTransactionAmount, hexTransactionAmount: hexTransactionAmount || state.hexTransactionAmount, - } + }; } case UPDATE_TRANSACTION_FEES: { const { fiatTransactionFee, ethTransactionFee, hexTransactionFee, - } = action.payload + } = action.payload; return { ...state, fiatTransactionFee: fiatTransactionFee || state.fiatTransactionFee, ethTransactionFee: ethTransactionFee || state.ethTransactionFee, hexTransactionFee: hexTransactionFee || state.hexTransactionFee, - } + }; } case UPDATE_TRANSACTION_TOTALS: { const { fiatTransactionTotal, ethTransactionTotal, hexTransactionTotal, - } = action.payload + } = action.payload; return { ...state, fiatTransactionTotal: fiatTransactionTotal || state.fiatTransactionTotal, ethTransactionTotal: ethTransactionTotal || state.ethTransactionTotal, hexTransactionTotal: hexTransactionTotal || state.hexTransactionTotal, - } + }; } case UPDATE_TOKEN_PROPS: { - const { tokenSymbol = '', tokenDecimals = '' } = action.payload + const { tokenSymbol = '', tokenDecimals = '' } = action.payload; return { ...state, tokenProps: { @@ -155,32 +155,32 @@ export default function reducer(state = initState, action = {}) { tokenSymbol, tokenDecimals, }, - } + }; } case UPDATE_NONCE: return { ...state, nonce: action.payload, - } + }; case UPDATE_TO_SMART_CONTRACT: return { ...state, toSmartContract: action.payload, - } + }; case FETCH_DATA_START: return { ...state, fetchingData: true, - } + }; case FETCH_DATA_END: return { ...state, fetchingData: false, - } + }; case CLEAR_CONFIRM_TRANSACTION: - return initState + return initState; default: - return state + return state; } } @@ -189,94 +189,94 @@ export function updateTxData(txData) { return { type: UPDATE_TX_DATA, payload: txData, - } + }; } export function clearTxData() { return { type: CLEAR_TX_DATA, - } + }; } export function updateTokenData(tokenData) { return { type: UPDATE_TOKEN_DATA, payload: tokenData, - } + }; } export function clearTokenData() { return { type: CLEAR_TOKEN_DATA, - } + }; } export function updateMethodData(methodData) { return { type: UPDATE_METHOD_DATA, payload: methodData, - } + }; } export function clearMethodData() { return { type: CLEAR_METHOD_DATA, - } + }; } export function updateTransactionAmounts(amounts) { return { type: UPDATE_TRANSACTION_AMOUNTS, payload: amounts, - } + }; } export function updateTransactionFees(fees) { return { type: UPDATE_TRANSACTION_FEES, payload: fees, - } + }; } export function updateTransactionTotals(totals) { return { type: UPDATE_TRANSACTION_TOTALS, payload: totals, - } + }; } export function updateTokenProps(tokenProps) { return { type: UPDATE_TOKEN_PROPS, payload: tokenProps, - } + }; } export function updateNonce(nonce) { return { type: UPDATE_NONCE, payload: nonce, - } + }; } export function updateToSmartContract(toSmartContract) { return { type: UPDATE_TO_SMART_CONTRACT, payload: toSmartContract, - } + }; } export function setFetchingData(isFetching) { return { type: isFetching ? FETCH_DATA_START : FETCH_DATA_END, - } + }; } export function updateGasAndCalculate({ gasLimit, gasPrice }) { return (dispatch, getState) => { const { confirmTransaction: { txData }, - } = getState() + } = getState(); const newTxData = { ...txData, txParams: { @@ -284,22 +284,28 @@ export function updateGasAndCalculate({ gasLimit, gasPrice }) { gas: addHexPrefix(gasLimit), gasPrice: addHexPrefix(gasPrice), }, - } + }; - dispatch(updateTxDataAndCalculate(newTxData)) - } + dispatch(updateTxDataAndCalculate(newTxData)); + }; } function increaseFromLastGasPrice(txData) { - const { lastGasPrice, txParams: { gasPrice: previousGasPrice } = {} } = txData + const { + lastGasPrice, + txParams: { gasPrice: previousGasPrice } = {}, + } = txData; // Set the minimum to a 10% increase from the lastGasPrice. - const minimumGasPrice = increaseLastGasPrice(lastGasPrice) - const gasPriceBelowMinimum = hexGreaterThan(minimumGasPrice, previousGasPrice) + const minimumGasPrice = increaseLastGasPrice(lastGasPrice); + const gasPriceBelowMinimum = hexGreaterThan( + minimumGasPrice, + previousGasPrice, + ); const gasPrice = !previousGasPrice || gasPriceBelowMinimum ? minimumGasPrice - : previousGasPrice + : previousGasPrice; return { ...txData, @@ -307,21 +313,21 @@ function increaseFromLastGasPrice(txData) { ...txData.txParams, gasPrice, }, - } + }; } export function updateTxDataAndCalculate(txData) { return (dispatch, getState) => { - const state = getState() - const currentCurrency = currentCurrencySelector(state) - const conversionRate = conversionRateSelector(state) - const nativeCurrency = getNativeCurrency(state) + const state = getState(); + const currentCurrency = currentCurrencySelector(state); + const conversionRate = conversionRateSelector(state); + const nativeCurrency = getNativeCurrency(state); - dispatch(updateTxData(txData)) + dispatch(updateTxData(txData)); const { txParams: { value = '0x0', gas: gasLimit = '0x0', gasPrice = '0x0' } = {}, - } = txData + } = txData; const fiatTransactionAmount = getValueFromWeiHex({ value, @@ -329,14 +335,14 @@ export function updateTxDataAndCalculate(txData) { toCurrency: currentCurrency, conversionRate, numberOfDecimals: 2, - }) + }); const ethTransactionAmount = getValueFromWeiHex({ value, fromCurrency: nativeCurrency, toCurrency: nativeCurrency, conversionRate, numberOfDecimals: 6, - }) + }); dispatch( updateTransactionAmounts({ @@ -344,9 +350,9 @@ export function updateTxDataAndCalculate(txData) { ethTransactionAmount, hexTransactionAmount: value, }), - ) + ); - const hexTransactionFee = getHexGasTotal({ gasLimit, gasPrice }) + const hexTransactionFee = getHexGasTotal({ gasLimit, gasPrice }); const fiatTransactionFee = getTransactionFee({ value: hexTransactionFee, @@ -354,14 +360,14 @@ export function updateTxDataAndCalculate(txData) { toCurrency: currentCurrency, numberOfDecimals: 2, conversionRate, - }) + }); const ethTransactionFee = getTransactionFee({ value: hexTransactionFee, fromCurrency: nativeCurrency, toCurrency: nativeCurrency, numberOfDecimals: 6, conversionRate, - }) + }); dispatch( updateTransactionFees({ @@ -369,14 +375,14 @@ export function updateTxDataAndCalculate(txData) { ethTransactionFee, hexTransactionFee, }), - ) + ); const fiatTransactionTotal = addFiat( fiatTransactionFee, fiatTransactionAmount, - ) - const ethTransactionTotal = addEth(ethTransactionFee, ethTransactionAmount) - const hexTransactionTotal = sumHexes(value, hexTransactionFee) + ); + const ethTransactionTotal = addEth(ethTransactionFee, ethTransactionAmount); + const hexTransactionTotal = sumHexes(value, hexTransactionFee); dispatch( updateTransactionTotals({ @@ -384,55 +390,55 @@ export function updateTxDataAndCalculate(txData) { ethTransactionTotal, hexTransactionTotal, }), - ) - } + ); + }; } export function setTransactionToConfirm(transactionId) { return (dispatch, getState) => { - const state = getState() + const state = getState(); const unconfirmedTransactionsHash = unconfirmedTransactionsHashSelector( state, - ) - const transaction = unconfirmedTransactionsHash[transactionId] + ); + const transaction = unconfirmedTransactionsHash[transactionId]; if (!transaction) { - console.error(`Transaction with id ${transactionId} not found`) - return + console.error(`Transaction with id ${transactionId} not found`); + return; } if (transaction.txParams) { - const { lastGasPrice } = transaction + const { lastGasPrice } = transaction; const txData = lastGasPrice ? increaseFromLastGasPrice(transaction) - : transaction - dispatch(updateTxDataAndCalculate(txData)) + : transaction; + dispatch(updateTxDataAndCalculate(txData)); - const { txParams } = transaction + const { txParams } = transaction; if (txParams.data) { - const { data } = txParams + const { data } = txParams; - const tokenData = getTokenData(data) - dispatch(updateTokenData(tokenData)) + const tokenData = getTokenData(data); + dispatch(updateTokenData(tokenData)); } if (txParams.nonce) { const nonce = conversionUtil(txParams.nonce, { fromNumericBase: 'hex', toNumericBase: 'dec', - }) + }); - dispatch(updateNonce(nonce)) + dispatch(updateNonce(nonce)); } } else { - dispatch(updateTxData(transaction)) + dispatch(updateTxData(transaction)); } - } + }; } export function clearConfirmTransaction() { return { type: CLEAR_CONFIRM_TRANSACTION, - } + }; } diff --git a/ui/app/ducks/confirm-transaction/confirm-transaction.duck.test.js b/ui/app/ducks/confirm-transaction/confirm-transaction.duck.test.js index f5edaa67f..6f512a703 100644 --- a/ui/app/ducks/confirm-transaction/confirm-transaction.duck.test.js +++ b/ui/app/ducks/confirm-transaction/confirm-transaction.duck.test.js @@ -1,13 +1,13 @@ -import assert from 'assert' -import configureMockStore from 'redux-mock-store' -import thunk from 'redux-thunk' -import sinon from 'sinon' +import assert from 'assert'; +import configureMockStore from 'redux-mock-store'; +import thunk from 'redux-thunk'; +import sinon from 'sinon'; import { TRANSACTION_CATEGORIES, TRANSACTION_STATUSES, -} from '../../../../shared/constants/transaction' +} from '../../../../shared/constants/transaction'; -import ConfirmTransactionReducer, * as actions from './confirm-transaction.duck' +import ConfirmTransactionReducer, * as actions from './confirm-transaction.duck'; const initialState = { txData: {}, @@ -29,28 +29,28 @@ const initialState = { nonce: '', toSmartContract: false, fetchingData: false, -} +}; -const UPDATE_TX_DATA = 'metamask/confirm-transaction/UPDATE_TX_DATA' -const CLEAR_TX_DATA = 'metamask/confirm-transaction/CLEAR_TX_DATA' -const UPDATE_TOKEN_DATA = 'metamask/confirm-transaction/UPDATE_TOKEN_DATA' -const CLEAR_TOKEN_DATA = 'metamask/confirm-transaction/CLEAR_TOKEN_DATA' -const UPDATE_METHOD_DATA = 'metamask/confirm-transaction/UPDATE_METHOD_DATA' -const CLEAR_METHOD_DATA = 'metamask/confirm-transaction/CLEAR_METHOD_DATA' +const UPDATE_TX_DATA = 'metamask/confirm-transaction/UPDATE_TX_DATA'; +const CLEAR_TX_DATA = 'metamask/confirm-transaction/CLEAR_TX_DATA'; +const UPDATE_TOKEN_DATA = 'metamask/confirm-transaction/UPDATE_TOKEN_DATA'; +const CLEAR_TOKEN_DATA = 'metamask/confirm-transaction/CLEAR_TOKEN_DATA'; +const UPDATE_METHOD_DATA = 'metamask/confirm-transaction/UPDATE_METHOD_DATA'; +const CLEAR_METHOD_DATA = 'metamask/confirm-transaction/CLEAR_METHOD_DATA'; const UPDATE_TRANSACTION_AMOUNTS = - 'metamask/confirm-transaction/UPDATE_TRANSACTION_AMOUNTS' + 'metamask/confirm-transaction/UPDATE_TRANSACTION_AMOUNTS'; const UPDATE_TRANSACTION_FEES = - 'metamask/confirm-transaction/UPDATE_TRANSACTION_FEES' + 'metamask/confirm-transaction/UPDATE_TRANSACTION_FEES'; const UPDATE_TRANSACTION_TOTALS = - 'metamask/confirm-transaction/UPDATE_TRANSACTION_TOTALS' -const UPDATE_TOKEN_PROPS = 'metamask/confirm-transaction/UPDATE_TOKEN_PROPS' -const UPDATE_NONCE = 'metamask/confirm-transaction/UPDATE_NONCE' + 'metamask/confirm-transaction/UPDATE_TRANSACTION_TOTALS'; +const UPDATE_TOKEN_PROPS = 'metamask/confirm-transaction/UPDATE_TOKEN_PROPS'; +const UPDATE_NONCE = 'metamask/confirm-transaction/UPDATE_NONCE'; const UPDATE_TO_SMART_CONTRACT = - 'metamask/confirm-transaction/UPDATE_TO_SMART_CONTRACT' -const FETCH_DATA_START = 'metamask/confirm-transaction/FETCH_DATA_START' -const FETCH_DATA_END = 'metamask/confirm-transaction/FETCH_DATA_END' + 'metamask/confirm-transaction/UPDATE_TO_SMART_CONTRACT'; +const FETCH_DATA_START = 'metamask/confirm-transaction/FETCH_DATA_START'; +const FETCH_DATA_END = 'metamask/confirm-transaction/FETCH_DATA_END'; const CLEAR_CONFIRM_TRANSACTION = - 'metamask/confirm-transaction/CLEAR_CONFIRM_TRANSACTION' + 'metamask/confirm-transaction/CLEAR_CONFIRM_TRANSACTION'; describe('Confirm Transaction Duck', function () { describe('State changes', function () { @@ -80,14 +80,14 @@ describe('Confirm Transaction Duck', function () { nonce: '0x0', toSmartContract: false, fetchingData: false, - } + }; it('should initialize state', function () { assert.deepStrictEqual( ConfirmTransactionReducer(undefined, {}), initialState, - ) - }) + ); + }); it('should return state unchanged if it does not match a dispatched actions type', function () { assert.deepStrictEqual( @@ -96,8 +96,8 @@ describe('Confirm Transaction Duck', function () { value: 'someValue', }), { ...mockState }, - ) - }) + ); + }); it('should set txData when receiving a UPDATE_TX_DATA action', function () { assert.deepStrictEqual( @@ -114,8 +114,8 @@ describe('Confirm Transaction Duck', function () { id: 2, }, }, - ) - }) + ); + }); it('should clear txData when receiving a CLEAR_TX_DATA action', function () { assert.deepStrictEqual( @@ -126,8 +126,8 @@ describe('Confirm Transaction Duck', function () { ...mockState, txData: {}, }, - ) - }) + ); + }); it('should set tokenData when receiving a UPDATE_TOKEN_DATA action', function () { assert.deepStrictEqual( @@ -144,8 +144,8 @@ describe('Confirm Transaction Duck', function () { name: 'defToken', }, }, - ) - }) + ); + }); it('should clear tokenData when receiving a CLEAR_TOKEN_DATA action', function () { assert.deepStrictEqual( @@ -156,8 +156,8 @@ describe('Confirm Transaction Duck', function () { ...mockState, tokenData: {}, }, - ) - }) + ); + }); it('should set methodData when receiving a UPDATE_METHOD_DATA action', function () { assert.deepStrictEqual( @@ -174,8 +174,8 @@ describe('Confirm Transaction Duck', function () { name: 'transferFrom', }, }, - ) - }) + ); + }); it('should clear methodData when receiving a CLEAR_METHOD_DATA action', function () { assert.deepStrictEqual( @@ -186,8 +186,8 @@ describe('Confirm Transaction Duck', function () { ...mockState, methodData: {}, }, - ) - }) + ); + }); it('should update transaction amounts when receiving an UPDATE_TRANSACTION_AMOUNTS action', function () { assert.deepStrictEqual( @@ -205,8 +205,8 @@ describe('Confirm Transaction Duck', function () { ethTransactionAmount: '.5', hexTransactionAmount: '0x1', }, - ) - }) + ); + }); it('should update transaction fees when receiving an UPDATE_TRANSACTION_FEES action', function () { assert.deepStrictEqual( @@ -224,8 +224,8 @@ describe('Confirm Transaction Duck', function () { ethTransactionFee: '.5', hexTransactionFee: '0x1', }, - ) - }) + ); + }); it('should update transaction totals when receiving an UPDATE_TRANSACTION_TOTALS action', function () { assert.deepStrictEqual( @@ -243,8 +243,8 @@ describe('Confirm Transaction Duck', function () { ethTransactionTotal: '.5', hexTransactionTotal: '0x1', }, - ) - }) + ); + }); it('should update tokenProps when receiving an UPDATE_TOKEN_PROPS action', function () { assert.deepStrictEqual( @@ -262,8 +262,8 @@ describe('Confirm Transaction Duck', function () { tokenDecimals: '1', }, }, - ) - }) + ); + }); it('should update nonce when receiving an UPDATE_NONCE action', function () { assert.deepStrictEqual( @@ -275,8 +275,8 @@ describe('Confirm Transaction Duck', function () { ...mockState, nonce: '0x1', }, - ) - }) + ); + }); it('should update nonce when receiving an UPDATE_TO_SMART_CONTRACT action', function () { assert.deepStrictEqual( @@ -288,8 +288,8 @@ describe('Confirm Transaction Duck', function () { ...mockState, toSmartContract: true, }, - ) - }) + ); + }); it('should set fetchingData to true when receiving a FETCH_DATA_START action', function () { assert.deepStrictEqual( @@ -300,8 +300,8 @@ describe('Confirm Transaction Duck', function () { ...mockState, fetchingData: true, }, - ) - }) + ); + }); it('should set fetchingData to false when receiving a FETCH_DATA_END action', function () { assert.deepStrictEqual( @@ -310,8 +310,8 @@ describe('Confirm Transaction Duck', function () { { type: FETCH_DATA_END }, ), { fetchingData: false }, - ) - }) + ); + }); it('should clear confirmTransaction when receiving a FETCH_DATA_END action', function () { assert.deepStrictEqual( @@ -319,157 +319,160 @@ describe('Confirm Transaction Duck', function () { type: CLEAR_CONFIRM_TRANSACTION, }), initialState, - ) - }) - }) + ); + }); + }); describe('Single actions', function () { it('should create an action to update txData', function () { - const txData = { test: 123 } + const txData = { test: 123 }; const expectedAction = { type: UPDATE_TX_DATA, payload: txData, - } + }; - assert.deepStrictEqual(actions.updateTxData(txData), expectedAction) - }) + assert.deepStrictEqual(actions.updateTxData(txData), expectedAction); + }); it('should create an action to clear txData', function () { const expectedAction = { type: CLEAR_TX_DATA, - } + }; - assert.deepStrictEqual(actions.clearTxData(), expectedAction) - }) + assert.deepStrictEqual(actions.clearTxData(), expectedAction); + }); it('should create an action to update tokenData', function () { - const tokenData = { test: 123 } + const tokenData = { test: 123 }; const expectedAction = { type: UPDATE_TOKEN_DATA, payload: tokenData, - } + }; - assert.deepStrictEqual(actions.updateTokenData(tokenData), expectedAction) - }) + assert.deepStrictEqual( + actions.updateTokenData(tokenData), + expectedAction, + ); + }); it('should create an action to clear tokenData', function () { const expectedAction = { type: CLEAR_TOKEN_DATA, - } + }; - assert.deepStrictEqual(actions.clearTokenData(), expectedAction) - }) + assert.deepStrictEqual(actions.clearTokenData(), expectedAction); + }); it('should create an action to update methodData', function () { - const methodData = { test: 123 } + const methodData = { test: 123 }; const expectedAction = { type: UPDATE_METHOD_DATA, payload: methodData, - } + }; assert.deepStrictEqual( actions.updateMethodData(methodData), expectedAction, - ) - }) + ); + }); it('should create an action to clear methodData', function () { const expectedAction = { type: CLEAR_METHOD_DATA, - } + }; - assert.deepStrictEqual(actions.clearMethodData(), expectedAction) - }) + assert.deepStrictEqual(actions.clearMethodData(), expectedAction); + }); it('should create an action to update transaction amounts', function () { - const transactionAmounts = { test: 123 } + const transactionAmounts = { test: 123 }; const expectedAction = { type: UPDATE_TRANSACTION_AMOUNTS, payload: transactionAmounts, - } + }; assert.deepStrictEqual( actions.updateTransactionAmounts(transactionAmounts), expectedAction, - ) - }) + ); + }); it('should create an action to update transaction fees', function () { - const transactionFees = { test: 123 } + const transactionFees = { test: 123 }; const expectedAction = { type: UPDATE_TRANSACTION_FEES, payload: transactionFees, - } + }; assert.deepStrictEqual( actions.updateTransactionFees(transactionFees), expectedAction, - ) - }) + ); + }); it('should create an action to update transaction totals', function () { - const transactionTotals = { test: 123 } + const transactionTotals = { test: 123 }; const expectedAction = { type: UPDATE_TRANSACTION_TOTALS, payload: transactionTotals, - } + }; assert.deepStrictEqual( actions.updateTransactionTotals(transactionTotals), expectedAction, - ) - }) + ); + }); it('should create an action to update tokenProps', function () { const tokenProps = { tokenDecimals: '1', tokenSymbol: 'abc', - } + }; const expectedAction = { type: UPDATE_TOKEN_PROPS, payload: tokenProps, - } + }; assert.deepStrictEqual( actions.updateTokenProps(tokenProps), expectedAction, - ) - }) + ); + }); it('should create an action to update nonce', function () { - const nonce = '0x1' + const nonce = '0x1'; const expectedAction = { type: UPDATE_NONCE, payload: nonce, - } + }; - assert.deepStrictEqual(actions.updateNonce(nonce), expectedAction) - }) + assert.deepStrictEqual(actions.updateNonce(nonce), expectedAction); + }); it('should create an action to set fetchingData to true', function () { const expectedAction = { type: FETCH_DATA_START, - } + }; - assert.deepStrictEqual(actions.setFetchingData(true), expectedAction) - }) + assert.deepStrictEqual(actions.setFetchingData(true), expectedAction); + }); it('should create an action to set fetchingData to false', function () { const expectedAction = { type: FETCH_DATA_END, - } + }; - assert.deepStrictEqual(actions.setFetchingData(false), expectedAction) - }) + assert.deepStrictEqual(actions.setFetchingData(false), expectedAction); + }); it('should create an action to clear confirmTransaction', function () { const expectedAction = { type: CLEAR_CONFIRM_TRANSACTION, - } + }; - assert.deepStrictEqual(actions.clearConfirmTransaction(), expectedAction) - }) - }) + assert.deepStrictEqual(actions.clearConfirmTransaction(), expectedAction); + }); + }); describe('Thunk actions', function () { beforeEach(function () { @@ -479,12 +482,12 @@ describe('Confirm Transaction Duck', function () { .callsFake((address) => Promise.resolve(address?.match(/isContract/u) ? 'not-0x' : '0x'), ), - } - }) + }; + }); afterEach(function () { - global.eth.getCode.resetHistory() - }) + global.eth.getCode.resetHistory(); + }); it('updates txData and gas on an existing transaction in confirmTransaction', function () { const mockState = { @@ -518,28 +521,28 @@ describe('Confirm Transaction Duck', function () { time: 1530838113716, }, }, - } + }; - const middlewares = [thunk] - const mockStore = configureMockStore(middlewares) - const store = mockStore(mockState) + const middlewares = [thunk]; + const mockStore = configureMockStore(middlewares); + const store = mockStore(mockState); const expectedActions = [ 'metamask/confirm-transaction/UPDATE_TX_DATA', 'metamask/confirm-transaction/UPDATE_TRANSACTION_AMOUNTS', 'metamask/confirm-transaction/UPDATE_TRANSACTION_FEES', 'metamask/confirm-transaction/UPDATE_TRANSACTION_TOTALS', - ] + ]; store.dispatch( actions.updateGasAndCalculate({ gasLimit: '0x2', gasPrice: '0x25' }), - ) + ); - const storeActions = store.getActions() - assert.strictEqual(storeActions.length, expectedActions.length) + const storeActions = store.getActions(); + assert.strictEqual(storeActions.length, expectedActions.length); storeActions.forEach((action, index) => assert.strictEqual(action.type, expectedActions[index]), - ) - }) + ); + }); it('updates txData and updates gas values in confirmTransaction', function () { const txData = { @@ -557,7 +560,7 @@ describe('Confirm Transaction Duck', function () { to: '0x81b7e08f65bdf5648606c89998a9cc8164397647', value: '0xde0b6b3a7640000', }, - } + }; const mockState = { metamask: { conversionRate: 468.58, @@ -586,26 +589,26 @@ describe('Confirm Transaction Duck', function () { }, }, }, - } + }; - const middlewares = [thunk] - const mockStore = configureMockStore(middlewares) - const store = mockStore(mockState) + const middlewares = [thunk]; + const mockStore = configureMockStore(middlewares); + const store = mockStore(mockState); const expectedActions = [ 'metamask/confirm-transaction/UPDATE_TX_DATA', 'metamask/confirm-transaction/UPDATE_TRANSACTION_AMOUNTS', 'metamask/confirm-transaction/UPDATE_TRANSACTION_FEES', 'metamask/confirm-transaction/UPDATE_TRANSACTION_TOTALS', - ] + ]; - store.dispatch(actions.updateTxDataAndCalculate(txData)) + store.dispatch(actions.updateTxDataAndCalculate(txData)); - const storeActions = store.getActions() - assert.strictEqual(storeActions.length, expectedActions.length) + const storeActions = store.getActions(); + assert.strictEqual(storeActions.length, expectedActions.length); storeActions.forEach((action, index) => assert.strictEqual(action.type, expectedActions[index]), - ) - }) + ); + }); it('updates confirmTransaction transaction', function () { const mockState = { @@ -633,25 +636,25 @@ describe('Confirm Transaction Duck', function () { }, }, confirmTransaction: {}, - } + }; - const middlewares = [thunk] - const mockStore = configureMockStore(middlewares) - const store = mockStore(mockState) + const middlewares = [thunk]; + const mockStore = configureMockStore(middlewares); + const store = mockStore(mockState); const expectedActions = [ 'metamask/confirm-transaction/UPDATE_TX_DATA', 'metamask/confirm-transaction/UPDATE_TRANSACTION_AMOUNTS', 'metamask/confirm-transaction/UPDATE_TRANSACTION_FEES', 'metamask/confirm-transaction/UPDATE_TRANSACTION_TOTALS', - ] + ]; - store.dispatch(actions.setTransactionToConfirm(2603411941761054)) - const storeActions = store.getActions() - assert.strictEqual(storeActions.length, expectedActions.length) + store.dispatch(actions.setTransactionToConfirm(2603411941761054)); + const storeActions = store.getActions(); + assert.strictEqual(storeActions.length, expectedActions.length); storeActions.forEach((action, index) => assert.strictEqual(action.type, expectedActions[index]), - ) - }) - }) -}) + ); + }); + }); +}); diff --git a/ui/app/ducks/gas/gas-duck.test.js b/ui/app/ducks/gas/gas-duck.test.js index 913fb1168..4e7be7956 100644 --- a/ui/app/ducks/gas/gas-duck.test.js +++ b/ui/app/ducks/gas/gas-duck.test.js @@ -1,13 +1,13 @@ -import assert from 'assert' -import nock from 'nock' -import sinon from 'sinon' -import proxyquire from 'proxyquire' +import assert from 'assert'; +import nock from 'nock'; +import sinon from 'sinon'; +import proxyquire from 'proxyquire'; -const fakeStorage = {} +const fakeStorage = {}; const GasDuck = proxyquire('./gas.duck.js', { '../../../lib/storage-helpers': fakeStorage, -}) +}); const { basicGasEstimatesLoadingStarted, @@ -17,34 +17,34 @@ const { setCustomGasLimit, resetCustomGasState, fetchBasicGasEstimates, -} = GasDuck -const GasReducer = GasDuck.default +} = GasDuck; +const GasReducer = GasDuck.default; describe('Gas Duck', function () { - let tempDateNow + let tempDateNow; const mockGasPriceApiResponse = { SafeGasPrice: 10, ProposeGasPrice: 20, FastGasPrice: 30, - } + }; beforeEach(function () { - tempDateNow = global.Date.now + tempDateNow = global.Date.now; - fakeStorage.getStorageItem = sinon.stub() - fakeStorage.setStorageItem = sinon.spy() - global.Date.now = () => 2000000 - }) + fakeStorage.getStorageItem = sinon.stub(); + fakeStorage.setStorageItem = sinon.spy(); + global.Date.now = () => 2000000; + }); afterEach(function () { - sinon.restore() + sinon.restore(); - global.Date.now = tempDateNow - }) + global.Date.now = tempDateNow; + }); const mockState = { mockProp: 123, - } + }; const initState = { customData: { price: null, @@ -57,22 +57,23 @@ describe('Gas Duck', function () { }, basicEstimateIsLoading: true, basicPriceEstimatesLastRetrieved: 0, - } + }; const BASIC_GAS_ESTIMATE_LOADING_FINISHED = - 'metamask/gas/BASIC_GAS_ESTIMATE_LOADING_FINISHED' + 'metamask/gas/BASIC_GAS_ESTIMATE_LOADING_FINISHED'; const BASIC_GAS_ESTIMATE_LOADING_STARTED = - 'metamask/gas/BASIC_GAS_ESTIMATE_LOADING_STARTED' - const RESET_CUSTOM_GAS_STATE = 'metamask/gas/RESET_CUSTOM_GAS_STATE' - const SET_BASIC_GAS_ESTIMATE_DATA = 'metamask/gas/SET_BASIC_GAS_ESTIMATE_DATA' - const SET_CUSTOM_GAS_LIMIT = 'metamask/gas/SET_CUSTOM_GAS_LIMIT' - const SET_CUSTOM_GAS_PRICE = 'metamask/gas/SET_CUSTOM_GAS_PRICE' + 'metamask/gas/BASIC_GAS_ESTIMATE_LOADING_STARTED'; + const RESET_CUSTOM_GAS_STATE = 'metamask/gas/RESET_CUSTOM_GAS_STATE'; + const SET_BASIC_GAS_ESTIMATE_DATA = + 'metamask/gas/SET_BASIC_GAS_ESTIMATE_DATA'; + const SET_CUSTOM_GAS_LIMIT = 'metamask/gas/SET_CUSTOM_GAS_LIMIT'; + const SET_CUSTOM_GAS_PRICE = 'metamask/gas/SET_CUSTOM_GAS_PRICE'; const SET_BASIC_PRICE_ESTIMATES_LAST_RETRIEVED = - 'metamask/gas/SET_BASIC_PRICE_ESTIMATES_LAST_RETRIEVED' + 'metamask/gas/SET_BASIC_PRICE_ESTIMATES_LAST_RETRIEVED'; describe('GasReducer()', function () { it('should initialize state', function () { - assert.deepStrictEqual(GasReducer(undefined, {}), initState) - }) + assert.deepStrictEqual(GasReducer(undefined, {}), initState); + }); it('should return state unchanged if it does not match a dispatched actions type', function () { assert.deepStrictEqual( @@ -81,22 +82,22 @@ describe('Gas Duck', function () { value: 'someValue', }), mockState, - ) - }) + ); + }); it('should set basicEstimateIsLoading to true when receiving a BASIC_GAS_ESTIMATE_LOADING_STARTED action', function () { assert.deepStrictEqual( GasReducer(mockState, { type: BASIC_GAS_ESTIMATE_LOADING_STARTED }), { basicEstimateIsLoading: true, ...mockState }, - ) - }) + ); + }); it('should set basicEstimateIsLoading to false when receiving a BASIC_GAS_ESTIMATE_LOADING_FINISHED action', function () { assert.deepStrictEqual( GasReducer(mockState, { type: BASIC_GAS_ESTIMATE_LOADING_FINISHED }), { basicEstimateIsLoading: false, ...mockState }, - ) - }) + ); + }); it('should set basicEstimates when receiving a SET_BASIC_GAS_ESTIMATE_DATA action', function () { assert.deepStrictEqual( @@ -105,8 +106,8 @@ describe('Gas Duck', function () { value: { someProp: 'someData123' }, }), { basicEstimates: { someProp: 'someData123' }, ...mockState }, - ) - }) + ); + }); it('should set customData.price when receiving a SET_CUSTOM_GAS_PRICE action', function () { assert.deepStrictEqual( @@ -115,8 +116,8 @@ describe('Gas Duck', function () { value: 4321, }), { customData: { price: 4321 }, ...mockState }, - ) - }) + ); + }); it('should set customData.limit when receiving a SET_CUSTOM_GAS_LIMIT action', function () { assert.deepStrictEqual( @@ -125,58 +126,58 @@ describe('Gas Duck', function () { value: 9876, }), { customData: { limit: 9876 }, ...mockState }, - ) - }) + ); + }); it('should return the initial state in response to a RESET_CUSTOM_GAS_STATE action', function () { assert.deepStrictEqual( GasReducer(mockState, { type: RESET_CUSTOM_GAS_STATE }), initState, - ) - }) - }) + ); + }); + }); describe('basicGasEstimatesLoadingStarted', function () { it('should create the correct action', function () { assert.deepStrictEqual(basicGasEstimatesLoadingStarted(), { type: BASIC_GAS_ESTIMATE_LOADING_STARTED, - }) - }) - }) + }); + }); + }); describe('basicGasEstimatesLoadingFinished', function () { it('should create the correct action', function () { assert.deepStrictEqual(basicGasEstimatesLoadingFinished(), { type: BASIC_GAS_ESTIMATE_LOADING_FINISHED, - }) - }) - }) + }); + }); + }); describe('fetchBasicGasEstimates', function () { it('should call fetch with the expected params', async function () { - const mockDistpatch = sinon.spy() + const mockDistpatch = sinon.spy(); - const windowFetchSpy = sinon.spy(window, 'fetch') + const windowFetchSpy = sinon.spy(window, 'fetch'); nock('https://api.metaswap.codefi.network') .get('/gasPrices') - .reply(200, mockGasPriceApiResponse) + .reply(200, mockGasPriceApiResponse); await fetchBasicGasEstimates()(mockDistpatch, () => ({ gas: { ...initState, basicPriceAEstimatesLastRetrieved: 1000000 }, - })) + })); assert.deepStrictEqual(mockDistpatch.getCall(0).args, [ { type: BASIC_GAS_ESTIMATE_LOADING_STARTED }, - ]) + ]); assert.ok( windowFetchSpy .getCall(0) .args[0].startsWith('https://api.metaswap.codefi.network/gasPrices'), 'should fetch metaswap /gasPrices', - ) + ); assert.deepStrictEqual(mockDistpatch.getCall(1).args, [ { type: SET_BASIC_PRICE_ESTIMATES_LAST_RETRIEVED, value: 2000000 }, - ]) + ]); assert.deepStrictEqual(mockDistpatch.getCall(2).args, [ { type: SET_BASIC_GAS_ESTIMATE_DATA, @@ -186,33 +187,33 @@ describe('Gas Duck', function () { safeLow: 10, }, }, - ]) + ]); assert.deepStrictEqual(mockDistpatch.getCall(3).args, [ { type: BASIC_GAS_ESTIMATE_LOADING_FINISHED }, - ]) - }) + ]); + }); it('should fetch recently retrieved estimates from storage', async function () { - const mockDistpatch = sinon.spy() + const mockDistpatch = sinon.spy(); - const windowFetchSpy = sinon.spy(window, 'fetch') + const windowFetchSpy = sinon.spy(window, 'fetch'); fakeStorage.getStorageItem .withArgs('BASIC_PRICE_ESTIMATES_LAST_RETRIEVED') - .returns(2000000 - 1) // one second ago from "now" + .returns(2000000 - 1); // one second ago from "now" fakeStorage.getStorageItem.withArgs('BASIC_PRICE_ESTIMATES').returns({ average: 25, fast: 35, safeLow: 15, - }) + }); await fetchBasicGasEstimates()(mockDistpatch, () => ({ gas: { ...initState }, - })) + })); assert.deepStrictEqual(mockDistpatch.getCall(0).args, [ { type: BASIC_GAS_ESTIMATE_LOADING_STARTED }, - ]) - assert.ok(windowFetchSpy.notCalled) + ]); + assert.ok(windowFetchSpy.notCalled); assert.deepStrictEqual(mockDistpatch.getCall(1).args, [ { type: SET_BASIC_GAS_ESTIMATE_DATA, @@ -222,41 +223,41 @@ describe('Gas Duck', function () { safeLow: 15, }, }, - ]) + ]); assert.deepStrictEqual(mockDistpatch.getCall(2).args, [ { type: BASIC_GAS_ESTIMATE_LOADING_FINISHED }, - ]) - }) + ]); + }); it('should fallback to network if retrieving estimates from storage fails', async function () { - const mockDistpatch = sinon.spy() + const mockDistpatch = sinon.spy(); - const windowFetchSpy = sinon.spy(window, 'fetch') + const windowFetchSpy = sinon.spy(window, 'fetch'); nock('https://api.metaswap.codefi.network') .get('/gasPrices') - .reply(200, mockGasPriceApiResponse) + .reply(200, mockGasPriceApiResponse); fakeStorage.getStorageItem .withArgs('BASIC_PRICE_ESTIMATES_LAST_RETRIEVED') - .returns(2000000 - 1) // one second ago from "now" + .returns(2000000 - 1); // one second ago from "now" await fetchBasicGasEstimates()(mockDistpatch, () => ({ gas: { ...initState }, - })) + })); assert.deepStrictEqual(mockDistpatch.getCall(0).args, [ { type: BASIC_GAS_ESTIMATE_LOADING_STARTED }, - ]) + ]); assert.ok( windowFetchSpy .getCall(0) .args[0].startsWith('https://api.metaswap.codefi.network/gasPrices'), 'should fetch metaswap /gasPrices', - ) + ); assert.deepStrictEqual(mockDistpatch.getCall(1).args, [ { type: SET_BASIC_PRICE_ESTIMATES_LAST_RETRIEVED, value: 2000000 }, - ]) + ]); assert.deepStrictEqual(mockDistpatch.getCall(2).args, [ { type: SET_BASIC_GAS_ESTIMATE_DATA, @@ -266,45 +267,45 @@ describe('Gas Duck', function () { fast: 30, }, }, - ]) + ]); assert.deepStrictEqual(mockDistpatch.getCall(3).args, [ { type: BASIC_GAS_ESTIMATE_LOADING_FINISHED }, - ]) - }) - }) + ]); + }); + }); describe('setBasicGasEstimateData', function () { it('should create the correct action', function () { assert.deepStrictEqual(setBasicGasEstimateData('mockBasicEstimatData'), { type: SET_BASIC_GAS_ESTIMATE_DATA, value: 'mockBasicEstimatData', - }) - }) - }) + }); + }); + }); describe('setCustomGasPrice', function () { it('should create the correct action', function () { assert.deepStrictEqual(setCustomGasPrice('mockCustomGasPrice'), { type: SET_CUSTOM_GAS_PRICE, value: 'mockCustomGasPrice', - }) - }) - }) + }); + }); + }); describe('setCustomGasLimit', function () { it('should create the correct action', function () { assert.deepStrictEqual(setCustomGasLimit('mockCustomGasLimit'), { type: SET_CUSTOM_GAS_LIMIT, value: 'mockCustomGasLimit', - }) - }) - }) + }); + }); + }); describe('resetCustomGasState', function () { it('should create the correct action', function () { assert.deepStrictEqual(resetCustomGasState(), { type: RESET_CUSTOM_GAS_STATE, - }) - }) - }) -}) + }); + }); + }); +}); diff --git a/ui/app/ducks/gas/gas.duck.js b/ui/app/ducks/gas/gas.duck.js index 1bcc5d417..73a621f8f 100644 --- a/ui/app/ducks/gas/gas.duck.js +++ b/ui/app/ducks/gas/gas.duck.js @@ -1,23 +1,23 @@ -import { cloneDeep } from 'lodash' -import BigNumber from 'bignumber.js' -import { getStorageItem, setStorageItem } from '../../../lib/storage-helpers' -import { decGWEIToHexWEI } from '../../helpers/utils/conversions.util' -import getFetchWithTimeout from '../../../../shared/modules/fetch-with-timeout' +import { cloneDeep } from 'lodash'; +import BigNumber from 'bignumber.js'; +import { getStorageItem, setStorageItem } from '../../../lib/storage-helpers'; +import { decGWEIToHexWEI } from '../../helpers/utils/conversions.util'; +import getFetchWithTimeout from '../../../../shared/modules/fetch-with-timeout'; -const fetchWithTimeout = getFetchWithTimeout(30000) +const fetchWithTimeout = getFetchWithTimeout(30000); // Actions const BASIC_GAS_ESTIMATE_LOADING_FINISHED = - 'metamask/gas/BASIC_GAS_ESTIMATE_LOADING_FINISHED' + 'metamask/gas/BASIC_GAS_ESTIMATE_LOADING_FINISHED'; const BASIC_GAS_ESTIMATE_LOADING_STARTED = - 'metamask/gas/BASIC_GAS_ESTIMATE_LOADING_STARTED' -const RESET_CUSTOM_GAS_STATE = 'metamask/gas/RESET_CUSTOM_GAS_STATE' -const RESET_CUSTOM_DATA = 'metamask/gas/RESET_CUSTOM_DATA' -const SET_BASIC_GAS_ESTIMATE_DATA = 'metamask/gas/SET_BASIC_GAS_ESTIMATE_DATA' -const SET_CUSTOM_GAS_LIMIT = 'metamask/gas/SET_CUSTOM_GAS_LIMIT' -const SET_CUSTOM_GAS_PRICE = 'metamask/gas/SET_CUSTOM_GAS_PRICE' + 'metamask/gas/BASIC_GAS_ESTIMATE_LOADING_STARTED'; +const RESET_CUSTOM_GAS_STATE = 'metamask/gas/RESET_CUSTOM_GAS_STATE'; +const RESET_CUSTOM_DATA = 'metamask/gas/RESET_CUSTOM_DATA'; +const SET_BASIC_GAS_ESTIMATE_DATA = 'metamask/gas/SET_BASIC_GAS_ESTIMATE_DATA'; +const SET_CUSTOM_GAS_LIMIT = 'metamask/gas/SET_CUSTOM_GAS_LIMIT'; +const SET_CUSTOM_GAS_PRICE = 'metamask/gas/SET_CUSTOM_GAS_PRICE'; const SET_BASIC_PRICE_ESTIMATES_LAST_RETRIEVED = - 'metamask/gas/SET_BASIC_PRICE_ESTIMATES_LAST_RETRIEVED' + 'metamask/gas/SET_BASIC_PRICE_ESTIMATES_LAST_RETRIEVED'; const initState = { customData: { @@ -31,7 +31,7 @@ const initState = { }, basicEstimateIsLoading: true, basicPriceEstimatesLastRetrieved: 0, -} +}; // Reducer export default function reducer(state = initState, action) { @@ -40,17 +40,17 @@ export default function reducer(state = initState, action) { return { ...state, basicEstimateIsLoading: true, - } + }; case BASIC_GAS_ESTIMATE_LOADING_FINISHED: return { ...state, basicEstimateIsLoading: false, - } + }; case SET_BASIC_GAS_ESTIMATE_DATA: return { ...state, basicEstimates: action.value, - } + }; case SET_CUSTOM_GAS_PRICE: return { ...state, @@ -58,7 +58,7 @@ export default function reducer(state = initState, action) { ...state.customData, price: action.value, }, - } + }; case SET_CUSTOM_GAS_LIMIT: return { ...state, @@ -66,21 +66,21 @@ export default function reducer(state = initState, action) { ...state.customData, limit: action.value, }, - } + }; case SET_BASIC_PRICE_ESTIMATES_LAST_RETRIEVED: return { ...state, basicPriceEstimatesLastRetrieved: action.value, - } + }; case RESET_CUSTOM_DATA: return { ...state, customData: cloneDeep(initState.customData), - } + }; case RESET_CUSTOM_GAS_STATE: - return cloneDeep(initState) + return cloneDeep(initState); default: - return state + return state; } } @@ -88,17 +88,17 @@ export default function reducer(state = initState, action) { export function basicGasEstimatesLoadingStarted() { return { type: BASIC_GAS_ESTIMATE_LOADING_STARTED, - } + }; } export function basicGasEstimatesLoadingFinished() { return { type: BASIC_GAS_ESTIMATE_LOADING_FINISHED, - } + }; } async function basicGasPriceQuery() { - const url = `https://api.metaswap.codefi.network/gasPrices` + const url = `https://api.metaswap.codefi.network/gasPrices`; return await fetchWithTimeout(url, { headers: {}, referrer: 'https://api.metaswap.codefi.network/gasPrices', @@ -106,105 +106,108 @@ async function basicGasPriceQuery() { body: null, method: 'GET', mode: 'cors', - }) + }); } export function fetchBasicGasEstimates() { return async (dispatch, getState) => { - const { basicPriceEstimatesLastRetrieved } = getState().gas + const { basicPriceEstimatesLastRetrieved } = getState().gas; const timeLastRetrieved = basicPriceEstimatesLastRetrieved || (await getStorageItem('BASIC_PRICE_ESTIMATES_LAST_RETRIEVED')) || - 0 + 0; - dispatch(basicGasEstimatesLoadingStarted()) + dispatch(basicGasEstimatesLoadingStarted()); - let basicEstimates + let basicEstimates; if (Date.now() - timeLastRetrieved > 75000) { - basicEstimates = await fetchExternalBasicGasEstimates(dispatch) + basicEstimates = await fetchExternalBasicGasEstimates(dispatch); } else { - const cachedBasicEstimates = await getStorageItem('BASIC_PRICE_ESTIMATES') + const cachedBasicEstimates = await getStorageItem( + 'BASIC_PRICE_ESTIMATES', + ); basicEstimates = - cachedBasicEstimates || (await fetchExternalBasicGasEstimates(dispatch)) + cachedBasicEstimates || + (await fetchExternalBasicGasEstimates(dispatch)); } - dispatch(setBasicGasEstimateData(basicEstimates)) - dispatch(basicGasEstimatesLoadingFinished()) + dispatch(setBasicGasEstimateData(basicEstimates)); + dispatch(basicGasEstimatesLoadingFinished()); - return basicEstimates - } + return basicEstimates; + }; } async function fetchExternalBasicGasEstimates(dispatch) { - const response = await basicGasPriceQuery() + const response = await basicGasPriceQuery(); - const { SafeGasPrice, ProposeGasPrice, FastGasPrice } = await response.json() + const { SafeGasPrice, ProposeGasPrice, FastGasPrice } = await response.json(); const [safeLow, average, fast] = [ SafeGasPrice, ProposeGasPrice, FastGasPrice, - ].map((price) => new BigNumber(price, 10).toNumber()) + ].map((price) => new BigNumber(price, 10).toNumber()); const basicEstimates = { safeLow, average, fast, - } + }; - const timeRetrieved = Date.now() + const timeRetrieved = Date.now(); await Promise.all([ setStorageItem('BASIC_PRICE_ESTIMATES', basicEstimates), setStorageItem('BASIC_PRICE_ESTIMATES_LAST_RETRIEVED', timeRetrieved), - ]) - dispatch(setBasicPriceEstimatesLastRetrieved(timeRetrieved)) + ]); + dispatch(setBasicPriceEstimatesLastRetrieved(timeRetrieved)); - return basicEstimates + return basicEstimates; } export function setCustomGasPriceForRetry(newPrice) { return async (dispatch) => { if (newPrice === '0x0') { - const { fast } = await getStorageItem('BASIC_PRICE_ESTIMATES') - dispatch(setCustomGasPrice(decGWEIToHexWEI(fast))) + const { fast } = await getStorageItem('BASIC_PRICE_ESTIMATES'); + dispatch(setCustomGasPrice(decGWEIToHexWEI(fast))); } else { - dispatch(setCustomGasPrice(newPrice)) + dispatch(setCustomGasPrice(newPrice)); } - } + }; } export function setBasicGasEstimateData(basicGasEstimateData) { return { type: SET_BASIC_GAS_ESTIMATE_DATA, value: basicGasEstimateData, - } + }; } export function setCustomGasPrice(newPrice) { return { type: SET_CUSTOM_GAS_PRICE, value: newPrice, - } + }; } export function setCustomGasLimit(newLimit) { return { type: SET_CUSTOM_GAS_LIMIT, value: newLimit, - } + }; } export function setBasicPriceEstimatesLastRetrieved(retrievalTime) { return { type: SET_BASIC_PRICE_ESTIMATES_LAST_RETRIEVED, value: retrievalTime, - } + }; } export function resetCustomGasState() { - return { type: RESET_CUSTOM_GAS_STATE } + return { type: RESET_CUSTOM_GAS_STATE }; } export function resetCustomData() { - return { type: RESET_CUSTOM_DATA } + return { type: RESET_CUSTOM_DATA }; } diff --git a/ui/app/ducks/history/history.js b/ui/app/ducks/history/history.js index e74576f7f..87fabe204 100644 --- a/ui/app/ducks/history/history.js +++ b/ui/app/ducks/history/history.js @@ -1,14 +1,14 @@ -import { createSlice } from '@reduxjs/toolkit' +import { createSlice } from '@reduxjs/toolkit'; -import { ASSET_ROUTE, DEFAULT_ROUTE } from '../../helpers/constants/routes' +import { ASSET_ROUTE, DEFAULT_ROUTE } from '../../helpers/constants/routes'; // Constants const initialState = { mostRecentOverviewPage: DEFAULT_ROUTE, -} +}; -const name = 'history' +const name = 'history'; // Slice (reducer plus auto-generated actions and action creators) @@ -17,23 +17,23 @@ const slice = createSlice({ initialState, reducers: { pageChanged: (state, action) => { - const path = action.payload + const path = action.payload; if (path === DEFAULT_ROUTE || path.startsWith(ASSET_ROUTE)) { - state.mostRecentOverviewPage = path + state.mostRecentOverviewPage = path; } }, }, -}) +}); -const { actions, reducer } = slice +const { actions, reducer } = slice; -export default reducer +export default reducer; // Selectors export const getMostRecentOverviewPage = (state) => - state[name].mostRecentOverviewPage + state[name].mostRecentOverviewPage; // Actions / action-creators -export const { pageChanged } = actions +export const { pageChanged } = actions; diff --git a/ui/app/ducks/index.js b/ui/app/ducks/index.js index 42fccab06..4782acc48 100644 --- a/ui/app/ducks/index.js +++ b/ui/app/ducks/index.js @@ -1,14 +1,14 @@ -import { combineReducers } from 'redux' -import { ALERT_TYPES } from '../../../shared/constants/alerts' -import metamaskReducer from './metamask/metamask' -import localeMessagesReducer from './locale/locale' -import sendReducer from './send/send.duck' -import appStateReducer from './app/app' -import confirmTransactionReducer from './confirm-transaction/confirm-transaction.duck' -import gasReducer from './gas/gas.duck' -import { invalidCustomNetwork, unconnectedAccount } from './alerts' -import swapsReducer from './swaps/swaps' -import historyReducer from './history/history' +import { combineReducers } from 'redux'; +import { ALERT_TYPES } from '../../../shared/constants/alerts'; +import metamaskReducer from './metamask/metamask'; +import localeMessagesReducer from './locale/locale'; +import sendReducer from './send/send.duck'; +import appStateReducer from './app/app'; +import confirmTransactionReducer from './confirm-transaction/confirm-transaction.duck'; +import gasReducer from './gas/gas.duck'; +import { invalidCustomNetwork, unconnectedAccount } from './alerts'; +import swapsReducer from './swaps/swaps'; +import historyReducer from './history/history'; export default combineReducers({ [ALERT_TYPES.invalidCustomNetwork]: invalidCustomNetwork, @@ -22,4 +22,4 @@ export default combineReducers({ swaps: swapsReducer, gas: gasReducer, localeMessages: localeMessagesReducer, -}) +}); diff --git a/ui/app/ducks/locale/locale.js b/ui/app/ducks/locale/locale.js index e7f14c40a..88976e62f 100644 --- a/ui/app/ducks/locale/locale.js +++ b/ui/app/ducks/locale/locale.js @@ -1,4 +1,4 @@ -import * as actionConstants from '../../store/actionConstants' +import * as actionConstants from '../../store/actionConstants'; export default function reduceLocaleMessages(state = {}, { type, value }) { switch (type) { @@ -6,12 +6,12 @@ export default function reduceLocaleMessages(state = {}, { type, value }) { return { ...state, current: value.messages, - } + }; default: - return state + return state; } } -export const getCurrentLocaleMessages = (state) => state.localeMessages.current +export const getCurrentLocaleMessages = (state) => state.localeMessages.current; -export const getEnLocaleMessages = (state) => state.localeMessages.en +export const getEnLocaleMessages = (state) => state.localeMessages.en; diff --git a/ui/app/ducks/metamask/metamask.js b/ui/app/ducks/metamask/metamask.js index cdc644a02..31c808877 100644 --- a/ui/app/ducks/metamask/metamask.js +++ b/ui/app/ducks/metamask/metamask.js @@ -1,6 +1,6 @@ -import * as actionConstants from '../../store/actionConstants' -import { ALERT_TYPES } from '../../../../shared/constants/alerts' -import { NETWORK_TYPE_RPC } from '../../../../shared/constants/network' +import * as actionConstants from '../../store/actionConstants'; +import { ALERT_TYPES } from '../../../../shared/constants/alerts'; +import { NETWORK_TYPE_RPC } from '../../../../shared/constants/network'; export default function reduceMetamask(state = {}, action) { const metamaskState = { @@ -48,17 +48,17 @@ export default function reduceMetamask(state = {}, action) { metaMetricsSendCount: 0, nextNonce: null, ...state, - } + }; switch (action.type) { case actionConstants.UPDATE_METAMASK_STATE: - return { ...metamaskState, ...action.value } + return { ...metamaskState, ...action.value }; case actionConstants.LOCK_METAMASK: return { ...metamaskState, isUnlocked: false, - } + }; case actionConstants.SET_RPC_TARGET: return { @@ -67,7 +67,7 @@ export default function reduceMetamask(state = {}, action) { type: NETWORK_TYPE_RPC, rpcUrl: action.value, }, - } + }; case actionConstants.SET_PROVIDER_TYPE: return { @@ -75,7 +75,7 @@ export default function reduceMetamask(state = {}, action) { provider: { type: action.value, }, - } + }; case actionConstants.SHOW_ACCOUNT_DETAIL: return { @@ -83,15 +83,15 @@ export default function reduceMetamask(state = {}, action) { isUnlocked: true, isInitialized: true, selectedAddress: action.value, - } + }; case actionConstants.SET_ACCOUNT_LABEL: { - const { account } = action.value - const name = action.value.label - const id = {} - id[account] = { ...metamaskState.identities[account], name } - const identities = { ...metamaskState.identities, ...id } - return Object.assign(metamaskState, { identities }) + const { account } = action.value; + const name = action.value.label; + const id = {}; + id[account] = { ...metamaskState.identities[account], name }; + const identities = { ...metamaskState.identities, ...id }; + return Object.assign(metamaskState, { identities }); } case actionConstants.SET_CURRENT_FIAT: @@ -99,13 +99,13 @@ export default function reduceMetamask(state = {}, action) { currentCurrency: action.value.currentCurrency, conversionRate: action.value.conversionRate, conversionDate: action.value.conversionDate, - }) + }); case actionConstants.UPDATE_TOKENS: return { ...metamaskState, tokens: action.newTokens, - } + }; // metamask.send case actionConstants.UPDATE_GAS_LIMIT: @@ -115,12 +115,12 @@ export default function reduceMetamask(state = {}, action) { ...metamaskState.send, gasLimit: action.value, }, - } + }; case actionConstants.UPDATE_CUSTOM_NONCE: return { ...metamaskState, customNonceValue: action.value, - } + }; case actionConstants.UPDATE_GAS_PRICE: return { ...metamaskState, @@ -128,13 +128,13 @@ export default function reduceMetamask(state = {}, action) { ...metamaskState.send, gasPrice: action.value, }, - } + }; case actionConstants.TOGGLE_ACCOUNT_MENU: return { ...metamaskState, isAccountMenuOpen: !metamaskState.isAccountMenuOpen, - } + }; case actionConstants.UPDATE_GAS_TOTAL: return { @@ -143,7 +143,7 @@ export default function reduceMetamask(state = {}, action) { ...metamaskState.send, gasTotal: action.value, }, - } + }; case actionConstants.UPDATE_SEND_TOKEN_BALANCE: return { @@ -152,7 +152,7 @@ export default function reduceMetamask(state = {}, action) { ...metamaskState.send, tokenBalance: action.value, }, - } + }; case actionConstants.UPDATE_SEND_HEX_DATA: return { @@ -161,7 +161,7 @@ export default function reduceMetamask(state = {}, action) { ...metamaskState.send, data: action.value, }, - } + }; case actionConstants.UPDATE_SEND_TO: return { @@ -171,7 +171,7 @@ export default function reduceMetamask(state = {}, action) { to: action.value.to, toNickname: action.value.nickname, }, - } + }; case actionConstants.UPDATE_SEND_AMOUNT: return { @@ -180,7 +180,7 @@ export default function reduceMetamask(state = {}, action) { ...metamaskState.send, amount: action.value, }, - } + }; case actionConstants.UPDATE_MAX_MODE: return { @@ -189,7 +189,7 @@ export default function reduceMetamask(state = {}, action) { ...metamaskState.send, maxModeOn: action.value, }, - } + }; case actionConstants.UPDATE_SEND: return Object.assign(metamaskState, { @@ -197,18 +197,18 @@ export default function reduceMetamask(state = {}, action) { ...metamaskState.send, ...action.value, }, - }) + }); case actionConstants.UPDATE_SEND_TOKEN: { const newSend = { ...metamaskState.send, token: action.value, - } + }; // erase token-related state when switching back to native currency if (newSend.editingTransactionId && !newSend.token) { const unapprovedTx = - newSend?.unapprovedTxs?.[newSend.editingTransactionId] || {} - const txParams = unapprovedTx.txParams || {} + newSend?.unapprovedTxs?.[newSend.editingTransactionId] || {}; + const txParams = unapprovedTx.txParams || {}; Object.assign(newSend, { tokenBalance: null, balance: '0', @@ -223,11 +223,11 @@ export default function reduceMetamask(state = {}, action) { }, }, }, - }) + }); } return Object.assign(metamaskState, { send: newSend, - }) + }); } case actionConstants.UPDATE_SEND_ENS_RESOLUTION: @@ -238,7 +238,7 @@ export default function reduceMetamask(state = {}, action) { ensResolution: action.payload, ensResolutionError: '', }, - } + }; case actionConstants.UPDATE_SEND_ENS_RESOLUTION_ERROR: return { @@ -248,7 +248,7 @@ export default function reduceMetamask(state = {}, action) { ensResolution: null, ensResolutionError: action.payload, }, - } + }; case actionConstants.CLEAR_SEND: return { @@ -267,73 +267,73 @@ export default function reduceMetamask(state = {}, action) { editingTransactionId: null, toNickname: '', }, - } + }; case actionConstants.UPDATE_TRANSACTION_PARAMS: { - const { id: txId, value } = action - let { currentNetworkTxList } = metamaskState + const { id: txId, value } = action; + let { currentNetworkTxList } = metamaskState; currentNetworkTxList = currentNetworkTxList.map((tx) => { if (tx.id === txId) { - const newTx = { ...tx } - newTx.txParams = value - return newTx + const newTx = { ...tx }; + newTx.txParams = value; + return newTx; } - return tx - }) + return tx; + }); return { ...metamaskState, currentNetworkTxList, - } + }; } case actionConstants.SET_PARTICIPATE_IN_METAMETRICS: return { ...metamaskState, participateInMetaMetrics: action.value, - } + }; case actionConstants.SET_METAMETRICS_SEND_COUNT: return { ...metamaskState, metaMetricsSendCount: action.value, - } + }; case actionConstants.SET_USE_BLOCKIE: return { ...metamaskState, useBlockie: action.value, - } + }; case actionConstants.UPDATE_FEATURE_FLAGS: return { ...metamaskState, featureFlags: action.value, - } + }; case actionConstants.CLOSE_WELCOME_SCREEN: return { ...metamaskState, welcomeScreenSeen: true, - } + }; case actionConstants.SET_CURRENT_LOCALE: return { ...metamaskState, currentLocale: action.value.locale, - } + }; case actionConstants.SET_PENDING_TOKENS: return { ...metamaskState, pendingTokens: { ...action.payload }, - } + }; case actionConstants.CLEAR_PENDING_TOKENS: { return { ...metamaskState, pendingTokens: {}, - } + }; } case actionConstants.UPDATE_PREFERENCES: { @@ -343,46 +343,46 @@ export default function reduceMetamask(state = {}, action) { ...metamaskState.preferences, ...action.payload, }, - } + }; } case actionConstants.COMPLETE_ONBOARDING: { return { ...metamaskState, completedOnboarding: true, - } + }; } case actionConstants.SET_FIRST_TIME_FLOW_TYPE: { return { ...metamaskState, firstTimeFlowType: action.value, - } + }; } case actionConstants.SET_NEXT_NONCE: { return { ...metamaskState, nextNonce: action.value, - } + }; } default: - return metamaskState + return metamaskState; } } -export const getCurrentLocale = (state) => state.metamask.currentLocale +export const getCurrentLocale = (state) => state.metamask.currentLocale; -export const getAlertEnabledness = (state) => state.metamask.alertEnabledness +export const getAlertEnabledness = (state) => state.metamask.alertEnabledness; export const getUnconnectedAccountAlertEnabledness = (state) => - getAlertEnabledness(state)[ALERT_TYPES.unconnectedAccount] + getAlertEnabledness(state)[ALERT_TYPES.unconnectedAccount]; export const getWeb3ShimUsageAlertEnabledness = (state) => - getAlertEnabledness(state)[ALERT_TYPES.web3ShimUsage] + getAlertEnabledness(state)[ALERT_TYPES.web3ShimUsage]; export const getUnconnectedAccountAlertShown = (state) => - state.metamask.unconnectedAccountAlertShownOrigins + state.metamask.unconnectedAccountAlertShownOrigins; -export const getTokens = (state) => state.metamask.tokens +export const getTokens = (state) => state.metamask.tokens; diff --git a/ui/app/ducks/send/send-duck.test.js b/ui/app/ducks/send/send-duck.test.js index 2d123fb01..3f24b7ece 100644 --- a/ui/app/ducks/send/send-duck.test.js +++ b/ui/app/ducks/send/send-duck.test.js @@ -1,4 +1,4 @@ -import assert from 'assert' +import assert from 'assert'; import SendReducer, { openToDropdown, @@ -6,28 +6,28 @@ import SendReducer, { updateSendErrors, showGasButtonGroup, hideGasButtonGroup, -} from './send.duck' +} from './send.duck'; describe('Send Duck', function () { const mockState = { mockProp: 123, - } + }; const initState = { toDropdownOpen: false, errors: {}, gasButtonGroupShown: true, - } - const OPEN_TO_DROPDOWN = 'metamask/send/OPEN_TO_DROPDOWN' - const CLOSE_TO_DROPDOWN = 'metamask/send/CLOSE_TO_DROPDOWN' - const UPDATE_SEND_ERRORS = 'metamask/send/UPDATE_SEND_ERRORS' - const RESET_SEND_STATE = 'metamask/send/RESET_SEND_STATE' - const SHOW_GAS_BUTTON_GROUP = 'metamask/send/SHOW_GAS_BUTTON_GROUP' - const HIDE_GAS_BUTTON_GROUP = 'metamask/send/HIDE_GAS_BUTTON_GROUP' + }; + const OPEN_TO_DROPDOWN = 'metamask/send/OPEN_TO_DROPDOWN'; + const CLOSE_TO_DROPDOWN = 'metamask/send/CLOSE_TO_DROPDOWN'; + const UPDATE_SEND_ERRORS = 'metamask/send/UPDATE_SEND_ERRORS'; + const RESET_SEND_STATE = 'metamask/send/RESET_SEND_STATE'; + const SHOW_GAS_BUTTON_GROUP = 'metamask/send/SHOW_GAS_BUTTON_GROUP'; + const HIDE_GAS_BUTTON_GROUP = 'metamask/send/HIDE_GAS_BUTTON_GROUP'; describe('SendReducer()', function () { it('should initialize state', function () { - assert.deepStrictEqual(SendReducer(undefined, {}), initState) - }) + assert.deepStrictEqual(SendReducer(undefined, {}), initState); + }); it('should return state unchanged if it does not match a dispatched actions type', function () { assert.deepStrictEqual( @@ -36,8 +36,8 @@ describe('Send Duck', function () { value: 'someValue', }), mockState, - ) - }) + ); + }); it('should set toDropdownOpen to true when receiving a OPEN_TO_DROPDOWN action', function () { assert.deepStrictEqual( @@ -45,8 +45,8 @@ describe('Send Duck', function () { type: OPEN_TO_DROPDOWN, }), { toDropdownOpen: true, ...mockState }, - ) - }) + ); + }); it('should set toDropdownOpen to false when receiving a CLOSE_TO_DROPDOWN action', function () { assert.deepStrictEqual( @@ -54,8 +54,8 @@ describe('Send Duck', function () { type: CLOSE_TO_DROPDOWN, }), { toDropdownOpen: false, ...mockState }, - ) - }) + ); + }); it('should set gasButtonGroupShown to true when receiving a SHOW_GAS_BUTTON_GROUP action', function () { assert.deepStrictEqual( @@ -64,15 +64,15 @@ describe('Send Duck', function () { { type: SHOW_GAS_BUTTON_GROUP }, ), { gasButtonGroupShown: true, ...mockState }, - ) - }) + ); + }); it('should set gasButtonGroupShown to false when receiving a HIDE_GAS_BUTTON_GROUP action', function () { assert.deepStrictEqual( SendReducer(mockState, { type: HIDE_GAS_BUTTON_GROUP }), { gasButtonGroupShown: false, ...mockState }, - ) - }) + ); + }); it('should extend send.errors with the value of a UPDATE_SEND_ERRORS action', function () { const modifiedMockState = { @@ -80,7 +80,7 @@ describe('Send Duck', function () { errors: { someError: false, }, - } + }; assert.deepStrictEqual( SendReducer(modifiedMockState, { type: UPDATE_SEND_ERRORS, @@ -93,8 +93,8 @@ describe('Send Duck', function () { someOtherError: true, }, }, - ) - }) + ); + }); it('should return the initial state in response to a RESET_SEND_STATE action', function () { assert.deepStrictEqual( @@ -102,34 +102,34 @@ describe('Send Duck', function () { type: RESET_SEND_STATE, }), initState, - ) - }) - }) + ); + }); + }); describe('openToDropdown', function () { - assert.deepStrictEqual(openToDropdown(), { type: OPEN_TO_DROPDOWN }) - }) + assert.deepStrictEqual(openToDropdown(), { type: OPEN_TO_DROPDOWN }); + }); describe('closeToDropdown', function () { - assert.deepStrictEqual(closeToDropdown(), { type: CLOSE_TO_DROPDOWN }) - }) + assert.deepStrictEqual(closeToDropdown(), { type: CLOSE_TO_DROPDOWN }); + }); describe('showGasButtonGroup', function () { assert.deepStrictEqual(showGasButtonGroup(), { type: SHOW_GAS_BUTTON_GROUP, - }) - }) + }); + }); describe('hideGasButtonGroup', function () { assert.deepStrictEqual(hideGasButtonGroup(), { type: HIDE_GAS_BUTTON_GROUP, - }) - }) + }); + }); describe('updateSendErrors', function () { assert.deepStrictEqual(updateSendErrors('mockErrorObject'), { type: UPDATE_SEND_ERRORS, value: 'mockErrorObject', - }) - }) -}) + }); + }); +}); diff --git a/ui/app/ducks/send/send.duck.js b/ui/app/ducks/send/send.duck.js index c5202d442..b8d974457 100644 --- a/ui/app/ducks/send/send.duck.js +++ b/ui/app/ducks/send/send.duck.js @@ -1,16 +1,16 @@ // Actions -const OPEN_TO_DROPDOWN = 'metamask/send/OPEN_TO_DROPDOWN' -const CLOSE_TO_DROPDOWN = 'metamask/send/CLOSE_TO_DROPDOWN' -const UPDATE_SEND_ERRORS = 'metamask/send/UPDATE_SEND_ERRORS' -const RESET_SEND_STATE = 'metamask/send/RESET_SEND_STATE' -const SHOW_GAS_BUTTON_GROUP = 'metamask/send/SHOW_GAS_BUTTON_GROUP' -const HIDE_GAS_BUTTON_GROUP = 'metamask/send/HIDE_GAS_BUTTON_GROUP' +const OPEN_TO_DROPDOWN = 'metamask/send/OPEN_TO_DROPDOWN'; +const CLOSE_TO_DROPDOWN = 'metamask/send/CLOSE_TO_DROPDOWN'; +const UPDATE_SEND_ERRORS = 'metamask/send/UPDATE_SEND_ERRORS'; +const RESET_SEND_STATE = 'metamask/send/RESET_SEND_STATE'; +const SHOW_GAS_BUTTON_GROUP = 'metamask/send/SHOW_GAS_BUTTON_GROUP'; +const HIDE_GAS_BUTTON_GROUP = 'metamask/send/HIDE_GAS_BUTTON_GROUP'; const initState = { toDropdownOpen: false, gasButtonGroupShown: true, errors: {}, -} +}; // Reducer export default function reducer(state = initState, action) { @@ -19,12 +19,12 @@ export default function reducer(state = initState, action) { return { ...state, toDropdownOpen: true, - } + }; case CLOSE_TO_DROPDOWN: return { ...state, toDropdownOpen: false, - } + }; case UPDATE_SEND_ERRORS: return { ...state, @@ -32,48 +32,48 @@ export default function reducer(state = initState, action) { ...state.errors, ...action.value, }, - } + }; case SHOW_GAS_BUTTON_GROUP: return { ...state, gasButtonGroupShown: true, - } + }; case HIDE_GAS_BUTTON_GROUP: return { ...state, gasButtonGroupShown: false, - } + }; case RESET_SEND_STATE: - return { ...initState } + return { ...initState }; default: - return state + return state; } } // Action Creators export function openToDropdown() { - return { type: OPEN_TO_DROPDOWN } + return { type: OPEN_TO_DROPDOWN }; } export function closeToDropdown() { - return { type: CLOSE_TO_DROPDOWN } + return { type: CLOSE_TO_DROPDOWN }; } export function showGasButtonGroup() { - return { type: SHOW_GAS_BUTTON_GROUP } + return { type: SHOW_GAS_BUTTON_GROUP }; } export function hideGasButtonGroup() { - return { type: HIDE_GAS_BUTTON_GROUP } + return { type: HIDE_GAS_BUTTON_GROUP }; } export function updateSendErrors(errorObject) { return { type: UPDATE_SEND_ERRORS, value: errorObject, - } + }; } export function resetSendState() { - return { type: RESET_SEND_STATE } + return { type: RESET_SEND_STATE }; } diff --git a/ui/app/ducks/swaps/swaps.js b/ui/app/ducks/swaps/swaps.js index d67e8c994..f59f20639 100644 --- a/ui/app/ducks/swaps/swaps.js +++ b/ui/app/ducks/swaps/swaps.js @@ -1,8 +1,8 @@ -import { createSlice } from '@reduxjs/toolkit' -import BigNumber from 'bignumber.js' -import log from 'loglevel' +import { createSlice } from '@reduxjs/toolkit'; +import BigNumber from 'bignumber.js'; +import log from 'loglevel'; -import { getStorageItem, setStorageItem } from '../../../lib/storage-helpers' +import { getStorageItem, setStorageItem } from '../../../lib/storage-helpers'; import { addToken, @@ -24,50 +24,50 @@ import { setSelectedQuoteAggId, setSwapsTxGasLimit, cancelTx, -} from '../../store/actions' +} from '../../store/actions'; import { AWAITING_SWAP_ROUTE, BUILD_QUOTE_ROUTE, LOADING_QUOTES_ROUTE, SWAPS_ERROR_ROUTE, SWAPS_MAINTENANCE_ROUTE, -} from '../../helpers/constants/routes' +} from '../../helpers/constants/routes'; import { fetchSwapsFeatureLiveness, fetchSwapsGasPrices, -} from '../../pages/swaps/swaps.util' -import { calcGasTotal } from '../../pages/send/send.utils' +} from '../../pages/swaps/swaps.util'; +import { calcGasTotal } from '../../pages/send/send.utils'; import { decimalToHex, getValueFromWeiHex, decGWEIToHexWEI, hexToDecimal, hexWEIToDecGWEI, -} from '../../helpers/utils/conversions.util' -import { conversionLessThan } from '../../helpers/utils/conversion-util' -import { calcTokenAmount } from '../../helpers/utils/token-util' +} from '../../helpers/utils/conversions.util'; +import { conversionLessThan } from '../../helpers/utils/conversion-util'; +import { calcTokenAmount } from '../../helpers/utils/token-util'; import { getSelectedAccount, getTokenExchangeRates, getUSDConversionRate, -} from '../../selectors' +} from '../../selectors'; import { ERROR_FETCHING_QUOTES, QUOTES_NOT_AVAILABLE_ERROR, ETH_SWAPS_TOKEN_OBJECT, SWAP_FAILED_ERROR, SWAPS_FETCH_ORDER_CONFLICT, -} from '../../helpers/constants/swaps' -import { TRANSACTION_CATEGORIES } from '../../../../shared/constants/transaction' +} from '../../helpers/constants/swaps'; +import { TRANSACTION_CATEGORIES } from '../../../../shared/constants/transaction'; const GAS_PRICES_LOADING_STATES = { INITIAL: 'INITIAL', LOADING: 'LOADING', FAILED: 'FAILED', COMPLETED: 'COMPLETED', -} +}; -export const FALLBACK_GAS_MULTIPLIER = 1.5 +export const FALLBACK_GAS_MULTIPLIER = 1.5; const initialState = { aggregatorMetadata: null, @@ -86,7 +86,7 @@ const initialState = { priceEstimatesLastRetrieved: 0, fallBackPrice: null, }, -} +}; const slice = createSlice({ name: 'swaps', @@ -94,115 +94,115 @@ const slice = createSlice({ reducers: { clearSwapsState: () => initialState, navigatedBackToBuildQuote: (state) => { - state.approveTxId = null - state.balanceError = false - state.fetchingQuotes = false - state.customGas.limit = null - state.customGas.price = null + state.approveTxId = null; + state.balanceError = false; + state.fetchingQuotes = false; + state.customGas.limit = null; + state.customGas.price = null; }, retriedGetQuotes: (state) => { - state.approveTxId = null - state.balanceError = false - state.fetchingQuotes = false + state.approveTxId = null; + state.balanceError = false; + state.fetchingQuotes = false; }, setAggregatorMetadata: (state, action) => { - state.aggregatorMetadata = action.payload + state.aggregatorMetadata = action.payload; }, setBalanceError: (state, action) => { - state.balanceError = action.payload + state.balanceError = action.payload; }, setFetchingQuotes: (state, action) => { - state.fetchingQuotes = action.payload + state.fetchingQuotes = action.payload; }, setFromToken: (state, action) => { - state.fromToken = action.payload + state.fromToken = action.payload; }, setQuotesFetchStartTime: (state, action) => { - state.quotesFetchStartTime = action.payload + state.quotesFetchStartTime = action.payload; }, setTopAssets: (state, action) => { - state.topAssets = action.payload + state.topAssets = action.payload; }, setToToken: (state, action) => { - state.toToken = action.payload + state.toToken = action.payload; }, swapCustomGasModalClosed: (state) => { - state.customGas.price = null - state.customGas.limit = null + state.customGas.price = null; + state.customGas.limit = null; }, swapCustomGasModalPriceEdited: (state, action) => { - state.customGas.price = action.payload + state.customGas.price = action.payload; }, swapCustomGasModalLimitEdited: (state, action) => { - state.customGas.limit = action.payload + state.customGas.limit = action.payload; }, swapGasPriceEstimatesFetchStarted: (state) => { - state.customGas.loading = GAS_PRICES_LOADING_STATES.LOADING + state.customGas.loading = GAS_PRICES_LOADING_STATES.LOADING; }, swapGasPriceEstimatesFetchFailed: (state) => { - state.customGas.loading = GAS_PRICES_LOADING_STATES.FAILED + state.customGas.loading = GAS_PRICES_LOADING_STATES.FAILED; }, swapGasPriceEstimatesFetchCompleted: (state, action) => { - state.customGas.priceEstimates = action.payload.priceEstimates - state.customGas.loading = GAS_PRICES_LOADING_STATES.COMPLETED + state.customGas.priceEstimates = action.payload.priceEstimates; + state.customGas.loading = GAS_PRICES_LOADING_STATES.COMPLETED; state.customGas.priceEstimatesLastRetrieved = - action.payload.priceEstimatesLastRetrieved + action.payload.priceEstimatesLastRetrieved; }, retrievedFallbackSwapsGasPrice: (state, action) => { - state.customGas.fallBackPrice = action.payload + state.customGas.fallBackPrice = action.payload; }, }, -}) +}); -const { actions, reducer } = slice +const { actions, reducer } = slice; -export default reducer +export default reducer; // Selectors -export const getAggregatorMetadata = (state) => state.swaps.aggregatorMetadata +export const getAggregatorMetadata = (state) => state.swaps.aggregatorMetadata; -export const getBalanceError = (state) => state.swaps.balanceError +export const getBalanceError = (state) => state.swaps.balanceError; -export const getFromToken = (state) => state.swaps.fromToken +export const getFromToken = (state) => state.swaps.fromToken; -export const getTopAssets = (state) => state.swaps.topAssets +export const getTopAssets = (state) => state.swaps.topAssets; -export const getToToken = (state) => state.swaps.toToken +export const getToToken = (state) => state.swaps.toToken; -export const getFetchingQuotes = (state) => state.swaps.fetchingQuotes +export const getFetchingQuotes = (state) => state.swaps.fetchingQuotes; export const getQuotesFetchStartTime = (state) => - state.swaps.quotesFetchStartTime + state.swaps.quotesFetchStartTime; export const getSwapsCustomizationModalPrice = (state) => - state.swaps.customGas.price + state.swaps.customGas.price; export const getSwapsCustomizationModalLimit = (state) => - state.swaps.customGas.limit + state.swaps.customGas.limit; export const swapGasPriceEstimateIsLoading = (state) => - state.swaps.customGas.loading === GAS_PRICES_LOADING_STATES.LOADING + state.swaps.customGas.loading === GAS_PRICES_LOADING_STATES.LOADING; export const swapGasEstimateLoadingHasFailed = (state) => - state.swaps.customGas.loading === GAS_PRICES_LOADING_STATES.INITIAL + state.swaps.customGas.loading === GAS_PRICES_LOADING_STATES.INITIAL; export const getSwapGasPriceEstimateData = (state) => - state.swaps.customGas.priceEstimates + state.swaps.customGas.priceEstimates; export const getSwapsPriceEstimatesLastRetrieved = (state) => - state.swaps.customGas.priceEstimatesLastRetrieved + state.swaps.customGas.priceEstimatesLastRetrieved; export const getSwapsFallbackGasPrice = (state) => - state.swaps.customGas.fallBackPrice + state.swaps.customGas.fallBackPrice; export function shouldShowCustomPriceTooLowWarning(state) { - const { average } = getSwapGasPriceEstimateData(state) + const { average } = getSwapGasPriceEstimateData(state); - const customGasPrice = getSwapsCustomizationModalPrice(state) + const customGasPrice = getSwapsCustomizationModalPrice(state); if (!customGasPrice || average === undefined) { - return false + return false; } const customPriceRisksSwapFailure = conversionLessThan( @@ -213,83 +213,84 @@ export function shouldShowCustomPriceTooLowWarning(state) { toDenomination: 'GWEI', }, { value: average, fromNumericBase: 'dec' }, - ) + ); - return customPriceRisksSwapFailure + return customPriceRisksSwapFailure; } // Background selectors -const getSwapsState = (state) => state.metamask.swapsState +const getSwapsState = (state) => state.metamask.swapsState; export const getSwapsFeatureLiveness = (state) => - state.metamask.swapsState.swapsFeatureIsLive + state.metamask.swapsState.swapsFeatureIsLive; export const getSwapsQuoteRefreshTime = (state) => - state.metamask.swapsState.swapsQuoteRefreshTime + state.metamask.swapsState.swapsQuoteRefreshTime; export const getBackgroundSwapRouteState = (state) => - state.metamask.swapsState.routeState + state.metamask.swapsState.routeState; export const getCustomSwapsGas = (state) => - state.metamask.swapsState.customMaxGas + state.metamask.swapsState.customMaxGas; export const getCustomSwapsGasPrice = (state) => - state.metamask.swapsState.customGasPrice + state.metamask.swapsState.customGasPrice; -export const getFetchParams = (state) => state.metamask.swapsState.fetchParams +export const getFetchParams = (state) => state.metamask.swapsState.fetchParams; -export const getQuotes = (state) => state.metamask.swapsState.quotes +export const getQuotes = (state) => state.metamask.swapsState.quotes; export const getQuotesLastFetched = (state) => - state.metamask.swapsState.quotesLastFetched + state.metamask.swapsState.quotesLastFetched; export const getSelectedQuote = (state) => { - const { selectedAggId, quotes } = getSwapsState(state) - return quotes[selectedAggId] -} + const { selectedAggId, quotes } = getSwapsState(state); + return quotes[selectedAggId]; +}; -export const getSwapsErrorKey = (state) => getSwapsState(state)?.errorKey +export const getSwapsErrorKey = (state) => getSwapsState(state)?.errorKey; export const getShowQuoteLoadingScreen = (state) => - state.swaps.showQuoteLoadingScreen + state.swaps.showQuoteLoadingScreen; -export const getSwapsTokens = (state) => state.metamask.swapsState.tokens +export const getSwapsTokens = (state) => state.metamask.swapsState.tokens; export const getSwapsWelcomeMessageSeenStatus = (state) => - state.metamask.swapsWelcomeMessageHasBeenShown + state.metamask.swapsWelcomeMessageHasBeenShown; export const getTopQuote = (state) => { - const { topAggId, quotes } = getSwapsState(state) - return quotes[topAggId] -} + const { topAggId, quotes } = getSwapsState(state); + return quotes[topAggId]; +}; -export const getApproveTxId = (state) => state.metamask.swapsState.approveTxId +export const getApproveTxId = (state) => state.metamask.swapsState.approveTxId; -export const getTradeTxId = (state) => state.metamask.swapsState.tradeTxId +export const getTradeTxId = (state) => state.metamask.swapsState.tradeTxId; export const getUsedQuote = (state) => - getSelectedQuote(state) || getTopQuote(state) + getSelectedQuote(state) || getTopQuote(state); // Compound selectors export const getDestinationTokenInfo = (state) => - getFetchParams(state)?.metaData?.destinationTokenInfo + getFetchParams(state)?.metaData?.destinationTokenInfo; export const getUsedSwapsGasPrice = (state) => - getCustomSwapsGasPrice(state) || getSwapsFallbackGasPrice(state) + getCustomSwapsGasPrice(state) || getSwapsFallbackGasPrice(state); export const getApproveTxParams = (state) => { - const { approvalNeeded } = getSelectedQuote(state) || getTopQuote(state) || {} + const { approvalNeeded } = + getSelectedQuote(state) || getTopQuote(state) || {}; if (!approvalNeeded) { - return null + return null; } - const data = getSwapsState(state)?.customApproveTxData || approvalNeeded.data + const data = getSwapsState(state)?.customApproveTxData || approvalNeeded.data; - const gasPrice = getCustomSwapsGasPrice(state) || approvalNeeded.gasPrice - return { ...approvalNeeded, gasPrice, data } -} + const gasPrice = getCustomSwapsGasPrice(state) || approvalNeeded.gasPrice; + return { ...approvalNeeded, gasPrice, data }; +}; // Actions / action-creators @@ -311,7 +312,7 @@ const { swapCustomGasModalLimitEdited, retrievedFallbackSwapsGasPrice, swapCustomGasModalClosed, -} = actions +} = actions; export { clearSwapsState, @@ -325,49 +326,49 @@ export { swapCustomGasModalPriceEdited, swapCustomGasModalLimitEdited, swapCustomGasModalClosed, -} +}; export const navigateBackToBuildQuote = (history) => { return async (dispatch) => { // TODO: Ensure any fetch in progress is cancelled - await dispatch(setBackgroundSwapRouteState('')) - dispatch(navigatedBackToBuildQuote()) - history.push(BUILD_QUOTE_ROUTE) - } -} + await dispatch(setBackgroundSwapRouteState('')); + dispatch(navigatedBackToBuildQuote()); + history.push(BUILD_QUOTE_ROUTE); + }; +}; export const prepareForRetryGetQuotes = () => { return async (dispatch) => { // TODO: Ensure any fetch in progress is cancelled - await dispatch(resetSwapsPostFetchState()) - dispatch(retriedGetQuotes()) - } -} + await dispatch(resetSwapsPostFetchState()); + dispatch(retriedGetQuotes()); + }; +}; export const prepareToLeaveSwaps = () => { return async (dispatch) => { - dispatch(clearSwapsState()) - await dispatch(resetBackgroundSwapsState()) - } -} + dispatch(clearSwapsState()); + await dispatch(resetBackgroundSwapsState()); + }; +}; export const swapsQuoteSelected = (aggId) => { return (dispatch) => { - dispatch(swapCustomGasModalLimitEdited(null)) - dispatch(setSelectedQuoteAggId(aggId)) - dispatch(setSwapsTxGasLimit('')) - } -} + dispatch(swapCustomGasModalLimitEdited(null)); + dispatch(setSelectedQuoteAggId(aggId)); + dispatch(setSwapsTxGasLimit('')); + }; +}; export const fetchAndSetSwapsGasPriceInfo = () => { return async (dispatch) => { - const basicEstimates = await dispatch(fetchMetaSwapsGasPriceEstimates()) + const basicEstimates = await dispatch(fetchMetaSwapsGasPriceEstimates()); if (basicEstimates?.fast) { - dispatch(setSwapsTxGasPrice(decGWEIToHexWEI(basicEstimates.fast))) + dispatch(setSwapsTxGasPrice(decGWEIToHexWEI(basicEstimates.fast))); } - } -} + }; +}; export const fetchQuotesAndSetQuoteState = ( history, @@ -376,23 +377,23 @@ export const fetchQuotesAndSetQuoteState = ( metaMetricsEvent, ) => { return async (dispatch, getState) => { - let swapsFeatureIsLive = false + let swapsFeatureIsLive = false; try { - swapsFeatureIsLive = await fetchSwapsFeatureLiveness() + swapsFeatureIsLive = await fetchSwapsFeatureLiveness(); } catch (error) { - log.error('Failed to fetch Swaps liveness, defaulting to false.', error) + log.error('Failed to fetch Swaps liveness, defaulting to false.', error); } - await dispatch(setSwapsLiveness(swapsFeatureIsLive)) + await dispatch(setSwapsLiveness(swapsFeatureIsLive)); if (!swapsFeatureIsLive) { - await history.push(SWAPS_MAINTENANCE_ROUTE) - return + await history.push(SWAPS_MAINTENANCE_ROUTE); + return; } - const state = getState() - const fetchParams = getFetchParams(state) - const selectedAccount = getSelectedAccount(state) - const balanceError = getBalanceError(state) + const state = getState(); + const fetchParams = getFetchParams(state); + const selectedAccount = getSelectedAccount(state); + const balanceError = getBalanceError(state); const fetchParamsFromToken = fetchParams?.metaData?.sourceTokenInfo?.symbol === 'ETH' ? { @@ -404,32 +405,32 @@ export const fetchQuotesAndSetQuoteState = ( }), balance: hexToDecimal(selectedAccount.balance), } - : fetchParams?.metaData?.sourceTokenInfo - const selectedFromToken = getFromToken(state) || fetchParamsFromToken || {} + : fetchParams?.metaData?.sourceTokenInfo; + const selectedFromToken = getFromToken(state) || fetchParamsFromToken || {}; const selectedToToken = - getToToken(state) || fetchParams?.metaData?.destinationTokenInfo || {} + getToToken(state) || fetchParams?.metaData?.destinationTokenInfo || {}; const { address: fromTokenAddress, symbol: fromTokenSymbol, decimals: fromTokenDecimals, iconUrl: fromTokenIconUrl, balance: fromTokenBalance, - } = selectedFromToken + } = selectedFromToken; const { address: toTokenAddress, symbol: toTokenSymbol, decimals: toTokenDecimals, iconUrl: toTokenIconUrl, - } = selectedToToken - await dispatch(setBackgroundSwapRouteState('loading')) - history.push(LOADING_QUOTES_ROUTE) - dispatch(setFetchingQuotes(true)) + } = selectedToToken; + await dispatch(setBackgroundSwapRouteState('loading')); + history.push(LOADING_QUOTES_ROUTE); + dispatch(setFetchingQuotes(true)); - const contractExchangeRates = getTokenExchangeRates(state) + const contractExchangeRates = getTokenExchangeRates(state); - let destinationTokenAddedForSwap = false + let destinationTokenAddedForSwap = false; if (toTokenSymbol !== 'ETH' && !contractExchangeRates[toTokenAddress]) { - destinationTokenAddedForSwap = true + destinationTokenAddedForSwap = true; await dispatch( addToken( toTokenAddress, @@ -438,7 +439,7 @@ export const fetchQuotesAndSetQuoteState = ( toTokenIconUrl, true, ), - ) + ); } if ( fromTokenSymbol !== 'ETH' && @@ -454,19 +455,19 @@ export const fetchQuotesAndSetQuoteState = ( fromTokenIconUrl, true, ), - ) + ); } - const swapsTokens = getSwapsTokens(state) + const swapsTokens = getSwapsTokens(state); const sourceTokenInfo = swapsTokens?.find(({ address }) => address === fromTokenAddress) || - selectedFromToken + selectedFromToken; const destinationTokenInfo = swapsTokens?.find(({ address }) => address === toTokenAddress) || - selectedToToken + selectedToToken; - dispatch(setFromToken(selectedFromToken)) + dispatch(setFromToken(selectedFromToken)); metaMetricsEvent({ event: 'Quotes Requested', @@ -480,11 +481,11 @@ export const fetchQuotesAndSetQuoteState = ( custom_slippage: maxSlippage !== 2, anonymizedData: true, }, - }) + }); try { - const fetchStartTime = Date.now() - dispatch(setQuotesFetchStartTime(fetchStartTime)) + const fetchStartTime = Date.now(); + dispatch(setQuotesFetchStartTime(fetchStartTime)); const fetchAndSetQuotesPromise = dispatch( fetchAndSetQuotes( @@ -504,14 +505,14 @@ export const fetchQuotesAndSetQuoteState = ( accountBalance: selectedAccount.balance, }, ), - ) + ); - const gasPriceFetchPromise = dispatch(fetchAndSetSwapsGasPriceInfo()) + const gasPriceFetchPromise = dispatch(fetchAndSetSwapsGasPriceInfo()); const [[fetchedQuotes, selectedAggId]] = await Promise.all([ fetchAndSetQuotesPromise, gasPriceFetchPromise, - ]) + ]); if (Object.values(fetchedQuotes)?.length === 0) { metaMetricsEvent({ @@ -525,10 +526,10 @@ export const fetchQuotesAndSetQuoteState = ( slippage: maxSlippage, custom_slippage: maxSlippage !== 2, }, - }) - dispatch(setSwapsErrorKey(QUOTES_NOT_AVAILABLE_ERROR)) + }); + dispatch(setSwapsErrorKey(QUOTES_NOT_AVAILABLE_ERROR)); } else { - const newSelectedQuote = fetchedQuotes[selectedAggId] + const newSelectedQuote = fetchedQuotes[selectedAggId]; metaMetricsEvent({ event: 'Quotes Received', @@ -549,87 +550,90 @@ export const fetchQuotesAndSetQuoteState = ( available_quotes: Object.values(fetchedQuotes)?.length, anonymizedData: true, }, - }) + }); - dispatch(setInitialGasEstimate(selectedAggId)) + dispatch(setInitialGasEstimate(selectedAggId)); } } catch (e) { // A newer swap request is running, so simply bail and let the newer request respond if (e.message === SWAPS_FETCH_ORDER_CONFLICT) { - log.debug(`Swap fetch order conflict detected; ignoring older request`) - return + log.debug(`Swap fetch order conflict detected; ignoring older request`); + return; } // TODO: Check for any errors we should expect to occur in production, and report others to Sentry - log.error(`Error fetching quotes: `, e) + log.error(`Error fetching quotes: `, e); - dispatch(setSwapsErrorKey(ERROR_FETCHING_QUOTES)) + dispatch(setSwapsErrorKey(ERROR_FETCHING_QUOTES)); } - dispatch(setFetchingQuotes(false)) - } -} + dispatch(setFetchingQuotes(false)); + }; +}; export const signAndSendTransactions = (history, metaMetricsEvent) => { return async (dispatch, getState) => { - let swapsFeatureIsLive = false + let swapsFeatureIsLive = false; try { - swapsFeatureIsLive = await fetchSwapsFeatureLiveness() + swapsFeatureIsLive = await fetchSwapsFeatureLiveness(); } catch (error) { - log.error('Failed to fetch Swaps liveness, defaulting to false.', error) + log.error('Failed to fetch Swaps liveness, defaulting to false.', error); } - await dispatch(setSwapsLiveness(swapsFeatureIsLive)) + await dispatch(setSwapsLiveness(swapsFeatureIsLive)); if (!swapsFeatureIsLive) { - await history.push(SWAPS_MAINTENANCE_ROUTE) - return + await history.push(SWAPS_MAINTENANCE_ROUTE); + return; } - const state = getState() - const customSwapsGas = getCustomSwapsGas(state) - const fetchParams = getFetchParams(state) - const { metaData, value: swapTokenValue, slippage } = fetchParams - const { sourceTokenInfo = {}, destinationTokenInfo = {} } = metaData - await dispatch(setBackgroundSwapRouteState('awaiting')) - await dispatch(stopPollingForQuotes()) - history.push(AWAITING_SWAP_ROUTE) + const state = getState(); + const customSwapsGas = getCustomSwapsGas(state); + const fetchParams = getFetchParams(state); + const { metaData, value: swapTokenValue, slippage } = fetchParams; + const { sourceTokenInfo = {}, destinationTokenInfo = {} } = metaData; + await dispatch(setBackgroundSwapRouteState('awaiting')); + await dispatch(stopPollingForQuotes()); + history.push(AWAITING_SWAP_ROUTE); - const { fast: fastGasEstimate } = getSwapGasPriceEstimateData(state) + const { fast: fastGasEstimate } = getSwapGasPriceEstimateData(state); - const usedQuote = getUsedQuote(state) - const usedTradeTxParams = usedQuote.trade + const usedQuote = getUsedQuote(state); + const usedTradeTxParams = usedQuote.trade; - const estimatedGasLimit = new BigNumber(usedQuote?.gasEstimate || `0x0`, 16) + const estimatedGasLimit = new BigNumber( + usedQuote?.gasEstimate || `0x0`, + 16, + ); const estimatedGasLimitWithMultiplier = estimatedGasLimit .times(usedQuote?.gasMultiplier || FALLBACK_GAS_MULTIPLIER, 10) .round(0) - .toString(16) + .toString(16); const maxGasLimit = customSwapsGas || (usedQuote?.gasEstimate ? estimatedGasLimitWithMultiplier - : `0x${decimalToHex(usedQuote?.maxGas || 0)}`) + : `0x${decimalToHex(usedQuote?.maxGas || 0)}`); - const usedGasPrice = getUsedSwapsGasPrice(state) - usedTradeTxParams.gas = maxGasLimit - usedTradeTxParams.gasPrice = usedGasPrice + const usedGasPrice = getUsedSwapsGasPrice(state); + usedTradeTxParams.gas = maxGasLimit; + usedTradeTxParams.gasPrice = usedGasPrice; - const usdConversionRate = getUSDConversionRate(state) + const usdConversionRate = getUSDConversionRate(state); const destinationValue = calcTokenAmount( usedQuote.destinationAmount, destinationTokenInfo.decimals || 18, - ).toPrecision(8) + ).toPrecision(8); const usedGasLimitEstimate = usedQuote?.gasEstimateWithRefund || - `0x${decimalToHex(usedQuote?.averageGas || 0)}` + `0x${decimalToHex(usedQuote?.averageGas || 0)}`; const totalGasLimitEstimate = new BigNumber(usedGasLimitEstimate, 16) .plus(usedQuote.approvalNeeded?.gas || '0x0', 16) - .toString(16) + .toString(16); const gasEstimateTotalInUSD = getValueFromWeiHex({ value: calcGasTotal(totalGasLimitEstimate, usedGasPrice), toCurrency: 'usd', conversionRate: usdConversionRate, numberOfDecimals: 6, - }) + }); const swapMetaData = { token_from: sourceTokenInfo.symbol, @@ -654,24 +658,24 @@ export const signAndSendTransactions = (history, metaMetricsEvent) => { performance_savings: usedQuote.savings?.performance, fee_savings: usedQuote.savings?.fee, median_metamask_fee: usedQuote.savings?.medianMetaMaskFee, - } + }; metaMetricsEvent({ event: 'Swap Started', category: 'swaps', sensitiveProperties: swapMetaData, - }) + }); - let finalApproveTxMeta - const approveTxParams = getApproveTxParams(state) + let finalApproveTxMeta; + const approveTxParams = getApproveTxParams(state); if (approveTxParams) { const approveTxMeta = await dispatch( addUnapprovedTransaction( { ...approveTxParams, amount: '0x0' }, 'metamask', ), - ) - await dispatch(setApproveTxId(approveTxMeta.id)) + ); + await dispatch(setApproveTxId(approveTxMeta.id)); finalApproveTxMeta = await dispatch( updateTransaction( { @@ -681,20 +685,20 @@ export const signAndSendTransactions = (history, metaMetricsEvent) => { }, true, ), - ) + ); try { - await dispatch(updateAndApproveTx(finalApproveTxMeta, true)) + await dispatch(updateAndApproveTx(finalApproveTxMeta, true)); } catch (e) { - await dispatch(setSwapsErrorKey(SWAP_FAILED_ERROR)) - history.push(SWAPS_ERROR_ROUTE) - return + await dispatch(setSwapsErrorKey(SWAP_FAILED_ERROR)); + history.push(SWAPS_ERROR_ROUTE); + return; } } const tradeTxMeta = await dispatch( addUnapprovedTransaction(usedTradeTxParams, 'metamask'), - ) - dispatch(setTradeTxId(tradeTxMeta.id)) + ); + dispatch(setTradeTxId(tradeTxMeta.id)); // The simulationFails property is added during the transaction controllers // addUnapprovedTransaction call if the estimateGas call fails. In cases @@ -706,10 +710,10 @@ export const signAndSendTransactions = (history, metaMetricsEvent) => { // transactions that get published to the blockchain only to fail and thereby // waste the user's funds on gas. if (!approveTxParams && tradeTxMeta.simulationFails) { - await dispatch(cancelTx(tradeTxMeta, false)) - await dispatch(setSwapsErrorKey(SWAP_FAILED_ERROR)) - history.push(SWAPS_ERROR_ROUTE) - return + await dispatch(cancelTx(tradeTxMeta, false)); + await dispatch(setSwapsErrorKey(SWAP_FAILED_ERROR)); + history.push(SWAPS_ERROR_ROUTE); + return; } const finalTradeTxMeta = await dispatch( updateTransaction( @@ -726,67 +730,67 @@ export const signAndSendTransactions = (history, metaMetricsEvent) => { }, true, ), - ) + ); try { - await dispatch(updateAndApproveTx(finalTradeTxMeta, true)) + await dispatch(updateAndApproveTx(finalTradeTxMeta, true)); } catch (e) { - await dispatch(setSwapsErrorKey(SWAP_FAILED_ERROR)) - history.push(SWAPS_ERROR_ROUTE) - return + await dispatch(setSwapsErrorKey(SWAP_FAILED_ERROR)); + history.push(SWAPS_ERROR_ROUTE); + return; } - await forceUpdateMetamaskState(dispatch) - } -} + await forceUpdateMetamaskState(dispatch); + }; +}; export function fetchMetaSwapsGasPriceEstimates() { return async (dispatch, getState) => { - const state = getState() + const state = getState(); const priceEstimatesLastRetrieved = getSwapsPriceEstimatesLastRetrieved( state, - ) + ); const timeLastRetrieved = priceEstimatesLastRetrieved || (await getStorageItem('METASWAP_GAS_PRICE_ESTIMATES_LAST_RETRIEVED')) || - 0 + 0; - dispatch(swapGasPriceEstimatesFetchStarted()) + dispatch(swapGasPriceEstimatesFetchStarted()); - let priceEstimates + let priceEstimates; try { if (Date.now() - timeLastRetrieved > 30000) { - priceEstimates = await fetchSwapsGasPrices() + priceEstimates = await fetchSwapsGasPrices(); } else { const cachedPriceEstimates = await getStorageItem( 'METASWAP_GAS_PRICE_ESTIMATES', - ) - priceEstimates = cachedPriceEstimates || (await fetchSwapsGasPrices()) + ); + priceEstimates = cachedPriceEstimates || (await fetchSwapsGasPrices()); } } catch (e) { - log.warn('Fetching swaps gas prices failed:', e) + log.warn('Fetching swaps gas prices failed:', e); if (!e.message?.match(/NetworkError|Fetch failed with status:/u)) { - throw e + throw e; } - dispatch(swapGasPriceEstimatesFetchFailed()) + dispatch(swapGasPriceEstimatesFetchFailed()); try { - const gasPrice = await global.ethQuery.gasPrice() - const gasPriceInDecGWEI = hexWEIToDecGWEI(gasPrice.toString(10)) + const gasPrice = await global.ethQuery.gasPrice(); + const gasPriceInDecGWEI = hexWEIToDecGWEI(gasPrice.toString(10)); - dispatch(retrievedFallbackSwapsGasPrice(gasPriceInDecGWEI)) - return null + dispatch(retrievedFallbackSwapsGasPrice(gasPriceInDecGWEI)); + return null; } catch (networkGasPriceError) { console.error( `Failed to retrieve fallback gas price: `, networkGasPriceError, - ) - return null + ); + return null; } } - const timeRetrieved = Date.now() + const timeRetrieved = Date.now(); await Promise.all([ setStorageItem('METASWAP_GAS_PRICE_ESTIMATES', priceEstimates), @@ -794,14 +798,14 @@ export function fetchMetaSwapsGasPriceEstimates() { 'METASWAP_GAS_PRICE_ESTIMATES_LAST_RETRIEVED', timeRetrieved, ), - ]) + ]); dispatch( swapGasPriceEstimatesFetchCompleted({ priceEstimates, priceEstimatesLastRetrieved: timeRetrieved, }), - ) - return priceEstimates - } + ); + return priceEstimates; + }; } diff --git a/ui/app/helpers/constants/common.js b/ui/app/helpers/constants/common.js index 7a0503112..c2e8f9bb5 100644 --- a/ui/app/helpers/constants/common.js +++ b/ui/app/helpers/constants/common.js @@ -1,13 +1,13 @@ -export const ETH = 'ETH' -export const GWEI = 'GWEI' -export const WEI = 'WEI' +export const ETH = 'ETH'; +export const GWEI = 'GWEI'; +export const WEI = 'WEI'; -export const PRIMARY = 'PRIMARY' -export const SECONDARY = 'SECONDARY' +export const PRIMARY = 'PRIMARY'; +export const SECONDARY = 'SECONDARY'; export const GAS_ESTIMATE_TYPES = { SLOW: 'SLOW', AVERAGE: 'AVERAGE', FAST: 'FAST', FASTEST: 'FASTEST', -} +}; diff --git a/ui/app/helpers/constants/connected-sites.js b/ui/app/helpers/constants/connected-sites.js index 717460f29..2a5579fcd 100644 --- a/ui/app/helpers/constants/connected-sites.js +++ b/ui/app/helpers/constants/connected-sites.js @@ -1,4 +1,4 @@ -export const STATUS_CONNECTED = 'STATUS_CONNECTED' +export const STATUS_CONNECTED = 'STATUS_CONNECTED'; export const STATUS_CONNECTED_TO_ANOTHER_ACCOUNT = - 'STATUS_CONNECTED_TO_ANOTHER_ACCOUNT' -export const STATUS_NOT_CONNECTED = 'STATUS_NOT_CONNECTED' + 'STATUS_CONNECTED_TO_ANOTHER_ACCOUNT'; +export const STATUS_NOT_CONNECTED = 'STATUS_NOT_CONNECTED'; diff --git a/ui/app/helpers/constants/design-system.js b/ui/app/helpers/constants/design-system.js index 6caef4414..070ea2748 100644 --- a/ui/app/helpers/constants/design-system.js +++ b/ui/app/helpers/constants/design-system.js @@ -32,7 +32,7 @@ export const COLORS = { RINKEBY: 'rinkeby', GOERLI: 'goerli', TRANSPARENT: 'transparent', -} +}; export const TYPOGRAPHY = { H1: 'h1', @@ -45,9 +45,9 @@ export const TYPOGRAPHY = { H8: 'h8', H9: 'h9', Paragraph: 'paragraph', -} +}; -const NONE = 'none' +const NONE = 'none'; export const SIZES = { XS: 'xs', @@ -56,7 +56,7 @@ export const SIZES = { LG: 'lg', XL: 'xl', NONE, -} +}; export const BORDER_STYLE = { DASHED: 'dashed', @@ -64,11 +64,11 @@ export const BORDER_STYLE = { DOTTED: 'dotted', DOUBLE: 'double', NONE, -} +}; -const FLEX_END = 'flex-end' -const FLEX_START = 'flex-start' -const CENTER = 'center' +const FLEX_END = 'flex-end'; +const FLEX_START = 'flex-start'; +const CENTER = 'center'; export const ALIGN_ITEMS = { FLEX_START, @@ -76,7 +76,7 @@ export const ALIGN_ITEMS = { CENTER, BASELINE: 'baseline', STRETCH: 'stretch', -} +}; export const JUSTIFY_CONTENT = { FLEX_START, @@ -85,7 +85,7 @@ export const JUSTIFY_CONTENT = { SPACE_AROUND: 'space-around', SPACE_BETWEEN: 'space-between', SPACE_EVENLY: 'space-evenly', -} +}; export const DISPLAY = { BLOCK: 'block', @@ -95,7 +95,7 @@ export const DISPLAY = { INLINE_FLEX: 'inline-flex', INLINE_GRID: 'inline-grid', LIST_ITEM: 'list-item', -} +}; const FRACTIONS = { HALF: '1/2', @@ -124,7 +124,7 @@ const FRACTIONS = { NINE_TWELFTHS: '9/12', TEN_TWELFTHS: '10/12', ELEVEN_TWELFTHS: '11/12', -} +}; export const BLOCK_SIZES = { ...FRACTIONS, @@ -132,14 +132,14 @@ export const BLOCK_SIZES = { MAX: 'max', MIN: 'min', FULL: 'full', -} +}; export const TEXT_ALIGN = { LEFT: 'left', CENTER: 'center', RIGHT: 'right', JUSTIFY: 'justify', -} +}; export const FONT_WEIGHT = { BOLD: 'bold', @@ -153,11 +153,11 @@ export const FONT_WEIGHT = { 700: 700, 800: 800, 900: 900, -} +}; export const SEVERITIES = { DANGER: 'danger', WARNING: 'warning', INFO: 'info', SUCCESS: 'success', -} +}; diff --git a/ui/app/helpers/constants/error-keys.js b/ui/app/helpers/constants/error-keys.js index 704064c96..85ce13d7d 100644 --- a/ui/app/helpers/constants/error-keys.js +++ b/ui/app/helpers/constants/error-keys.js @@ -1,4 +1,4 @@ -export const INSUFFICIENT_FUNDS_ERROR_KEY = 'insufficientFunds' -export const GAS_LIMIT_TOO_LOW_ERROR_KEY = 'gasLimitTooLow' -export const TRANSACTION_ERROR_KEY = 'transactionError' -export const TRANSACTION_NO_CONTRACT_ERROR_KEY = 'transactionErrorNoContract' +export const INSUFFICIENT_FUNDS_ERROR_KEY = 'insufficientFunds'; +export const GAS_LIMIT_TOO_LOW_ERROR_KEY = 'gasLimitTooLow'; +export const TRANSACTION_ERROR_KEY = 'transactionError'; +export const TRANSACTION_NO_CONTRACT_ERROR_KEY = 'transactionErrorNoContract'; diff --git a/ui/app/helpers/constants/routes.js b/ui/app/helpers/constants/routes.js index d3b5904c5..5b92c3fd5 100644 --- a/ui/app/helpers/constants/routes.js +++ b/ui/app/helpers/constants/routes.js @@ -1,67 +1,69 @@ -const DEFAULT_ROUTE = '/' -const UNLOCK_ROUTE = '/unlock' -const LOCK_ROUTE = '/lock' -const ASSET_ROUTE = '/asset' -const SETTINGS_ROUTE = '/settings' -const GENERAL_ROUTE = '/settings/general' -const ADVANCED_ROUTE = '/settings/advanced' -const SECURITY_ROUTE = '/settings/security' -const ABOUT_US_ROUTE = '/settings/about-us' -const ALERTS_ROUTE = '/settings/alerts' -const NETWORKS_ROUTE = '/settings/networks' -const NETWORKS_FORM_ROUTE = '/settings/networks/form' -const CONTACT_LIST_ROUTE = '/settings/contact-list' -const CONTACT_EDIT_ROUTE = '/settings/contact-list/edit-contact' -const CONTACT_ADD_ROUTE = '/settings/contact-list/add-contact' -const CONTACT_VIEW_ROUTE = '/settings/contact-list/view-contact' -const CONTACT_MY_ACCOUNTS_ROUTE = '/settings/contact-list/my-accounts' -const CONTACT_MY_ACCOUNTS_VIEW_ROUTE = '/settings/contact-list/my-accounts/view' -const CONTACT_MY_ACCOUNTS_EDIT_ROUTE = '/settings/contact-list/my-accounts/edit' -const REVEAL_SEED_ROUTE = '/seed' -const MOBILE_SYNC_ROUTE = '/mobile-sync' -const RESTORE_VAULT_ROUTE = '/restore-vault' -const ADD_TOKEN_ROUTE = '/add-token' -const CONFIRM_ADD_TOKEN_ROUTE = '/confirm-add-token' -const CONFIRM_ADD_SUGGESTED_TOKEN_ROUTE = '/confirm-add-suggested-token' -const NEW_ACCOUNT_ROUTE = '/new-account' -const IMPORT_ACCOUNT_ROUTE = '/new-account/import' -const CONNECT_HARDWARE_ROUTE = '/new-account/connect' -const SEND_ROUTE = '/send' -const CONNECT_ROUTE = '/connect' -const CONNECT_CONFIRM_PERMISSIONS_ROUTE = '/confirm-permissions' -const CONNECTED_ROUTE = '/connected' -const CONNECTED_ACCOUNTS_ROUTE = '/connected/accounts' -const SWAPS_ROUTE = '/swaps' -const BUILD_QUOTE_ROUTE = '/swaps/build-quote' -const VIEW_QUOTE_ROUTE = '/swaps/view-quote' -const LOADING_QUOTES_ROUTE = '/swaps/loading-quotes' -const AWAITING_SWAP_ROUTE = '/swaps/awaiting-swap' -const SWAPS_ERROR_ROUTE = '/swaps/swaps-error' -const SWAPS_MAINTENANCE_ROUTE = '/swaps/maintenance' +const DEFAULT_ROUTE = '/'; +const UNLOCK_ROUTE = '/unlock'; +const LOCK_ROUTE = '/lock'; +const ASSET_ROUTE = '/asset'; +const SETTINGS_ROUTE = '/settings'; +const GENERAL_ROUTE = '/settings/general'; +const ADVANCED_ROUTE = '/settings/advanced'; +const SECURITY_ROUTE = '/settings/security'; +const ABOUT_US_ROUTE = '/settings/about-us'; +const ALERTS_ROUTE = '/settings/alerts'; +const NETWORKS_ROUTE = '/settings/networks'; +const NETWORKS_FORM_ROUTE = '/settings/networks/form'; +const CONTACT_LIST_ROUTE = '/settings/contact-list'; +const CONTACT_EDIT_ROUTE = '/settings/contact-list/edit-contact'; +const CONTACT_ADD_ROUTE = '/settings/contact-list/add-contact'; +const CONTACT_VIEW_ROUTE = '/settings/contact-list/view-contact'; +const CONTACT_MY_ACCOUNTS_ROUTE = '/settings/contact-list/my-accounts'; +const CONTACT_MY_ACCOUNTS_VIEW_ROUTE = + '/settings/contact-list/my-accounts/view'; +const CONTACT_MY_ACCOUNTS_EDIT_ROUTE = + '/settings/contact-list/my-accounts/edit'; +const REVEAL_SEED_ROUTE = '/seed'; +const MOBILE_SYNC_ROUTE = '/mobile-sync'; +const RESTORE_VAULT_ROUTE = '/restore-vault'; +const ADD_TOKEN_ROUTE = '/add-token'; +const CONFIRM_ADD_TOKEN_ROUTE = '/confirm-add-token'; +const CONFIRM_ADD_SUGGESTED_TOKEN_ROUTE = '/confirm-add-suggested-token'; +const NEW_ACCOUNT_ROUTE = '/new-account'; +const IMPORT_ACCOUNT_ROUTE = '/new-account/import'; +const CONNECT_HARDWARE_ROUTE = '/new-account/connect'; +const SEND_ROUTE = '/send'; +const CONNECT_ROUTE = '/connect'; +const CONNECT_CONFIRM_PERMISSIONS_ROUTE = '/confirm-permissions'; +const CONNECTED_ROUTE = '/connected'; +const CONNECTED_ACCOUNTS_ROUTE = '/connected/accounts'; +const SWAPS_ROUTE = '/swaps'; +const BUILD_QUOTE_ROUTE = '/swaps/build-quote'; +const VIEW_QUOTE_ROUTE = '/swaps/view-quote'; +const LOADING_QUOTES_ROUTE = '/swaps/loading-quotes'; +const AWAITING_SWAP_ROUTE = '/swaps/awaiting-swap'; +const SWAPS_ERROR_ROUTE = '/swaps/swaps-error'; +const SWAPS_MAINTENANCE_ROUTE = '/swaps/maintenance'; -const INITIALIZE_ROUTE = '/initialize' -const INITIALIZE_WELCOME_ROUTE = '/initialize/welcome' -const INITIALIZE_UNLOCK_ROUTE = '/initialize/unlock' -const INITIALIZE_CREATE_PASSWORD_ROUTE = '/initialize/create-password' +const INITIALIZE_ROUTE = '/initialize'; +const INITIALIZE_WELCOME_ROUTE = '/initialize/welcome'; +const INITIALIZE_UNLOCK_ROUTE = '/initialize/unlock'; +const INITIALIZE_CREATE_PASSWORD_ROUTE = '/initialize/create-password'; const INITIALIZE_IMPORT_WITH_SEED_PHRASE_ROUTE = - '/initialize/create-password/import-with-seed-phrase' -const INITIALIZE_SELECT_ACTION_ROUTE = '/initialize/select-action' -const INITIALIZE_SEED_PHRASE_ROUTE = '/initialize/seed-phrase' -const INITIALIZE_BACKUP_SEED_PHRASE_ROUTE = '/initialize/backup-seed-phrase' -const INITIALIZE_END_OF_FLOW_ROUTE = '/initialize/end-of-flow' -const INITIALIZE_CONFIRM_SEED_PHRASE_ROUTE = '/initialize/seed-phrase/confirm' -const INITIALIZE_METAMETRICS_OPT_IN_ROUTE = '/initialize/metametrics-opt-in' + '/initialize/create-password/import-with-seed-phrase'; +const INITIALIZE_SELECT_ACTION_ROUTE = '/initialize/select-action'; +const INITIALIZE_SEED_PHRASE_ROUTE = '/initialize/seed-phrase'; +const INITIALIZE_BACKUP_SEED_PHRASE_ROUTE = '/initialize/backup-seed-phrase'; +const INITIALIZE_END_OF_FLOW_ROUTE = '/initialize/end-of-flow'; +const INITIALIZE_CONFIRM_SEED_PHRASE_ROUTE = '/initialize/seed-phrase/confirm'; +const INITIALIZE_METAMETRICS_OPT_IN_ROUTE = '/initialize/metametrics-opt-in'; -const CONFIRM_TRANSACTION_ROUTE = '/confirm-transaction' -const CONFIRM_SEND_ETHER_PATH = '/send-ether' -const CONFIRM_SEND_TOKEN_PATH = '/send-token' -const CONFIRM_DEPLOY_CONTRACT_PATH = '/deploy-contract' -const CONFIRM_APPROVE_PATH = '/approve' -const CONFIRM_TRANSFER_FROM_PATH = '/transfer-from' -const CONFIRM_TOKEN_METHOD_PATH = '/token-method' -const SIGNATURE_REQUEST_PATH = '/signature-request' -const DECRYPT_MESSAGE_REQUEST_PATH = '/decrypt-message-request' -const ENCRYPTION_PUBLIC_KEY_REQUEST_PATH = '/encryption-public-key-request' +const CONFIRM_TRANSACTION_ROUTE = '/confirm-transaction'; +const CONFIRM_SEND_ETHER_PATH = '/send-ether'; +const CONFIRM_SEND_TOKEN_PATH = '/send-token'; +const CONFIRM_DEPLOY_CONTRACT_PATH = '/deploy-contract'; +const CONFIRM_APPROVE_PATH = '/approve'; +const CONFIRM_TRANSFER_FROM_PATH = '/transfer-from'; +const CONFIRM_TOKEN_METHOD_PATH = '/token-method'; +const SIGNATURE_REQUEST_PATH = '/signature-request'; +const DECRYPT_MESSAGE_REQUEST_PATH = '/decrypt-message-request'; +const ENCRYPTION_PUBLIC_KEY_REQUEST_PATH = '/encryption-public-key-request'; // Used to pull a convenient name for analytics tracking events. The key must // be react-router ready path, and can include params such as :id for popup windows @@ -130,7 +132,7 @@ const PATH_NAME_MAP = { [LOADING_QUOTES_ROUTE]: 'Swaps Loading Quotes Page', [AWAITING_SWAP_ROUTE]: 'Swaps Awaiting Swaps Page', [SWAPS_ERROR_ROUTE]: 'Swaps Error Page', -} +}; export { DEFAULT_ROUTE, @@ -195,4 +197,4 @@ export { AWAITING_SWAP_ROUTE, SWAPS_ERROR_ROUTE, SWAPS_MAINTENANCE_ROUTE, -} +}; diff --git a/ui/app/helpers/constants/swaps.js b/ui/app/helpers/constants/swaps.js index af22f84ea..1011306a8 100644 --- a/ui/app/helpers/constants/swaps.js +++ b/ui/app/helpers/constants/swaps.js @@ -1,6 +1,6 @@ // An address that the metaswap-api recognizes as ETH, in place of the token address that ERC-20 tokens have export const ETH_SWAPS_TOKEN_ADDRESS = - '0x0000000000000000000000000000000000000000' + '0x0000000000000000000000000000000000000000'; export const ETH_SWAPS_TOKEN_OBJECT = { symbol: 'ETH', @@ -8,17 +8,17 @@ export const ETH_SWAPS_TOKEN_OBJECT = { address: ETH_SWAPS_TOKEN_ADDRESS, decimals: 18, iconUrl: 'images/black-eth-logo.svg', -} +}; -export const QUOTES_EXPIRED_ERROR = 'quotes-expired' -export const SWAP_FAILED_ERROR = 'swap-failed-error' -export const ERROR_FETCHING_QUOTES = 'error-fetching-quotes' -export const QUOTES_NOT_AVAILABLE_ERROR = 'quotes-not-avilable' -export const OFFLINE_FOR_MAINTENANCE = 'offline-for-maintenance' -export const SWAPS_FETCH_ORDER_CONFLICT = 'swaps-fetch-order-conflict' +export const QUOTES_EXPIRED_ERROR = 'quotes-expired'; +export const SWAP_FAILED_ERROR = 'swap-failed-error'; +export const ERROR_FETCHING_QUOTES = 'error-fetching-quotes'; +export const QUOTES_NOT_AVAILABLE_ERROR = 'quotes-not-avilable'; +export const OFFLINE_FOR_MAINTENANCE = 'offline-for-maintenance'; +export const SWAPS_FETCH_ORDER_CONFLICT = 'swaps-fetch-order-conflict'; // A gas value for ERC20 approve calls that should be sufficient for all ERC20 approve implementations -export const DEFAULT_ERC20_APPROVE_GAS = '0x1d4c0' +export const DEFAULT_ERC20_APPROVE_GAS = '0x1d4c0'; export const SWAPS_CONTRACT_ADDRESS = - '0x881d40237659c251811cec9c364ef91dc08d300c' + '0x881d40237659c251811cec9c364ef91dc08d300c'; diff --git a/ui/app/helpers/constants/transactions.js b/ui/app/helpers/constants/transactions.js index e344587ba..f349b3ae6 100644 --- a/ui/app/helpers/constants/transactions.js +++ b/ui/app/helpers/constants/transactions.js @@ -1,21 +1,21 @@ import { TRANSACTION_CATEGORIES, TRANSACTION_STATUSES, -} from '../../../../shared/constants/transaction' +} from '../../../../shared/constants/transaction'; export const PENDING_STATUS_HASH = { [TRANSACTION_STATUSES.UNAPPROVED]: true, [TRANSACTION_STATUSES.APPROVED]: true, [TRANSACTION_STATUSES.SUBMITTED]: true, -} +}; export const PRIORITY_STATUS_HASH = { ...PENDING_STATUS_HASH, [TRANSACTION_STATUSES.CONFIRMED]: true, -} +}; export const TOKEN_CATEGORY_HASH = { [TRANSACTION_CATEGORIES.TOKEN_METHOD_APPROVE]: true, [TRANSACTION_CATEGORIES.TOKEN_METHOD_TRANSFER]: true, [TRANSACTION_CATEGORIES.TOKEN_METHOD_TRANSFER_FROM]: true, -} +}; diff --git a/ui/app/helpers/higher-order-components/authenticated/authenticated.component.js b/ui/app/helpers/higher-order-components/authenticated/authenticated.component.js index 585e34707..2feebfdb0 100644 --- a/ui/app/helpers/higher-order-components/authenticated/authenticated.component.js +++ b/ui/app/helpers/higher-order-components/authenticated/authenticated.component.js @@ -1,22 +1,22 @@ -import React from 'react' -import PropTypes from 'prop-types' -import { Redirect, Route } from 'react-router-dom' -import { UNLOCK_ROUTE, INITIALIZE_ROUTE } from '../../constants/routes' +import React from 'react'; +import PropTypes from 'prop-types'; +import { Redirect, Route } from 'react-router-dom'; +import { UNLOCK_ROUTE, INITIALIZE_ROUTE } from '../../constants/routes'; export default function Authenticated(props) { - const { isUnlocked, completedOnboarding } = props + const { isUnlocked, completedOnboarding } = props; switch (true) { case isUnlocked && completedOnboarding: - return + return ; case !completedOnboarding: - return + return ; default: - return + return ; } } Authenticated.propTypes = { isUnlocked: PropTypes.bool, completedOnboarding: PropTypes.bool, -} +}; diff --git a/ui/app/helpers/higher-order-components/authenticated/authenticated.container.js b/ui/app/helpers/higher-order-components/authenticated/authenticated.container.js index 1f956957b..6b0d735d1 100644 --- a/ui/app/helpers/higher-order-components/authenticated/authenticated.container.js +++ b/ui/app/helpers/higher-order-components/authenticated/authenticated.container.js @@ -1,15 +1,15 @@ -import { connect } from 'react-redux' -import Authenticated from './authenticated.component' +import { connect } from 'react-redux'; +import Authenticated from './authenticated.component'; const mapStateToProps = (state) => { const { metamask: { isUnlocked, completedOnboarding }, - } = state + } = state; return { isUnlocked, completedOnboarding, - } -} + }; +}; -export default connect(mapStateToProps)(Authenticated) +export default connect(mapStateToProps)(Authenticated); diff --git a/ui/app/helpers/higher-order-components/authenticated/index.js b/ui/app/helpers/higher-order-components/authenticated/index.js index 05632ed21..bd53f1116 100644 --- a/ui/app/helpers/higher-order-components/authenticated/index.js +++ b/ui/app/helpers/higher-order-components/authenticated/index.js @@ -1 +1 @@ -export { default } from './authenticated.container' +export { default } from './authenticated.container'; diff --git a/ui/app/helpers/higher-order-components/feature-toggled-route.js b/ui/app/helpers/higher-order-components/feature-toggled-route.js index bcfca050b..6d58b7d04 100644 --- a/ui/app/helpers/higher-order-components/feature-toggled-route.js +++ b/ui/app/helpers/higher-order-components/feature-toggled-route.js @@ -1,15 +1,15 @@ -import React from 'react' -import PropTypes from 'prop-types' -import { Redirect, Route } from 'react-router-dom' +import React from 'react'; +import PropTypes from 'prop-types'; +import { Redirect, Route } from 'react-router-dom'; export default function FeatureToggledRoute({ flag, redirectRoute, ...props }) { if (flag) { - return + return ; } - return + return ; } FeatureToggledRoute.propTypes = { flag: PropTypes.bool.isRequired, redirectRoute: PropTypes.string.isRequired, -} +}; diff --git a/ui/app/helpers/higher-order-components/initialized/index.js b/ui/app/helpers/higher-order-components/initialized/index.js index 5aa9f0809..48ab62577 100644 --- a/ui/app/helpers/higher-order-components/initialized/index.js +++ b/ui/app/helpers/higher-order-components/initialized/index.js @@ -1 +1 @@ -export { default } from './initialized.container' +export { default } from './initialized.container'; diff --git a/ui/app/helpers/higher-order-components/initialized/initialized.component.js b/ui/app/helpers/higher-order-components/initialized/initialized.component.js index 88a4deb1d..a953403fd 100644 --- a/ui/app/helpers/higher-order-components/initialized/initialized.component.js +++ b/ui/app/helpers/higher-order-components/initialized/initialized.component.js @@ -1,16 +1,16 @@ -import React from 'react' -import PropTypes from 'prop-types' -import { Redirect, Route } from 'react-router-dom' -import { INITIALIZE_ROUTE } from '../../constants/routes' +import React from 'react'; +import PropTypes from 'prop-types'; +import { Redirect, Route } from 'react-router-dom'; +import { INITIALIZE_ROUTE } from '../../constants/routes'; export default function Initialized(props) { return props.completedOnboarding ? ( ) : ( - ) + ); } Initialized.propTypes = { completedOnboarding: PropTypes.bool, -} +}; diff --git a/ui/app/helpers/higher-order-components/initialized/initialized.container.js b/ui/app/helpers/higher-order-components/initialized/initialized.container.js index d7b5633a4..c4143cc07 100644 --- a/ui/app/helpers/higher-order-components/initialized/initialized.container.js +++ b/ui/app/helpers/higher-order-components/initialized/initialized.container.js @@ -1,14 +1,14 @@ -import { connect } from 'react-redux' -import Initialized from './initialized.component' +import { connect } from 'react-redux'; +import Initialized from './initialized.component'; const mapStateToProps = (state) => { const { metamask: { completedOnboarding }, - } = state + } = state; return { completedOnboarding, - } -} + }; +}; -export default connect(mapStateToProps)(Initialized) +export default connect(mapStateToProps)(Initialized); diff --git a/ui/app/helpers/higher-order-components/with-modal-props/index.js b/ui/app/helpers/higher-order-components/with-modal-props/index.js index e476b51d2..0bc8f5e2a 100644 --- a/ui/app/helpers/higher-order-components/with-modal-props/index.js +++ b/ui/app/helpers/higher-order-components/with-modal-props/index.js @@ -1 +1 @@ -export { default } from './with-modal-props' +export { default } from './with-modal-props'; diff --git a/ui/app/helpers/higher-order-components/with-modal-props/tests/with-modal-props.test.js b/ui/app/helpers/higher-order-components/with-modal-props/tests/with-modal-props.test.js index 06f95129a..79339b4ad 100644 --- a/ui/app/helpers/higher-order-components/with-modal-props/tests/with-modal-props.test.js +++ b/ui/app/helpers/higher-order-components/with-modal-props/tests/with-modal-props.test.js @@ -1,8 +1,8 @@ -import assert from 'assert' -import configureMockStore from 'redux-mock-store' -import { mount } from 'enzyme' -import React from 'react' -import withModalProps from '../with-modal-props' +import assert from 'assert'; +import configureMockStore from 'redux-mock-store'; +import { mount } from 'enzyme'; +import React from 'react'; +import withModalProps from '../with-modal-props'; const mockState = { appState: { @@ -16,23 +16,23 @@ const mockState = { }, }, }, -} +}; describe('withModalProps', function () { it('should return a component wrapped with modal state props', function () { - const TestComponent = () =>
    Testing
    - const WrappedComponent = withModalProps(TestComponent) - const store = configureMockStore()(mockState) - const wrapper = mount() + const TestComponent = () =>
    Testing
    ; + const WrappedComponent = withModalProps(TestComponent); + const store = configureMockStore()(mockState); + const wrapper = mount(); - assert.ok(wrapper) - const testComponent = wrapper.find(TestComponent).at(0) - assert.strictEqual(testComponent.length, 1) - assert.strictEqual(testComponent.find('.test').text(), 'Testing') - const testComponentProps = testComponent.props() - assert.strictEqual(testComponentProps.prop1, 'prop1') - assert.strictEqual(testComponentProps.prop2, 2) - assert.strictEqual(testComponentProps.prop3, true) - assert.strictEqual(typeof testComponentProps.hideModal, 'function') - }) -}) + assert.ok(wrapper); + const testComponent = wrapper.find(TestComponent).at(0); + assert.strictEqual(testComponent.length, 1); + assert.strictEqual(testComponent.find('.test').text(), 'Testing'); + const testComponentProps = testComponent.props(); + assert.strictEqual(testComponentProps.prop1, 'prop1'); + assert.strictEqual(testComponentProps.prop2, 2); + assert.strictEqual(testComponentProps.prop3, true); + assert.strictEqual(typeof testComponentProps.hideModal, 'function'); + }); +}); diff --git a/ui/app/helpers/higher-order-components/with-modal-props/with-modal-props.js b/ui/app/helpers/higher-order-components/with-modal-props/with-modal-props.js index 88dbfa925..8d19a4958 100644 --- a/ui/app/helpers/higher-order-components/with-modal-props/with-modal-props.js +++ b/ui/app/helpers/higher-order-components/with-modal-props/with-modal-props.js @@ -1,21 +1,21 @@ -import { connect } from 'react-redux' -import { hideModal } from '../../../store/actions' +import { connect } from 'react-redux'; +import { hideModal } from '../../../store/actions'; const mapStateToProps = (state) => { - const { appState } = state - const { props: modalProps } = appState.modal.modalState + const { appState } = state; + const { props: modalProps } = appState.modal.modalState; return { ...modalProps, - } -} + }; +}; const mapDispatchToProps = (dispatch) => { return { hideModal: () => dispatch(hideModal()), - } -} + }; +}; export default function withModalProps(Component) { - return connect(mapStateToProps, mapDispatchToProps)(Component) + return connect(mapStateToProps, mapDispatchToProps)(Component); } diff --git a/ui/app/helpers/utils/common.util.js b/ui/app/helpers/utils/common.util.js index 0c0d49c15..06272009a 100644 --- a/ui/app/helpers/utils/common.util.js +++ b/ui/app/helpers/utils/common.util.js @@ -1,3 +1,3 @@ export function camelCaseToCapitalize(str = '') { - return str.replace(/([A-Z])/gu, ' $1').replace(/^./u, (s) => s.toUpperCase()) + return str.replace(/([A-Z])/gu, ' $1').replace(/^./u, (s) => s.toUpperCase()); } diff --git a/ui/app/helpers/utils/common.util.test.js b/ui/app/helpers/utils/common.util.test.js index 2e083322d..50a50d47b 100644 --- a/ui/app/helpers/utils/common.util.test.js +++ b/ui/app/helpers/utils/common.util.test.js @@ -1,5 +1,5 @@ -import assert from 'assert' -import * as utils from './common.util' +import assert from 'assert'; +import * as utils from './common.util'; describe('Common utils', function () { describe('camelCaseToCapitalize', function () { @@ -17,11 +17,11 @@ describe('Common utils', function () { test: 'thisIsATest', expected: 'This Is A Test', }, - ] + ]; tests.forEach(({ test, expected }) => { - assert.strictEqual(utils.camelCaseToCapitalize(test), expected) - }) - }) - }) -}) + assert.strictEqual(utils.camelCaseToCapitalize(test), expected); + }); + }); + }); +}); diff --git a/ui/app/helpers/utils/confirm-tx.util.js b/ui/app/helpers/utils/confirm-tx.util.js index 8ff39e498..80fe2f3df 100644 --- a/ui/app/helpers/utils/confirm-tx.util.js +++ b/ui/app/helpers/utils/confirm-tx.util.js @@ -1,15 +1,15 @@ -import currencyFormatter from 'currency-formatter' -import currencies from 'currency-formatter/currencies' -import BigNumber from 'bignumber.js' -import { addHexPrefix } from '../../../../app/scripts/lib/util' +import currencyFormatter from 'currency-formatter'; +import currencies from 'currency-formatter/currencies'; +import BigNumber from 'bignumber.js'; +import { addHexPrefix } from '../../../../app/scripts/lib/util'; -import { unconfirmedTransactionsCountSelector } from '../../selectors' +import { unconfirmedTransactionsCountSelector } from '../../selectors'; import { conversionUtil, addCurrencies, multiplyCurrencies, conversionGreaterThan, -} from './conversion-util' +} from './conversion-util'; export function increaseLastGasPrice(lastGasPrice) { return addHexPrefix( @@ -18,14 +18,14 @@ export function increaseLastGasPrice(lastGasPrice) { multiplierBase: 10, toNumericBase: 'hex', }), - ) + ); } export function hexGreaterThan(a, b) { return conversionGreaterThan( { value: a, fromNumericBase: 'hex' }, { value: b, fromNumericBase: 'hex' }, - ) + ); } export function getHexGasTotal({ gasLimit, gasPrice }) { @@ -35,7 +35,7 @@ export function getHexGasTotal({ gasLimit, gasPrice }) { multiplicandBase: 16, multiplierBase: 16, }), - ) + ); } export function addEth(...args) { @@ -45,8 +45,8 @@ export function addEth(...args) { numberOfDecimals: 6, aBase: 10, bBase: 10, - }) - }) + }); + }); } export function addFiat(...args) { @@ -56,8 +56,8 @@ export function addFiat(...args) { numberOfDecimals: 2, aBase: 10, bBase: 10, - }) - }) + }); + }); } export function getValueFromWeiHex({ @@ -77,7 +77,7 @@ export function getValueFromWeiHex({ fromDenomination: 'WEI', toDenomination, conversionRate, - }) + }); } export function getTransactionFee({ @@ -95,18 +95,18 @@ export function getTransactionFee({ toCurrency, numberOfDecimals, conversionRate, - }) + }); } export function formatCurrency(value, currencyCode) { - const upperCaseCurrencyCode = currencyCode.toUpperCase() + const upperCaseCurrencyCode = currencyCode.toUpperCase(); return currencies.find((currency) => currency.code === upperCaseCurrencyCode) ? currencyFormatter.format(Number(value), { code: upperCaseCurrencyCode, style: 'currency', }) - : value + : value; } export function convertTokenToFiat({ @@ -116,7 +116,7 @@ export function convertTokenToFiat({ conversionRate, contractExchangeRate, }) { - const totalExchangeRate = conversionRate * contractExchangeRate + const totalExchangeRate = conversionRate * contractExchangeRate; return conversionUtil(value, { fromNumericBase: 'dec', @@ -125,11 +125,11 @@ export function convertTokenToFiat({ toCurrency, numberOfDecimals: 2, conversionRate: totalExchangeRate, - }) + }); } export function hasUnconfirmedTransactions(state) { - return unconfirmedTransactionsCountSelector(state) > 0 + return unconfirmedTransactionsCountSelector(state) > 0; } /** @@ -140,11 +140,11 @@ export function hasUnconfirmedTransactions(state) { * rounding was necessary. */ export function roundExponential(decimalString) { - const PRECISION = 4 - const bigNumberValue = new BigNumber(decimalString) + const PRECISION = 4; + const bigNumberValue = new BigNumber(decimalString); // In JS, numbers with exponentials greater than 20 get displayed as an exponential. return bigNumberValue.e > 20 ? bigNumberValue.toPrecision(PRECISION) - : decimalString + : decimalString; } diff --git a/ui/app/helpers/utils/confirm-tx.util.test.js b/ui/app/helpers/utils/confirm-tx.util.test.js index a05090648..e4e6287da 100644 --- a/ui/app/helpers/utils/confirm-tx.util.test.js +++ b/ui/app/helpers/utils/confirm-tx.util.test.js @@ -1,57 +1,57 @@ -import assert from 'assert' -import * as utils from './confirm-tx.util' +import assert from 'assert'; +import * as utils from './confirm-tx.util'; describe('Confirm Transaction utils', function () { describe('increaseLastGasPrice', function () { it('should increase the gasPrice by 10%', function () { - const increasedGasPrice = utils.increaseLastGasPrice('0xa') - assert.strictEqual(increasedGasPrice, '0xb') - }) + const increasedGasPrice = utils.increaseLastGasPrice('0xa'); + assert.strictEqual(increasedGasPrice, '0xb'); + }); it('should prefix the result with 0x', function () { - const increasedGasPrice = utils.increaseLastGasPrice('a') - assert.strictEqual(increasedGasPrice, '0xb') - }) - }) + const increasedGasPrice = utils.increaseLastGasPrice('a'); + assert.strictEqual(increasedGasPrice, '0xb'); + }); + }); describe('hexGreaterThan', function () { it('should return true if the first value is greater than the second value', function () { - assert.strictEqual(utils.hexGreaterThan('0xb', '0xa'), true) - }) + assert.strictEqual(utils.hexGreaterThan('0xb', '0xa'), true); + }); it('should return false if the first value is less than the second value', function () { - assert.strictEqual(utils.hexGreaterThan('0xa', '0xb'), false) - }) + assert.strictEqual(utils.hexGreaterThan('0xa', '0xb'), false); + }); it('should return false if the first value is equal to the second value', function () { - assert.strictEqual(utils.hexGreaterThan('0xa', '0xa'), false) - }) + assert.strictEqual(utils.hexGreaterThan('0xa', '0xa'), false); + }); it('should correctly compare prefixed and non-prefixed hex values', function () { - assert.strictEqual(utils.hexGreaterThan('0xb', 'a'), true) - }) - }) + assert.strictEqual(utils.hexGreaterThan('0xb', 'a'), true); + }); + }); describe('getHexGasTotal', function () { it('should multiply the hex gasLimit and hex gasPrice values together', function () { assert.strictEqual( utils.getHexGasTotal({ gasLimit: '0x5208', gasPrice: '0x3b9aca00' }), '0x1319718a5000', - ) - }) + ); + }); it('should prefix the result with 0x', function () { assert.strictEqual( utils.getHexGasTotal({ gasLimit: '5208', gasPrice: '3b9aca00' }), '0x1319718a5000', - ) - }) - }) + ); + }); + }); describe('addEth', function () { it('should add two values together rounding to 6 decimal places', function () { - assert.strictEqual(utils.addEth('0.12345678', '0'), '0.123457') - }) + assert.strictEqual(utils.addEth('0.12345678', '0'), '0.123457'); + }); it('should add any number of values together rounding to 6 decimal places', function () { assert.strictEqual( @@ -65,14 +65,14 @@ describe('Confirm Transaction utils', function () { '0.0000007', ), '0.123457', - ) - }) - }) + ); + }); + }); describe('addFiat', function () { it('should add two values together rounding to 2 decimal places', function () { - assert.strictEqual(utils.addFiat('0.12345678', '0'), '0.12') - }) + assert.strictEqual(utils.addFiat('0.12345678', '0'), '0.12'); + }); it('should add any number of values together rounding to 2 decimal places', function () { assert.strictEqual( @@ -86,9 +86,9 @@ describe('Confirm Transaction utils', function () { '0.0000007', ), '0.12', - ) - }) - }) + ); + }); + }); describe('getValueFromWeiHex', function () { it('should get the transaction amount in ETH', function () { @@ -97,10 +97,10 @@ describe('Confirm Transaction utils', function () { toCurrency: 'ETH', conversionRate: 468.58, numberOfDecimals: 6, - }) + }); - assert.strictEqual(ethTransactionAmount, '1') - }) + assert.strictEqual(ethTransactionAmount, '1'); + }); it('should get the transaction amount in fiat', function () { const fiatTransactionAmount = utils.getValueFromWeiHex({ @@ -108,11 +108,11 @@ describe('Confirm Transaction utils', function () { toCurrency: 'usd', conversionRate: 468.58, numberOfDecimals: 2, - }) + }); - assert.strictEqual(fiatTransactionAmount, '468.58') - }) - }) + assert.strictEqual(fiatTransactionAmount, '468.58'); + }); + }); describe('getTransactionFee', function () { it('should get the transaction fee in ETH', function () { @@ -121,10 +121,10 @@ describe('Confirm Transaction utils', function () { toCurrency: 'ETH', conversionRate: 468.58, numberOfDecimals: 6, - }) + }); - assert.strictEqual(ethTransactionFee, '0.000021') - }) + assert.strictEqual(ethTransactionFee, '0.000021'); + }); it('should get the transaction fee in fiat', function () { const fiatTransactionFee = utils.getTransactionFee({ @@ -132,16 +132,16 @@ describe('Confirm Transaction utils', function () { toCurrency: 'usd', conversionRate: 468.58, numberOfDecimals: 2, - }) + }); - assert.strictEqual(fiatTransactionFee, '0.01') - }) - }) + assert.strictEqual(fiatTransactionFee, '0.01'); + }); + }); describe('formatCurrency', function () { it('should format USD values', function () { - const value = utils.formatCurrency('123.45', 'usd') - assert.strictEqual(value, '$123.45') - }) - }) -}) + const value = utils.formatCurrency('123.45', 'usd'); + assert.strictEqual(value, '$123.45'); + }); + }); +}); diff --git a/ui/app/helpers/utils/conversion-util.js b/ui/app/helpers/utils/conversion-util.js index ca6bad62b..fac0dd415 100644 --- a/ui/app/helpers/utils/conversion-util.js +++ b/ui/app/helpers/utils/conversion-util.js @@ -21,43 +21,43 @@ * on the accompanying options. */ -import BigNumber from 'bignumber.js' +import BigNumber from 'bignumber.js'; -import ethUtil, { stripHexPrefix } from 'ethereumjs-util' +import ethUtil, { stripHexPrefix } from 'ethereumjs-util'; -const { BN } = ethUtil +const { BN } = ethUtil; // Big Number Constants -const BIG_NUMBER_WEI_MULTIPLIER = new BigNumber('1000000000000000000') -const BIG_NUMBER_GWEI_MULTIPLIER = new BigNumber('1000000000') -const BIG_NUMBER_ETH_MULTIPLIER = new BigNumber('1') +const BIG_NUMBER_WEI_MULTIPLIER = new BigNumber('1000000000000000000'); +const BIG_NUMBER_GWEI_MULTIPLIER = new BigNumber('1000000000'); +const BIG_NUMBER_ETH_MULTIPLIER = new BigNumber('1'); // Setter Maps const toBigNumber = { hex: (n) => new BigNumber(stripHexPrefix(n), 16), dec: (n) => new BigNumber(String(n), 10), BN: (n) => new BigNumber(n.toString(16), 16), -} +}; const toNormalizedDenomination = { WEI: (bigNumber) => bigNumber.div(BIG_NUMBER_WEI_MULTIPLIER), GWEI: (bigNumber) => bigNumber.div(BIG_NUMBER_GWEI_MULTIPLIER), ETH: (bigNumber) => bigNumber.div(BIG_NUMBER_ETH_MULTIPLIER), -} +}; const toSpecifiedDenomination = { WEI: (bigNumber) => bigNumber.times(BIG_NUMBER_WEI_MULTIPLIER).round(), GWEI: (bigNumber) => bigNumber.times(BIG_NUMBER_GWEI_MULTIPLIER).round(9), ETH: (bigNumber) => bigNumber.times(BIG_NUMBER_ETH_MULTIPLIER).round(9), -} +}; const baseChange = { hex: (n) => n.toString(16), dec: (n) => new BigNumber(n).toString(10), BN: (n) => new BN(n.toString(16)), -} +}; // Utility function for checking base types const isValidBase = (base) => { - return Number.isInteger(base) && base > 1 -} + return Number.isInteger(base) && base > 1; +}; /** * Defines the base type of numeric value @@ -99,45 +99,45 @@ const converter = ({ }) => { let convertedValue = fromNumericBase ? toBigNumber[fromNumericBase](value) - : value + : value; if (fromDenomination) { - convertedValue = toNormalizedDenomination[fromDenomination](convertedValue) + convertedValue = toNormalizedDenomination[fromDenomination](convertedValue); } if (fromCurrency !== toCurrency) { if (conversionRate === null || conversionRate === undefined) { throw new Error( `Converting from ${fromCurrency} to ${toCurrency} requires a conversionRate, but one was not provided`, - ) + ); } - let rate = toBigNumber.dec(conversionRate) + let rate = toBigNumber.dec(conversionRate); if (invertConversionRate) { - rate = new BigNumber(1.0).div(conversionRate) + rate = new BigNumber(1.0).div(conversionRate); } - convertedValue = convertedValue.times(rate) + convertedValue = convertedValue.times(rate); } if (toDenomination) { - convertedValue = toSpecifiedDenomination[toDenomination](convertedValue) + convertedValue = toSpecifiedDenomination[toDenomination](convertedValue); } if (numberOfDecimals) { convertedValue = convertedValue.round( numberOfDecimals, BigNumber.ROUND_HALF_DOWN, - ) + ); } if (roundDown) { - convertedValue = convertedValue.round(roundDown, BigNumber.ROUND_DOWN) + convertedValue = convertedValue.round(roundDown, BigNumber.ROUND_DOWN); } if (toNumericBase) { - convertedValue = baseChange[toNumericBase](convertedValue) + convertedValue = baseChange[toNumericBase](convertedValue); } - return convertedValue -} + return convertedValue; +}; const conversionUtil = ( value, @@ -164,107 +164,107 @@ const conversionUtil = ( conversionRate, invertConversionRate, value: value || '0', - }) + }); const getBigNumber = (value, base) => { if (!isValidBase(base)) { - throw new Error('Must specificy valid base') + throw new Error('Must specificy valid base'); } // We don't include 'number' here, because BigNumber will throw if passed // a number primitive it considers unsafe. if (typeof value === 'string' || value instanceof BigNumber) { - return new BigNumber(value, base) + return new BigNumber(value, base); } - return new BigNumber(String(value), base) -} + return new BigNumber(String(value), base); +}; const addCurrencies = (a, b, options = {}) => { - const { aBase, bBase, ...conversionOptions } = options + const { aBase, bBase, ...conversionOptions } = options; if (!isValidBase(aBase) || !isValidBase(bBase)) { - throw new Error('Must specify valid aBase and bBase') + throw new Error('Must specify valid aBase and bBase'); } - const value = getBigNumber(a, aBase).add(getBigNumber(b, bBase)) + const value = getBigNumber(a, aBase).add(getBigNumber(b, bBase)); return converter({ value, ...conversionOptions, - }) -} + }); +}; const subtractCurrencies = (a, b, options = {}) => { - const { aBase, bBase, ...conversionOptions } = options + const { aBase, bBase, ...conversionOptions } = options; if (!isValidBase(aBase) || !isValidBase(bBase)) { - throw new Error('Must specify valid aBase and bBase') + throw new Error('Must specify valid aBase and bBase'); } - const value = getBigNumber(a, aBase).minus(getBigNumber(b, bBase)) + const value = getBigNumber(a, aBase).minus(getBigNumber(b, bBase)); return converter({ value, ...conversionOptions, - }) -} + }); +}; const multiplyCurrencies = (a, b, options = {}) => { - const { multiplicandBase, multiplierBase, ...conversionOptions } = options + const { multiplicandBase, multiplierBase, ...conversionOptions } = options; if (!isValidBase(multiplicandBase) || !isValidBase(multiplierBase)) { - throw new Error('Must specify valid multiplicandBase and multiplierBase') + throw new Error('Must specify valid multiplicandBase and multiplierBase'); } const value = getBigNumber(a, multiplicandBase).times( getBigNumber(b, multiplierBase), - ) + ); return converter({ value, ...conversionOptions, - }) -} + }); +}; const conversionGreaterThan = ({ ...firstProps }, { ...secondProps }) => { - const firstValue = converter({ ...firstProps }) - const secondValue = converter({ ...secondProps }) + const firstValue = converter({ ...firstProps }); + const secondValue = converter({ ...secondProps }); - return firstValue.gt(secondValue) -} + return firstValue.gt(secondValue); +}; const conversionLessThan = ({ ...firstProps }, { ...secondProps }) => { - const firstValue = converter({ ...firstProps }) - const secondValue = converter({ ...secondProps }) + const firstValue = converter({ ...firstProps }); + const secondValue = converter({ ...secondProps }); - return firstValue.lt(secondValue) -} + return firstValue.lt(secondValue); +}; const conversionMax = ({ ...firstProps }, { ...secondProps }) => { const firstIsGreater = conversionGreaterThan( { ...firstProps }, { ...secondProps }, - ) + ); - return firstIsGreater ? firstProps.value : secondProps.value -} + return firstIsGreater ? firstProps.value : secondProps.value; +}; const conversionGTE = ({ ...firstProps }, { ...secondProps }) => { - const firstValue = converter({ ...firstProps }) - const secondValue = converter({ ...secondProps }) - return firstValue.greaterThanOrEqualTo(secondValue) -} + const firstValue = converter({ ...firstProps }); + const secondValue = converter({ ...secondProps }); + return firstValue.greaterThanOrEqualTo(secondValue); +}; const conversionLTE = ({ ...firstProps }, { ...secondProps }) => { - const firstValue = converter({ ...firstProps }) - const secondValue = converter({ ...secondProps }) - return firstValue.lessThanOrEqualTo(secondValue) -} + const firstValue = converter({ ...firstProps }); + const secondValue = converter({ ...secondProps }); + return firstValue.lessThanOrEqualTo(secondValue); +}; const toNegative = (n, options = {}) => { - return multiplyCurrencies(n, -1, options) -} + return multiplyCurrencies(n, -1, options); +}; export { conversionUtil, @@ -277,4 +277,4 @@ export { conversionMax, toNegative, subtractCurrencies, -} +}; diff --git a/ui/app/helpers/utils/conversion-util.test.js b/ui/app/helpers/utils/conversion-util.test.js index 5e05f6727..bb1f2a690 100644 --- a/ui/app/helpers/utils/conversion-util.test.js +++ b/ui/app/helpers/utils/conversion-util.test.js @@ -1,6 +1,6 @@ -import assert from 'assert' -import BigNumber from 'bignumber.js' -import { addCurrencies, conversionUtil } from './conversion-util' +import assert from 'assert'; +import BigNumber from 'bignumber.js'; +import { addCurrencies, conversionUtil } from './conversion-util'; describe('conversion utils', function () { describe('addCurrencies()', function () { @@ -8,44 +8,44 @@ describe('conversion utils', function () { const result = addCurrencies(3, 9, { aBase: 10, bBase: 10, - }) - assert.strictEqual(result.toNumber(), 12) - }) + }); + assert.strictEqual(result.toNumber(), 12); + }); it('add decimals', function () { const result = addCurrencies(1.3, 1.9, { aBase: 10, bBase: 10, - }) - assert.strictEqual(result.toNumber(), 3.2) - }) + }); + assert.strictEqual(result.toNumber(), 3.2); + }); it('add repeating decimals', function () { const result = addCurrencies(1 / 3, 1 / 9, { aBase: 10, bBase: 10, - }) - assert.strictEqual(result.toNumber(), 0.4444444444444444) - }) - }) + }); + assert.strictEqual(result.toNumber(), 0.4444444444444444); + }); + }); describe('conversionUtil', function () { it('Returns expected types', function () { const conv1 = conversionUtil(1000000000000000000, { fromNumericBase: 'dec', toNumericBase: 'hex', - }) + }); const conv2 = conversionUtil(1, { fromNumericBase: 'dec', fromDenomination: 'ETH', toDenomination: 'WEI', - }) + }); assert( typeof conv1 === 'string', 'conversion 1 should return type string', - ) - assert(conv2 instanceof BigNumber, 'conversion 2 should be a BigNumber') - }) + ); + assert(conv2 instanceof BigNumber, 'conversion 2 should be a BigNumber'); + }); it('Converts from dec to hex', function () { assert.strictEqual( conversionUtil('1000000000000000000', { @@ -53,15 +53,15 @@ describe('conversion utils', function () { toNumericBase: 'hex', }), 'de0b6b3a7640000', - ) + ); assert.strictEqual( conversionUtil('1500000000000000000', { fromNumericBase: 'dec', toNumericBase: 'hex', }), '14d1120d7b160000', - ) - }) + ); + }); it('Converts hex formatted numbers to dec', function () { assert.strictEqual( conversionUtil('0xde0b6b3a7640000', { @@ -69,15 +69,15 @@ describe('conversion utils', function () { toNumericBase: 'dec', }), '1000000000000000000', - ) + ); assert.strictEqual( conversionUtil('0x14d1120d7b160000', { fromNumericBase: 'hex', toNumericBase: 'dec', }), '1500000000000000000', - ) - }) + ); + }); it('Converts WEI to ETH', function () { assert.strictEqual( conversionUtil('0xde0b6b3a7640000', { @@ -87,7 +87,7 @@ describe('conversion utils', function () { toDenomination: 'ETH', }), '1', - ) + ); assert.strictEqual( conversionUtil('0x14d1120d7b160000', { fromNumericBase: 'hex', @@ -96,8 +96,8 @@ describe('conversion utils', function () { toDenomination: 'ETH', }), '1.5', - ) - }) + ); + }); it('Converts ETH to WEI', function () { assert.strictEqual( conversionUtil('1', { @@ -106,7 +106,7 @@ describe('conversion utils', function () { toDenomination: 'WEI', }).toNumber(), 1000000000000000000, - ) + ); assert.strictEqual( conversionUtil('1.5', { fromNumericBase: 'dec', @@ -114,8 +114,8 @@ describe('conversion utils', function () { toDenomination: 'WEI', }).toNumber(), 1500000000000000000, - ) - }) + ); + }); it('Converts ETH to GWEI', function () { assert.strictEqual( conversionUtil('1', { @@ -124,7 +124,7 @@ describe('conversion utils', function () { toDenomination: 'GWEI', }).toNumber(), 1000000000, - ) + ); assert.strictEqual( conversionUtil('1.5', { fromNumericBase: 'dec', @@ -132,8 +132,8 @@ describe('conversion utils', function () { toDenomination: 'GWEI', }).toNumber(), 1500000000, - ) - }) + ); + }); it('Converts ETH to USD', function () { assert.strictEqual( conversionUtil('1', { @@ -144,7 +144,7 @@ describe('conversion utils', function () { numberOfDecimals: 2, }), '468.58', - ) + ); assert.strictEqual( conversionUtil('1.5', { fromNumericBase: 'dec', @@ -154,8 +154,8 @@ describe('conversion utils', function () { numberOfDecimals: 2, }), '702.87', - ) - }) + ); + }); it('Converts USD to ETH', function () { assert.strictEqual( conversionUtil('468.58', { @@ -167,7 +167,7 @@ describe('conversion utils', function () { invertConversionRate: true, }), '1', - ) + ); assert.strictEqual( conversionUtil('702.87', { fromNumericBase: 'dec', @@ -178,7 +178,7 @@ describe('conversion utils', function () { invertConversionRate: true, }), '1.5', - ) - }) - }) -}) + ); + }); + }); +}); diff --git a/ui/app/helpers/utils/conversions.util.js b/ui/app/helpers/utils/conversions.util.js index 9e0f97681..ce4fe8c51 100644 --- a/ui/app/helpers/utils/conversions.util.js +++ b/ui/app/helpers/utils/conversions.util.js @@ -1,28 +1,28 @@ -import { ETH, GWEI, WEI } from '../constants/common' -import { addHexPrefix } from '../../../../app/scripts/lib/util' +import { ETH, GWEI, WEI } from '../constants/common'; +import { addHexPrefix } from '../../../../app/scripts/lib/util'; import { conversionUtil, addCurrencies, subtractCurrencies, -} from './conversion-util' -import { formatCurrency } from './confirm-tx.util' +} from './conversion-util'; +import { formatCurrency } from './confirm-tx.util'; export function bnToHex(inputBn) { - return addHexPrefix(inputBn.toString(16)) + return addHexPrefix(inputBn.toString(16)); } export function hexToDecimal(hexValue) { return conversionUtil(hexValue, { fromNumericBase: 'hex', toNumericBase: 'dec', - }) + }); } export function decimalToHex(decimal) { return conversionUtil(decimal, { fromNumericBase: 'dec', toNumericBase: 'hex', - }) + }); } export function getEthConversionFromWeiHex({ @@ -31,9 +31,9 @@ export function getEthConversionFromWeiHex({ conversionRate, numberOfDecimals = 6, }) { - const denominations = [fromCurrency, GWEI, WEI] + const denominations = [fromCurrency, GWEI, WEI]; - let nonZeroDenomination + let nonZeroDenomination; for (let i = 0; i < denominations.length; i++) { const convertedValue = getValueFromWeiHex({ @@ -43,15 +43,15 @@ export function getEthConversionFromWeiHex({ toCurrency: fromCurrency, numberOfDecimals, toDenomination: denominations[i], - }) + }); if (convertedValue !== '0' || i === denominations.length - 1) { - nonZeroDenomination = `${convertedValue} ${denominations[i]}` - break + nonZeroDenomination = `${convertedValue} ${denominations[i]}`; + break; } } - return nonZeroDenomination + return nonZeroDenomination; } export function getValueFromWeiHex({ @@ -71,7 +71,7 @@ export function getValueFromWeiHex({ fromDenomination: WEI, toDenomination, conversionRate, - }) + }); } export function getWeiHexFromDecimalValue({ @@ -90,7 +90,7 @@ export function getWeiHexFromDecimalValue({ invertConversionRate, fromDenomination, toDenomination: WEI, - }) + }); } export function addHexWEIsToDec(aHexWEI, bHexWEI) { @@ -99,7 +99,7 @@ export function addHexWEIsToDec(aHexWEI, bHexWEI) { bBase: 16, fromDenomination: 'WEI', numberOfDecimals: 6, - }) + }); } export function subtractHexWEIsToDec(aHexWEI, bHexWEI) { @@ -108,7 +108,7 @@ export function subtractHexWEIsToDec(aHexWEI, bHexWEI) { bBase: 16, fromDenomination: 'WEI', numberOfDecimals: 6, - }) + }); } export function decEthToConvertedCurrency( @@ -123,7 +123,7 @@ export function decEthToConvertedCurrency( toCurrency: convertedCurrency, numberOfDecimals: 2, conversionRate, - }) + }); } export function decGWEIToHexWEI(decGWEI) { @@ -132,7 +132,7 @@ export function decGWEIToHexWEI(decGWEI) { toNumericBase: 'hex', fromDenomination: 'GWEI', toDenomination: 'WEI', - }) + }); } export function hexWEIToDecGWEI(decGWEI) { @@ -141,7 +141,7 @@ export function hexWEIToDecGWEI(decGWEI) { toNumericBase: 'dec', fromDenomination: 'WEI', toDenomination: 'GWEI', - }) + }); } export function decETHToDecWEI(decEth) { @@ -150,7 +150,7 @@ export function decETHToDecWEI(decEth) { toNumericBase: 'dec', fromDenomination: 'ETH', toDenomination: 'WEI', - }) + }); } export function hexWEIToDecETH(hexWEI) { @@ -159,7 +159,7 @@ export function hexWEIToDecETH(hexWEI) { toNumericBase: 'dec', fromDenomination: 'WEI', toDenomination: 'ETH', - }) + }); } export function addHexes(aHexWEI, bHexWEI) { @@ -168,11 +168,11 @@ export function addHexes(aHexWEI, bHexWEI) { bBase: 16, toNumericBase: 'hex', numberOfDecimals: 6, - }) + }); } export function sumHexWEIs(hexWEIs) { - return hexWEIs.filter(Boolean).reduce(addHexes) + return hexWEIs.filter(Boolean).reduce(addHexes); } export function sumHexWEIsToUnformattedFiat( @@ -180,7 +180,7 @@ export function sumHexWEIsToUnformattedFiat( convertedCurrency, conversionRate, ) { - const hexWEIsSum = sumHexWEIs(hexWEIs) + const hexWEIsSum = sumHexWEIs(hexWEIs); const convertedTotal = decEthToConvertedCurrency( getValueFromWeiHex({ value: hexWEIsSum, @@ -189,8 +189,8 @@ export function sumHexWEIsToUnformattedFiat( }), convertedCurrency, conversionRate, - ) - return convertedTotal + ); + return convertedTotal; } export function sumHexWEIsToRenderableFiat( @@ -202,6 +202,6 @@ export function sumHexWEIsToRenderableFiat( hexWEIs, convertedCurrency, conversionRate, - ) - return formatCurrency(convertedTotal, convertedCurrency) + ); + return formatCurrency(convertedTotal, convertedCurrency); } diff --git a/ui/app/helpers/utils/conversions.util.test.js b/ui/app/helpers/utils/conversions.util.test.js index 6ae58ca83..6fe4159ea 100644 --- a/ui/app/helpers/utils/conversions.util.test.js +++ b/ui/app/helpers/utils/conversions.util.test.js @@ -1,6 +1,6 @@ -import assert from 'assert' -import { ETH } from '../constants/common' -import * as utils from './conversions.util' +import assert from 'assert'; +import { ETH } from '../constants/common'; +import * as utils from './conversions.util'; describe('conversion utils', function () { describe('getWeiHexFromDecimalValue', function () { @@ -9,35 +9,35 @@ describe('conversion utils', function () { value: '0', fromCurrency: ETH, fromDenomination: ETH, - }) - assert.strictEqual(weiValue, '0') - }) - }) + }); + assert.strictEqual(weiValue, '0'); + }); + }); describe('decETHToDecWEI', function () { it('should correctly convert 1 ETH to WEI', function () { - const weiValue = utils.decETHToDecWEI('1') - assert.strictEqual(weiValue, '1000000000000000000') - }) + const weiValue = utils.decETHToDecWEI('1'); + assert.strictEqual(weiValue, '1000000000000000000'); + }); it('should correctly convert 0.000000000000000001 ETH to WEI', function () { - const weiValue = utils.decETHToDecWEI('0.000000000000000001') - assert.strictEqual(weiValue, '1') - }) + const weiValue = utils.decETHToDecWEI('0.000000000000000001'); + assert.strictEqual(weiValue, '1'); + }); it('should correctly convert 1000000.000000000000000001 ETH to WEI', function () { - const weiValue = utils.decETHToDecWEI('1000000.000000000000000001') - assert.strictEqual(weiValue, '1000000000000000000000001') - }) + const weiValue = utils.decETHToDecWEI('1000000.000000000000000001'); + assert.strictEqual(weiValue, '1000000000000000000000001'); + }); it('should correctly convert 9876.543210 ETH to WEI', function () { - const weiValue = utils.decETHToDecWEI('9876.543210') - assert.strictEqual(weiValue, '9876543210000000000000') - }) + const weiValue = utils.decETHToDecWEI('9876.543210'); + assert.strictEqual(weiValue, '9876543210000000000000'); + }); it('should correctly convert 1.0000000000000000 ETH to WEI', function () { - const weiValue = utils.decETHToDecWEI('1.0000000000000000') - assert.strictEqual(weiValue, '1000000000000000000') - }) - }) -}) + const weiValue = utils.decETHToDecWEI('1.0000000000000000'); + assert.strictEqual(weiValue, '1000000000000000000'); + }); + }); +}); diff --git a/ui/app/helpers/utils/fetch-with-cache.js b/ui/app/helpers/utils/fetch-with-cache.js index a903680c4..6dc377593 100644 --- a/ui/app/helpers/utils/fetch-with-cache.js +++ b/ui/app/helpers/utils/fetch-with-cache.js @@ -1,5 +1,5 @@ -import { getStorageItem, setStorageItem } from '../../../lib/storage-helpers' -import getFetchWithTimeout from '../../../../shared/modules/fetch-with-timeout' +import { getStorageItem, setStorageItem } from '../../../lib/storage-helpers'; +import getFetchWithTimeout from '../../../../shared/modules/fetch-with-timeout'; const fetchWithCache = async ( url, @@ -10,46 +10,46 @@ const fetchWithCache = async ( fetchOptions.body || (fetchOptions.method && fetchOptions.method !== 'GET') ) { - throw new Error('fetchWithCache only supports GET requests') + throw new Error('fetchWithCache only supports GET requests'); } if (!(fetchOptions.headers instanceof window.Headers)) { - fetchOptions.headers = new window.Headers(fetchOptions.headers) + fetchOptions.headers = new window.Headers(fetchOptions.headers); } if ( fetchOptions.headers.has('Content-Type') && fetchOptions.headers.get('Content-Type') !== 'application/json' ) { - throw new Error('fetchWithCache only supports JSON responses') + throw new Error('fetchWithCache only supports JSON responses'); } - const currentTime = Date.now() - const cacheKey = `cachedFetch:${url}` - const { cachedResponse, cachedTime } = (await getStorageItem(cacheKey)) || {} + const currentTime = Date.now(); + const cacheKey = `cachedFetch:${url}`; + const { cachedResponse, cachedTime } = (await getStorageItem(cacheKey)) || {}; if (cachedResponse && currentTime - cachedTime < cacheRefreshTime) { - return cachedResponse + return cachedResponse; } - fetchOptions.headers.set('Content-Type', 'application/json') - const fetchWithTimeout = getFetchWithTimeout(timeout) + fetchOptions.headers.set('Content-Type', 'application/json'); + const fetchWithTimeout = getFetchWithTimeout(timeout); const response = await fetchWithTimeout(url, { referrerPolicy: 'no-referrer-when-downgrade', body: null, method: 'GET', mode: 'cors', ...fetchOptions, - }) + }); if (!response.ok) { throw new Error( `Fetch failed with status '${response.status}': '${response.statusText}'`, - ) + ); } - const responseJson = await response.json() + const responseJson = await response.json(); const cacheEntry = { cachedResponse: responseJson, cachedTime: currentTime, - } + }; - await setStorageItem(cacheKey, cacheEntry) - return responseJson -} + await setStorageItem(cacheKey, cacheEntry); + return responseJson; +}; -export default fetchWithCache +export default fetchWithCache; diff --git a/ui/app/helpers/utils/fetch-with-cache.test.js b/ui/app/helpers/utils/fetch-with-cache.test.js index 3c98cadba..0b6dc3da3 100644 --- a/ui/app/helpers/utils/fetch-with-cache.test.js +++ b/ui/app/helpers/utils/fetch-with-cache.test.js @@ -1,79 +1,79 @@ -import assert from 'assert' -import nock from 'nock' -import sinon from 'sinon' -import proxyquire from 'proxyquire' +import assert from 'assert'; +import nock from 'nock'; +import sinon from 'sinon'; +import proxyquire from 'proxyquire'; -const fakeStorage = {} +const fakeStorage = {}; const fetchWithCache = proxyquire('./fetch-with-cache', { '../../../lib/storage-helpers': fakeStorage, -}).default +}).default; describe('Fetch with cache', function () { beforeEach(function () { - fakeStorage.getStorageItem = sinon.stub() - fakeStorage.setStorageItem = sinon.stub() - }) + fakeStorage.getStorageItem = sinon.stub(); + fakeStorage.setStorageItem = sinon.stub(); + }); afterEach(function () { - sinon.restore() - nock.cleanAll() - }) + sinon.restore(); + nock.cleanAll(); + }); it('fetches a url', async function () { nock('https://fetchwithcache.metamask.io') .get('/price') - .reply(200, '{"average": 1}') + .reply(200, '{"average": 1}'); const response = await fetchWithCache( 'https://fetchwithcache.metamask.io/price', - ) + ); assert.deepStrictEqual(response, { average: 1, - }) - }) + }); + }); it('returns cached response', async function () { nock('https://fetchwithcache.metamask.io') .get('/price') - .reply(200, '{"average": 2}') + .reply(200, '{"average": 2}'); fakeStorage.getStorageItem.returns({ cachedResponse: { average: 1 }, cachedTime: Date.now(), - }) + }); const response = await fetchWithCache( 'https://fetchwithcache.metamask.io/price', - ) + ); assert.deepStrictEqual(response, { average: 1, - }) - }) + }); + }); it('fetches URL again after cache refresh time has passed', async function () { nock('https://fetchwithcache.metamask.io') .get('/price') - .reply(200, '{"average": 3}') + .reply(200, '{"average": 3}'); fakeStorage.getStorageItem.returns({ cachedResponse: { average: 1 }, cachedTime: Date.now() - 1000, - }) + }); const response = await fetchWithCache( 'https://fetchwithcache.metamask.io/price', {}, { cacheRefreshTime: 123 }, - ) + ); assert.deepStrictEqual(response, { average: 3, - }) - }) + }); + }); it('should abort the request when the custom timeout is hit', async function () { nock('https://fetchwithcache.metamask.io') .get('/price') .delay(100) - .reply(200, '{"average": 4}') + .reply(200, '{"average": 4}'); await assert.rejects( () => @@ -83,45 +83,45 @@ describe('Fetch with cache', function () { { timeout: 20 }, ), { name: 'AbortError', message: 'Aborted' }, - ) - }) + ); + }); it('throws when the response is unsuccessful', async function () { nock('https://fetchwithcache.metamask.io') .get('/price') - .reply(500, '{"average": 6}') + .reply(500, '{"average": 6}'); await assert.rejects(() => fetchWithCache('https://fetchwithcache.metamask.io/price'), - ) - }) + ); + }); it('throws when a POST request is attempted', async function () { nock('https://fetchwithcache.metamask.io') .post('/price') - .reply(200, '{"average": 7}') + .reply(200, '{"average": 7}'); await assert.rejects(() => fetchWithCache('https://fetchwithcache.metamask.io/price', { method: 'POST', }), - ) - }) + ); + }); it('throws when the request has a truthy body', async function () { nock('https://fetchwithcache.metamask.io') .get('/price') - .reply(200, '{"average": 8}') + .reply(200, '{"average": 8}'); await assert.rejects(() => fetchWithCache('https://fetchwithcache.metamask.io/price', { body: 1 }), - ) - }) + ); + }); it('throws when the request has an invalid Content-Type header', async function () { nock('https://fetchwithcache.metamask.io') .get('/price') - .reply(200, '{"average": 9}') + .reply(200, '{"average": 9}'); await assert.rejects( () => @@ -129,22 +129,22 @@ describe('Fetch with cache', function () { headers: { 'Content-Type': 'text/plain' }, }), { message: 'fetchWithCache only supports JSON responses' }, - ) - }) + ); + }); it('should correctly cache responses from interwoven requests', async function () { nock('https://fetchwithcache.metamask.io') .get('/foo') - .reply(200, '{"average": 9}') + .reply(200, '{"average": 9}'); nock('https://fetchwithcache.metamask.io') .get('/bar') - .reply(200, '{"average": 9}') + .reply(200, '{"average": 9}'); - const testCache = {} - fakeStorage.getStorageItem.callsFake((key) => testCache[key]) + const testCache = {}; + fakeStorage.getStorageItem.callsFake((key) => testCache[key]); fakeStorage.setStorageItem.callsFake((key, value) => { - testCache[key] = value - }) + testCache[key] = value; + }); await Promise.all([ fetchWithCache( @@ -157,17 +157,17 @@ describe('Fetch with cache', function () { {}, { cacheRefreshTime: 123 }, ), - ]) + ]); assert.deepStrictEqual( testCache['cachedFetch:https://fetchwithcache.metamask.io/foo'] .cachedResponse, { average: 9 }, - ) + ); assert.deepStrictEqual( testCache['cachedFetch:https://fetchwithcache.metamask.io/bar'] .cachedResponse, { average: 9 }, - ) - }) -}) + ); + }); +}); diff --git a/ui/app/helpers/utils/formatters.js b/ui/app/helpers/utils/formatters.js index f4a120044..c75e30f1c 100644 --- a/ui/app/helpers/utils/formatters.js +++ b/ui/app/helpers/utils/formatters.js @@ -1,3 +1,3 @@ export function formatETHFee(ethFee) { - return `${ethFee} ETH` + return `${ethFee} ETH`; } diff --git a/ui/app/helpers/utils/i18n-helper.js b/ui/app/helpers/utils/i18n-helper.js index bb8932683..ea2d7049f 100644 --- a/ui/app/helpers/utils/i18n-helper.js +++ b/ui/app/helpers/utils/i18n-helper.js @@ -1,15 +1,15 @@ // cross-browser connection to extension i18n API -import React from 'react' -import log from 'loglevel' -import * as Sentry from '@sentry/browser' +import React from 'react'; +import log from 'loglevel'; +import * as Sentry from '@sentry/browser'; -import getFetchWithTimeout from '../../../../shared/modules/fetch-with-timeout' +import getFetchWithTimeout from '../../../../shared/modules/fetch-with-timeout'; -const fetchWithTimeout = getFetchWithTimeout(30000) +const fetchWithTimeout = getFetchWithTimeout(30000); -const warned = {} -const missingMessageErrors = {} -const missingSubstitutionErrors = {} +const warned = {}; +const missingMessageErrors = {}; +const missingSubstitutionErrors = {}; /** * Returns a localized message for the given key @@ -21,110 +21,110 @@ const missingSubstitutionErrors = {} */ export const getMessage = (localeCode, localeMessages, key, substitutions) => { if (!localeMessages) { - return null + return null; } if (!localeMessages[key]) { if (localeCode === 'en') { if (!missingMessageErrors[key]) { missingMessageErrors[key] = new Error( `Unable to find value of key "${key}" for locale "${localeCode}"`, - ) - Sentry.captureException(missingMessageErrors[key]) - log.error(missingMessageErrors[key]) + ); + Sentry.captureException(missingMessageErrors[key]); + log.error(missingMessageErrors[key]); if (process.env.IN_TEST === 'true') { - throw missingMessageErrors[key] + throw missingMessageErrors[key]; } } } else if (!warned[localeCode] || !warned[localeCode][key]) { if (!warned[localeCode]) { - warned[localeCode] = {} + warned[localeCode] = {}; } - warned[localeCode][key] = true + warned[localeCode][key] = true; log.warn( `Translator - Unable to find value of key "${key}" for locale "${localeCode}"`, - ) + ); } - return null + return null; } - const entry = localeMessages[key] - let phrase = entry.message + const entry = localeMessages[key]; + let phrase = entry.message; - const hasSubstitutions = Boolean(substitutions && substitutions.length) + const hasSubstitutions = Boolean(substitutions && substitutions.length); const hasReactSubstitutions = hasSubstitutions && substitutions.some( (element) => element !== null && (typeof element === 'function' || typeof element === 'object'), - ) + ); // perform substitutions if (hasSubstitutions) { - const parts = phrase.split(/(\$\d)/gu) + const parts = phrase.split(/(\$\d)/gu); const substitutedParts = parts.map((part) => { - const subMatch = part.match(/\$(\d)/u) + const subMatch = part.match(/\$(\d)/u); if (!subMatch) { - return part + return part; } - const substituteIndex = Number(subMatch[1]) - 1 + const substituteIndex = Number(subMatch[1]) - 1; if ( (substitutions[substituteIndex] === null || substitutions[substituteIndex] === undefined) && !missingSubstitutionErrors[localeCode]?.[key] ) { if (!missingSubstitutionErrors[localeCode]) { - missingSubstitutionErrors[localeCode] = {} + missingSubstitutionErrors[localeCode] = {}; } - missingSubstitutionErrors[localeCode][key] = true + missingSubstitutionErrors[localeCode][key] = true; const error = new Error( `Insufficient number of substitutions for key "${key}" with locale "${localeCode}"`, - ) - log.error(error) - Sentry.captureException(error) + ); + log.error(error); + Sentry.captureException(error); } - return substitutions[substituteIndex] - }) + return substitutions[substituteIndex]; + }); phrase = hasReactSubstitutions ? ( {substitutedParts} ) : ( substitutedParts.join('') - ) + ); } - return phrase -} + return phrase; +}; export async function fetchLocale(localeCode) { try { const response = await fetchWithTimeout( `./_locales/${localeCode}/messages.json`, - ) - return await response.json() + ); + return await response.json(); } catch (error) { - log.error(`failed to fetch ${localeCode} locale because of ${error}`) - return {} + log.error(`failed to fetch ${localeCode} locale because of ${error}`); + return {}; } } -const relativeTimeFormatLocaleData = new Set() +const relativeTimeFormatLocaleData = new Set(); export async function loadRelativeTimeFormatLocaleData(localeCode) { - const languageTag = localeCode.split('_')[0] + const languageTag = localeCode.split('_')[0]; if ( Intl.RelativeTimeFormat && typeof Intl.RelativeTimeFormat.__addLocaleData === 'function' && !relativeTimeFormatLocaleData.has(languageTag) ) { - const localeData = await fetchRelativeTimeFormatData(languageTag) - Intl.RelativeTimeFormat.__addLocaleData(localeData) + const localeData = await fetchRelativeTimeFormatData(languageTag); + Intl.RelativeTimeFormat.__addLocaleData(localeData); } } async function fetchRelativeTimeFormatData(languageTag) { const response = await fetchWithTimeout( `./intl/${languageTag}/relative-time-format-data.json`, - ) - return await response.json() + ); + return await response.json(); } diff --git a/ui/app/helpers/utils/i18n-helper.test.js b/ui/app/helpers/utils/i18n-helper.test.js index 1c908f7f3..d02053315 100644 --- a/ui/app/helpers/utils/i18n-helper.test.js +++ b/ui/app/helpers/utils/i18n-helper.test.js @@ -1,30 +1,30 @@ -import assert from 'assert' -import React from 'react' -import { shallow } from 'enzyme' -import { getMessage } from './i18n-helper' +import assert from 'assert'; +import React from 'react'; +import { shallow } from 'enzyme'; +import { getMessage } from './i18n-helper'; describe('i18n helper', function () { - const TEST_LOCALE_CODE = 'TEST_LOCALE_CODE' + const TEST_LOCALE_CODE = 'TEST_LOCALE_CODE'; - const TEST_KEY_1 = 'TEST_KEY_1' - const TEST_KEY_2 = 'TEST_KEY_2' - const TEST_KEY_3 = 'TEST_KEY_3' - const TEST_KEY_4 = 'TEST_KEY_4' - const TEST_KEY_5 = 'TEST_KEY_5' - const TEST_KEY_6 = 'TEST_KEY_6' - const TEST_KEY_6_HELPER = 'TEST_KEY_6_HELPER' - const TEST_KEY_7 = 'TEST_KEY_7' - const TEST_KEY_7_HELPER_1 = 'TEST_KEY_7_HELPER_1' - const TEST_KEY_7_HELPER_2 = 'TEST_KEY_7_HELPER_2' - const TEST_KEY_8 = 'TEST_KEY_8' - const TEST_KEY_8_HELPER_1 = 'TEST_KEY_8_HELPER_1' - const TEST_KEY_8_HELPER_2 = 'TEST_KEY_8_HELPER_2' + const TEST_KEY_1 = 'TEST_KEY_1'; + const TEST_KEY_2 = 'TEST_KEY_2'; + const TEST_KEY_3 = 'TEST_KEY_3'; + const TEST_KEY_4 = 'TEST_KEY_4'; + const TEST_KEY_5 = 'TEST_KEY_5'; + const TEST_KEY_6 = 'TEST_KEY_6'; + const TEST_KEY_6_HELPER = 'TEST_KEY_6_HELPER'; + const TEST_KEY_7 = 'TEST_KEY_7'; + const TEST_KEY_7_HELPER_1 = 'TEST_KEY_7_HELPER_1'; + const TEST_KEY_7_HELPER_2 = 'TEST_KEY_7_HELPER_2'; + const TEST_KEY_8 = 'TEST_KEY_8'; + const TEST_KEY_8_HELPER_1 = 'TEST_KEY_8_HELPER_1'; + const TEST_KEY_8_HELPER_2 = 'TEST_KEY_8_HELPER_2'; - const TEST_SUBSTITUTION_1 = 'TEST_SUBSTITUTION_1' - const TEST_SUBSTITUTION_2 = 'TEST_SUBSTITUTION_2' - const TEST_SUBSTITUTION_3 = 'TEST_SUBSTITUTION_3' - const TEST_SUBSTITUTION_4 = 'TEST_SUBSTITUTION_4' - const TEST_SUBSTITUTION_5 = 'TEST_SUBSTITUTION_5' + const TEST_SUBSTITUTION_1 = 'TEST_SUBSTITUTION_1'; + const TEST_SUBSTITUTION_2 = 'TEST_SUBSTITUTION_2'; + const TEST_SUBSTITUTION_3 = 'TEST_SUBSTITUTION_3'; + const TEST_SUBSTITUTION_4 = 'TEST_SUBSTITUTION_4'; + const TEST_SUBSTITUTION_5 = 'TEST_SUBSTITUTION_5'; const testLocaleMessages = { [TEST_KEY_1]: { @@ -68,56 +68,56 @@ describe('i18n helper', function () { [TEST_KEY_8_HELPER_2]: { message: TEST_SUBSTITUTION_4, }, - } - const t = getMessage.bind(null, TEST_LOCALE_CODE, testLocaleMessages) + }; + const t = getMessage.bind(null, TEST_LOCALE_CODE, testLocaleMessages); const TEST_SUBSTITUTION_6 = (
    {t(TEST_KEY_6_HELPER)}
    - ) + ); const TEST_SUBSTITUTION_7_1 = (
    {t(TEST_KEY_7_HELPER_1)}
    - ) + ); const TEST_SUBSTITUTION_7_2 = (
    {t(TEST_KEY_7_HELPER_2)}
    - ) + ); const TEST_SUBSTITUTION_8_1 = (
    {t(TEST_KEY_8_HELPER_1)}
    - ) + ); const TEST_SUBSTITUTION_8_2 = (
    {t(TEST_KEY_8_HELPER_2)}
    - ) + ); describe('getMessage', function () { it('should return the exact message paired with key if there are no substitutions', function () { - const result = t(TEST_KEY_1) - assert.strictEqual(result, 'This is a simple message.') - }) + const result = t(TEST_KEY_1); + assert.strictEqual(result, 'This is a simple message.'); + }); it('should return the correct message when a single non-react substitution is made', function () { - const result = t(TEST_KEY_2, [TEST_SUBSTITUTION_1]) + const result = t(TEST_KEY_2, [TEST_SUBSTITUTION_1]); assert.strictEqual( result, `This is a message with a single non-react substitution ${TEST_SUBSTITUTION_1}.`, - ) - }) + ); + }); it('should return the correct message when two non-react substitutions are made', function () { - const result = t(TEST_KEY_3, [TEST_SUBSTITUTION_1, TEST_SUBSTITUTION_2]) + const result = t(TEST_KEY_3, [TEST_SUBSTITUTION_1, TEST_SUBSTITUTION_2]); assert.strictEqual( result, `This is a message with two non-react substitutions ${TEST_SUBSTITUTION_1} and ${TEST_SUBSTITUTION_2}.`, - ) - }) + ); + }); it('should return the correct message when multiple non-react substitutions are made', function () { const result = t(TEST_KEY_4, [ @@ -126,41 +126,41 @@ describe('i18n helper', function () { TEST_SUBSTITUTION_3, TEST_SUBSTITUTION_4, TEST_SUBSTITUTION_5, - ]) + ]); assert.strictEqual( result, `${TEST_SUBSTITUTION_1} - ${TEST_SUBSTITUTION_2} - ${TEST_SUBSTITUTION_3} - ${TEST_SUBSTITUTION_4} - ${TEST_SUBSTITUTION_5}`, - ) - }) + ); + }); it('should correctly render falsey substitutions', function () { - const result = t(TEST_KEY_4, [0, -0, '', false, NaN]) - assert.strictEqual(result, '0 - 0 - - false - NaN') - }) + const result = t(TEST_KEY_4, [0, -0, '', false, NaN]); + assert.strictEqual(result, '0 - 0 - - false - NaN'); + }); it('should render nothing for "null" and "undefined" substitutions', function () { - const result = t(TEST_KEY_5, [null, TEST_SUBSTITUTION_2]) - assert.strictEqual(result, ` - ${TEST_SUBSTITUTION_2} - `) - }) + const result = t(TEST_KEY_5, [null, TEST_SUBSTITUTION_2]); + assert.strictEqual(result, ` - ${TEST_SUBSTITUTION_2} - `); + }); it('should return the correct message when a single react substitution is made', function () { - const result = t(TEST_KEY_6, [TEST_SUBSTITUTION_6]) + const result = t(TEST_KEY_6, [TEST_SUBSTITUTION_6]); assert.strictEqual( shallow(result).html(), ' Testing a react substitution
    TEST_SUBSTITUTION_1
    .
    ', - ) - }) + ); + }); it('should return the correct message when two react substitutions are made', function () { const result = t(TEST_KEY_7, [ TEST_SUBSTITUTION_7_1, TEST_SUBSTITUTION_7_2, - ]) + ]); assert.strictEqual( shallow(result).html(), ' Testing a react substitution
    TEST_SUBSTITUTION_1
    and another
    TEST_SUBSTITUTION_2
    .
    ', - ) - }) + ); + }); it('should return the correct message when substituting a mix of react elements and strings', function () { const result = t(TEST_KEY_8, [ @@ -168,11 +168,11 @@ describe('i18n helper', function () { TEST_SUBSTITUTION_8_1, TEST_SUBSTITUTION_2, TEST_SUBSTITUTION_8_2, - ]) + ]); assert.strictEqual( shallow(result).html(), ' Testing a mix TEST_SUBSTITUTION_1 of react substitutions
    TEST_SUBSTITUTION_3
    and string substitutions TEST_SUBSTITUTION_2 +
    TEST_SUBSTITUTION_4
    .
    ', - ) - }) - }) -}) + ); + }); + }); +}); diff --git a/ui/app/helpers/utils/switch-direction.js b/ui/app/helpers/utils/switch-direction.js index 5d4075896..606f452f6 100644 --- a/ui/app/helpers/utils/switch-direction.js +++ b/ui/app/helpers/utils/switch-direction.js @@ -6,30 +6,30 @@ const switchDirection = async (direction) => { if (direction === 'auto') { // eslint-disable-next-line no-param-reassign - direction = 'ltr' + direction = 'ltr'; } - let updatedLink + let updatedLink; Array.from(document.getElementsByTagName('link')) .filter((link) => link.rel === 'stylesheet') .forEach((link) => { if (link.title === direction && link.disabled) { - link.disabled = false - updatedLink = link + link.disabled = false; + updatedLink = link; } else if (link.title !== direction && !link.disabled) { - link.disabled = true + link.disabled = true; } - }) + }); if (updatedLink) { return new Promise((resolve, reject) => { updatedLink.onload = () => { - resolve() - } + resolve(); + }; updatedLink.onerror = () => - reject(new Error(`Failed to load '${direction}' stylesheet`)) - }) + reject(new Error(`Failed to load '${direction}' stylesheet`)); + }); } - return undefined -} + return undefined; +}; -export default switchDirection +export default switchDirection; diff --git a/ui/app/helpers/utils/token-util.js b/ui/app/helpers/utils/token-util.js index e8965edb3..8811bec5d 100644 --- a/ui/app/helpers/utils/token-util.js +++ b/ui/app/helpers/utils/token-util.js @@ -1,154 +1,154 @@ -import log from 'loglevel' -import BigNumber from 'bignumber.js' -import contractMap from '@metamask/contract-metadata' -import * as util from './util' -import { conversionUtil, multiplyCurrencies } from './conversion-util' -import { formatCurrency } from './confirm-tx.util' +import log from 'loglevel'; +import BigNumber from 'bignumber.js'; +import contractMap from '@metamask/contract-metadata'; +import * as util from './util'; +import { conversionUtil, multiplyCurrencies } from './conversion-util'; +import { formatCurrency } from './confirm-tx.util'; const casedContractMap = Object.keys(contractMap).reduce((acc, base) => { return { ...acc, [base.toLowerCase()]: contractMap[base], - } -}, {}) + }; +}, {}); -const DEFAULT_SYMBOL = '' -const DEFAULT_DECIMALS = '0' +const DEFAULT_SYMBOL = ''; +const DEFAULT_DECIMALS = '0'; async function getSymbolFromContract(tokenAddress) { - const token = util.getContractAtAddress(tokenAddress) + const token = util.getContractAtAddress(tokenAddress); try { - const result = await token.symbol() - return result[0] + const result = await token.symbol(); + return result[0]; } catch (error) { log.warn( `symbol() call for token at address ${tokenAddress} resulted in error:`, error, - ) - return undefined + ); + return undefined; } } async function getDecimalsFromContract(tokenAddress) { - const token = util.getContractAtAddress(tokenAddress) + const token = util.getContractAtAddress(tokenAddress); try { - const result = await token.decimals() - const decimalsBN = result[0] - return decimalsBN?.toString() + const result = await token.decimals(); + const decimalsBN = result[0]; + return decimalsBN?.toString(); } catch (error) { log.warn( `decimals() call for token at address ${tokenAddress} resulted in error:`, error, - ) - return undefined + ); + return undefined; } } function getContractMetadata(tokenAddress) { - return tokenAddress && casedContractMap[tokenAddress.toLowerCase()] + return tokenAddress && casedContractMap[tokenAddress.toLowerCase()]; } async function getSymbol(tokenAddress) { - let symbol = await getSymbolFromContract(tokenAddress) + let symbol = await getSymbolFromContract(tokenAddress); if (!symbol) { - const contractMetadataInfo = getContractMetadata(tokenAddress) + const contractMetadataInfo = getContractMetadata(tokenAddress); if (contractMetadataInfo) { - symbol = contractMetadataInfo.symbol + symbol = contractMetadataInfo.symbol; } } - return symbol + return symbol; } async function getDecimals(tokenAddress) { - let decimals = await getDecimalsFromContract(tokenAddress) + let decimals = await getDecimalsFromContract(tokenAddress); if (!decimals || decimals === '0') { - const contractMetadataInfo = getContractMetadata(tokenAddress) + const contractMetadataInfo = getContractMetadata(tokenAddress); if (contractMetadataInfo) { - decimals = contractMetadataInfo.decimals + decimals = contractMetadataInfo.decimals; } } - return decimals + return decimals; } export async function fetchSymbolAndDecimals(tokenAddress) { - let symbol, decimals + let symbol, decimals; try { - symbol = await getSymbol(tokenAddress) - decimals = await getDecimals(tokenAddress) + symbol = await getSymbol(tokenAddress); + decimals = await getDecimals(tokenAddress); } catch (error) { log.warn( `symbol() and decimal() calls for token at address ${tokenAddress} resulted in error:`, error, - ) + ); } return { symbol: symbol || DEFAULT_SYMBOL, decimals: decimals || DEFAULT_DECIMALS, - } + }; } export async function getSymbolAndDecimals(tokenAddress, existingTokens = []) { const existingToken = existingTokens.find( ({ address }) => tokenAddress === address, - ) + ); if (existingToken) { return { symbol: existingToken.symbol, decimals: existingToken.decimals, - } + }; } - let symbol, decimals + let symbol, decimals; try { - symbol = await getSymbol(tokenAddress) - decimals = await getDecimals(tokenAddress) + symbol = await getSymbol(tokenAddress); + decimals = await getDecimals(tokenAddress); } catch (error) { log.warn( `symbol() and decimal() calls for token at address ${tokenAddress} resulted in error:`, error, - ) + ); } return { symbol: symbol || DEFAULT_SYMBOL, decimals: decimals || DEFAULT_DECIMALS, - } + }; } export function tokenInfoGetter() { - const tokens = {} + const tokens = {}; return async (address) => { if (tokens[address]) { - return tokens[address] + return tokens[address]; } - tokens[address] = await getSymbolAndDecimals(address) + tokens[address] = await getSymbolAndDecimals(address); - return tokens[address] - } + return tokens[address]; + }; } export function calcTokenAmount(value, decimals) { - const multiplier = Math.pow(10, Number(decimals || 0)) - return new BigNumber(String(value)).div(multiplier) + const multiplier = Math.pow(10, Number(decimals || 0)); + return new BigNumber(String(value)).div(multiplier); } export function calcTokenValue(value, decimals) { - const multiplier = Math.pow(10, Number(decimals || 0)) - return new BigNumber(String(value)).times(multiplier) + const multiplier = Math.pow(10, Number(decimals || 0)); + return new BigNumber(String(value)).times(multiplier); } /** @@ -162,8 +162,8 @@ export function calcTokenValue(value, decimals) { * @returns {string | undefined} A lowercase address string. */ export function getTokenAddressParam(tokenData = {}) { - const value = tokenData?.args?._to || tokenData?.args?.[0] - return value?.toString().toLowerCase() + const value = tokenData?.args?._to || tokenData?.args?.[0]; + return value?.toString().toLowerCase(); } /** @@ -174,12 +174,12 @@ export function getTokenAddressParam(tokenData = {}) { * @returns {string | undefined} A decimal string value. */ export function getTokenValueParam(tokenData = {}) { - return tokenData?.args?._value?.toString() + return tokenData?.args?._value?.toString(); } export function getTokenValue(tokenParams = []) { - const valueData = tokenParams.find((param) => param.name === '_value') - return valueData && valueData.value + const valueData = tokenParams.find((param) => param.name === '_value'); + return valueData && valueData.value; } /** @@ -211,7 +211,7 @@ export function getTokenFiatAmount( !contractExchangeRate || tokenAmount === undefined ) { - return undefined + return undefined; } const currentTokenToFiatRate = multiplyCurrencies( @@ -221,24 +221,24 @@ export function getTokenFiatAmount( multiplicandBase: 10, multiplierBase: 10, }, - ) + ); const currentTokenInFiat = conversionUtil(tokenAmount, { fromNumericBase: 'dec', fromCurrency: tokenSymbol, toCurrency: currentCurrency.toUpperCase(), numberOfDecimals: 2, conversionRate: currentTokenToFiatRate, - }) - let result + }); + let result; if (hideCurrencySymbol) { - result = formatCurrency(currentTokenInFiat, currentCurrency) + result = formatCurrency(currentTokenInFiat, currentCurrency); } else if (formatted) { result = `${formatCurrency( currentTokenInFiat, currentCurrency, - )} ${currentCurrency.toUpperCase()}` + )} ${currentCurrency.toUpperCase()}`; } else { - result = currentTokenInFiat + result = currentTokenInFiat; } - return result + return result; } diff --git a/ui/app/helpers/utils/transactions.util.js b/ui/app/helpers/utils/transactions.util.js index bcafae970..61f2e1f8c 100644 --- a/ui/app/helpers/utils/transactions.util.js +++ b/ui/app/helpers/utils/transactions.util.js @@ -1,20 +1,20 @@ -import { MethodRegistry } from 'eth-method-registry' -import abi from 'human-standard-token-abi' -import { ethers } from 'ethers' -import log from 'loglevel' -import { addHexPrefix } from '../../../../app/scripts/lib/util' -import { getEtherscanNetworkPrefix } from '../../../lib/etherscan-prefix-for-network' +import { MethodRegistry } from 'eth-method-registry'; +import abi from 'human-standard-token-abi'; +import { ethers } from 'ethers'; +import log from 'loglevel'; +import { addHexPrefix } from '../../../../app/scripts/lib/util'; +import { getEtherscanNetworkPrefix } from '../../../lib/etherscan-prefix-for-network'; import { TRANSACTION_CATEGORIES, TRANSACTION_GROUP_STATUSES, TRANSACTION_STATUSES, TRANSACTION_TYPES, -} from '../../../../shared/constants/transaction' -import fetchWithCache from './fetch-with-cache' +} from '../../../../shared/constants/transaction'; +import fetchWithCache from './fetch-with-cache'; -import { addCurrencies } from './conversion-util' +import { addCurrencies } from './conversion-util'; -const hstInterface = new ethers.utils.Interface(abi) +const hstInterface = new ethers.utils.Interface(abi); /** * @typedef EthersContractCall @@ -34,10 +34,10 @@ const hstInterface = new ethers.utils.Interface(abi) */ export function getTokenData(data) { try { - return hstInterface.parseTransaction({ data }) + return hstInterface.parseTransaction({ data }); } catch (error) { - log.debug('Failed to parse transaction data.', error, data) - return undefined + log.debug('Failed to parse transaction data.', error, data); + return undefined; } } @@ -50,14 +50,14 @@ async function getMethodFrom4Byte(fourBytePrefix) { method: 'GET', mode: 'cors', }, - ) + ); if (fourByteResponse.count === 1) { - return fourByteResponse.results[0].text_signature + return fourByteResponse.results[0].text_signature; } - return null + return null; } -let registry +let registry; /** * Attempts to return the method data from the MethodRegistry library, the message registry library and the token abi, in that order of preference @@ -67,33 +67,33 @@ let registry export async function getMethodDataAsync(fourBytePrefix) { try { const fourByteSig = getMethodFrom4Byte(fourBytePrefix).catch((e) => { - log.error(e) - return null - }) + log.error(e); + return null; + }); if (!registry) { - registry = new MethodRegistry({ provider: global.ethereumProvider }) + registry = new MethodRegistry({ provider: global.ethereumProvider }); } - let sig = await registry.lookup(fourBytePrefix) + let sig = await registry.lookup(fourBytePrefix); if (!sig) { - sig = await fourByteSig + sig = await fourByteSig; } if (!sig) { - return {} + return {}; } - const parsedResult = registry.parse(sig) + const parsedResult = registry.parse(sig); return { name: parsedResult.name, params: parsedResult.args, - } + }; } catch (error) { - log.error(error) - return {} + log.error(error); + return {}; } } @@ -104,9 +104,9 @@ export async function getMethodDataAsync(fourBytePrefix) { * @returns {string} The four-byte method signature */ export function getFourBytePrefix(data = '') { - const prefixedData = addHexPrefix(data) - const fourBytePrefix = prefixedData.slice(0, 10) - return fourBytePrefix + const prefixedData = addHexPrefix(data); + const fourBytePrefix = prefixedData.slice(0, 10); + return fourBytePrefix; } /** @@ -120,7 +120,7 @@ export function isTokenMethodAction(transactionCategory) { TRANSACTION_CATEGORIES.TOKEN_METHOD_TRANSFER, TRANSACTION_CATEGORIES.TOKEN_METHOD_APPROVE, TRANSACTION_CATEGORIES.TOKEN_METHOD_TRANSFER_FROM, - ].includes(transactionCategory) + ].includes(transactionCategory); } export function getLatestSubmittedTxWithNonce( @@ -128,27 +128,27 @@ export function getLatestSubmittedTxWithNonce( nonce = '0x0', ) { if (!transactions.length) { - return {} + return {}; } return transactions.reduce((acc, current) => { - const { submittedTime, txParams: { nonce: currentNonce } = {} } = current + const { submittedTime, txParams: { nonce: currentNonce } = {} } = current; if (currentNonce === nonce) { if (!acc.submittedTime) { - return current + return current; } - return submittedTime > acc.submittedTime ? current : acc + return submittedTime > acc.submittedTime ? current : acc; } - return acc - }, {}) + return acc; + }, {}); } export async function isSmartContractAddress(address) { - const code = await global.eth.getCode(address) + const code = await global.eth.getCode(address); // Geth will return '0x', and ganache-core v2.2.1 will return '0x0' - const codeIsEmpty = !code || code === '0x' || code === '0x0' - return !codeIsEmpty + const codeIsEmpty = !code || code === '0x' || code === '0x0'; + return !codeIsEmpty; } export function sumHexes(...args) { @@ -157,10 +157,10 @@ export function sumHexes(...args) { toNumericBase: 'hex', aBase: 16, bBase: 16, - }) - }) + }); + }); - return addHexPrefix(total) + return addHexPrefix(total); } /** @@ -175,21 +175,21 @@ export function getStatusKey(transaction) { txReceipt: { status: receiptStatus } = {}, type, status, - } = transaction + } = transaction; // There was an on-chain failure if (receiptStatus === '0x0') { - return TRANSACTION_STATUSES.FAILED + return TRANSACTION_STATUSES.FAILED; } if ( status === TRANSACTION_STATUSES.CONFIRMED && type === TRANSACTION_TYPES.CANCEL ) { - return TRANSACTION_GROUP_STATUSES.CANCELLED + return TRANSACTION_GROUP_STATUSES.CANCELLED; } - return transaction.status + return transaction.status; } /** @@ -200,8 +200,8 @@ export function getStatusKey(transaction) { */ export function getBlockExplorerUrlForTx(networkId, hash, rpcPrefs = {}) { if (rpcPrefs.blockExplorerUrl) { - return `${rpcPrefs.blockExplorerUrl.replace(/\/+$/u, '')}/tx/${hash}` + return `${rpcPrefs.blockExplorerUrl.replace(/\/+$/u, '')}/tx/${hash}`; } - const prefix = getEtherscanNetworkPrefix(networkId) - return `https://${prefix}etherscan.io/tx/${hash}` + const prefix = getEtherscanNetworkPrefix(networkId); + return `https://${prefix}etherscan.io/tx/${hash}`; } diff --git a/ui/app/helpers/utils/transactions.util.test.js b/ui/app/helpers/utils/transactions.util.test.js index 9079028dd..a725156bd 100644 --- a/ui/app/helpers/utils/transactions.util.test.js +++ b/ui/app/helpers/utils/transactions.util.test.js @@ -1,30 +1,30 @@ -import assert from 'assert' +import assert from 'assert'; import { TRANSACTION_CATEGORIES, TRANSACTION_GROUP_STATUSES, TRANSACTION_STATUSES, -} from '../../../../shared/constants/transaction' -import * as utils from './transactions.util' +} from '../../../../shared/constants/transaction'; +import * as utils from './transactions.util'; describe('Transactions utils', function () { describe('getTokenData', function () { it('should return token data', function () { const tokenData = utils.getTokenData( '0xa9059cbb00000000000000000000000050a9d56c2b8ba9a5c7f2c08c3d26e0499f23a7060000000000000000000000000000000000000000000000000000000000004e20', - ) - assert.ok(tokenData) - const { name, args } = tokenData - assert.strictEqual(name, TRANSACTION_CATEGORIES.TOKEN_METHOD_TRANSFER) - const to = args._to - const value = args._value.toString() - assert.strictEqual(to, '0x50A9D56C2B8BA9A5c7f2C08C3d26E0499F23a706') - assert.strictEqual(value, '20000') - }) + ); + assert.ok(tokenData); + const { name, args } = tokenData; + assert.strictEqual(name, TRANSACTION_CATEGORIES.TOKEN_METHOD_TRANSFER); + const to = args._to; + const value = args._value.toString(); + assert.strictEqual(to, '0x50A9D56C2B8BA9A5c7f2C08C3d26E0499F23a706'); + assert.strictEqual(value, '20000'); + }); it('should not throw errors when called without arguments', function () { - assert.doesNotThrow(() => utils.getTokenData()) - }) - }) + assert.doesNotThrow(() => utils.getTokenData()); + }); + }); describe('getStatusKey', function () { it('should return the correct status', function () { @@ -53,13 +53,13 @@ describe('Transactions utils', function () { }, expected: TRANSACTION_GROUP_STATUSES.PENDING, }, - ] + ]; tests.forEach(({ transaction, expected }) => { - assert.strictEqual(utils.getStatusKey(transaction), expected) - }) - }) - }) + assert.strictEqual(utils.getStatusKey(transaction), expected); + }); + }); + }); describe('getBlockExplorerUrlForTx', function () { it('should return the correct block explorer url for a transaction', function () { @@ -93,14 +93,14 @@ describe('Transactions utils', function () { blockExplorerUrl: 'https://another.block.explorer/', }, }, - ] + ]; tests.forEach(({ expected, networkId, hash, rpcPrefs }) => { assert.strictEqual( utils.getBlockExplorerUrlForTx(networkId, hash, rpcPrefs), expected, - ) - }) - }) - }) -}) + ); + }); + }); + }); +}); diff --git a/ui/app/helpers/utils/util.js b/ui/app/helpers/utils/util.js index b88abc876..bc22d05c1 100644 --- a/ui/app/helpers/utils/util.js +++ b/ui/app/helpers/utils/util.js @@ -1,16 +1,16 @@ -import punycode from 'punycode/punycode' -import abi from 'human-standard-token-abi' -import BigNumber from 'bignumber.js' -import ethUtil from 'ethereumjs-util' -import { DateTime } from 'luxon' -import { addHexPrefix } from '../../../../app/scripts/lib/util' -import getFetchWithTimeout from '../../../../shared/modules/fetch-with-timeout' +import punycode from 'punycode/punycode'; +import abi from 'human-standard-token-abi'; +import BigNumber from 'bignumber.js'; +import ethUtil from 'ethereumjs-util'; +import { DateTime } from 'luxon'; +import { addHexPrefix } from '../../../../app/scripts/lib/util'; +import getFetchWithTimeout from '../../../../shared/modules/fetch-with-timeout'; -const fetchWithTimeout = getFetchWithTimeout(30000) +const fetchWithTimeout = getFetchWithTimeout(30000); // formatData :: ( date: ) -> String export function formatDate(date, format = "M/d/y 'at' T") { - return DateTime.fromMillis(date).toFormat(format) + return DateTime.fromMillis(date).toFormat(format); } export function formatDateWithYearContext( @@ -18,11 +18,11 @@ export function formatDateWithYearContext( formatThisYear = 'MMM d', fallback = 'MMM d, y', ) { - const dateTime = DateTime.fromMillis(date) - const now = DateTime.local() + const dateTime = DateTime.fromMillis(date); + const now = DateTime.local(); return dateTime.toFormat( now.year === dateTime.year ? formatThisYear : fallback, - ) + ); } const valueTable = { @@ -37,11 +37,11 @@ const valueTable = { mether: '0.000001', gether: '0.000000001', tether: '0.000000000001', -} -const bnTable = {} +}; +const bnTable = {}; Object.keys(valueTable).forEach((currency) => { - bnTable[currency] = new ethUtil.BN(valueTable[currency], 10) -}) + bnTable[currency] = new ethUtil.BN(valueTable[currency], 10); +}); export function isEthNetwork(netId) { if ( @@ -52,19 +52,19 @@ export function isEthNetwork(netId) { netId === '42' || netId === '1337' ) { - return true + return true; } - return false + return false; } export function valuesFor(obj) { if (!obj) { - return [] + return []; } return Object.keys(obj).map(function (key) { - return obj[key] - }) + return obj[key]; + }); } export function addressSummary( @@ -74,28 +74,28 @@ export function addressSummary( includeHex = true, ) { if (!address) { - return '' + return ''; } - let checked = checksumAddress(address) + let checked = checksumAddress(address); if (!includeHex) { - checked = ethUtil.stripHexPrefix(checked) + checked = ethUtil.stripHexPrefix(checked); } return checked ? `${checked.slice(0, firstSegLength)}...${checked.slice( checked.length - lastSegLength, )}` - : '...' + : '...'; } export function isValidAddress(address) { if (!address || address === '0x0000000000000000000000000000000000000000') { - return false + return false; } - const prefixed = addHexPrefix(address) + const prefixed = addHexPrefix(address); return ( (isAllOneCase(prefixed.slice(2)) && ethUtil.isValidAddress(prefixed)) || ethUtil.isValidChecksumAddress(prefixed) - ) + ); } export function isValidDomainName(address) { @@ -107,44 +107,44 @@ export function isValidDomainName(address) { // A chunk has minimum length of 1, but minimum tld is set to 2 for now (no 1-character tlds exist yet) .match( /^(?:[a-z0-9](?:[-a-z0-9]*[a-z0-9])?\.)+[a-z0-9][-a-z0-9]*[a-z0-9]$/u, - ) - return match !== null + ); + return match !== null; } export function isAllOneCase(address) { if (!address) { - return true + return true; } - const lower = address.toLowerCase() - const upper = address.toUpperCase() - return address === lower || address === upper + const lower = address.toLowerCase(); + const upper = address.toUpperCase(); + return address === lower || address === upper; } // Takes wei Hex, returns wei BN, even if input is null export function numericBalance(balance) { if (!balance) { - return new ethUtil.BN(0, 16) + return new ethUtil.BN(0, 16); } - const stripped = ethUtil.stripHexPrefix(balance) - return new ethUtil.BN(stripped, 16) + const stripped = ethUtil.stripHexPrefix(balance); + return new ethUtil.BN(stripped, 16); } // Takes hex, returns [beforeDecimal, afterDecimal] export function parseBalance(balance) { - let afterDecimal - const wei = numericBalance(balance) - const weiString = wei.toString() - const trailingZeros = /0+$/u + let afterDecimal; + const wei = numericBalance(balance); + const weiString = wei.toString(); + const trailingZeros = /0+$/u; const beforeDecimal = - weiString.length > 18 ? weiString.slice(0, weiString.length - 18) : '0' + weiString.length > 18 ? weiString.slice(0, weiString.length - 18) : '0'; afterDecimal = `000000000000000000${wei}` .slice(-18) - .replace(trailingZeros, '') + .replace(trailingZeros, ''); if (afterDecimal === '') { - afterDecimal = '0' + afterDecimal = '0'; } - return [beforeDecimal, afterDecimal] + return [beforeDecimal, afterDecimal]; } // Takes wei hex, returns an object with three properties. @@ -155,147 +155,147 @@ export function formatBalance( needsParse = true, ticker = 'ETH', ) { - const parsed = needsParse ? parseBalance(balance) : balance.split('.') - const beforeDecimal = parsed[0] - let afterDecimal = parsed[1] - let formatted = 'None' + const parsed = needsParse ? parseBalance(balance) : balance.split('.'); + const beforeDecimal = parsed[0]; + let afterDecimal = parsed[1]; + let formatted = 'None'; if (decimalsToKeep === undefined) { if (beforeDecimal === '0') { if (afterDecimal !== '0') { - const sigFigs = afterDecimal.match(/^0*(.{2})/u) // default: grabs 2 most significant digits + const sigFigs = afterDecimal.match(/^0*(.{2})/u); // default: grabs 2 most significant digits if (sigFigs) { - afterDecimal = sigFigs[0] + afterDecimal = sigFigs[0]; } - formatted = `0.${afterDecimal} ${ticker}` + formatted = `0.${afterDecimal} ${ticker}`; } } else { - formatted = `${beforeDecimal}.${afterDecimal.slice(0, 3)} ${ticker}` + formatted = `${beforeDecimal}.${afterDecimal.slice(0, 3)} ${ticker}`; } } else { - afterDecimal += Array(decimalsToKeep).join('0') + afterDecimal += Array(decimalsToKeep).join('0'); formatted = `${beforeDecimal}.${afterDecimal.slice( 0, decimalsToKeep, - )} ${ticker}` + )} ${ticker}`; } - return formatted + return formatted; } export function generateBalanceObject(formattedBalance, decimalsToKeep = 1) { - let balance = formattedBalance.split(' ')[0] - const label = formattedBalance.split(' ')[1] - const beforeDecimal = balance.split('.')[0] - const afterDecimal = balance.split('.')[1] - const shortBalance = shortenBalance(balance, decimalsToKeep) + let balance = formattedBalance.split(' ')[0]; + const label = formattedBalance.split(' ')[1]; + const beforeDecimal = balance.split('.')[0]; + const afterDecimal = balance.split('.')[1]; + const shortBalance = shortenBalance(balance, decimalsToKeep); if (beforeDecimal === '0' && afterDecimal.substr(0, 5) === '00000') { // eslint-disable-next-line eqeqeq if (afterDecimal == 0) { - balance = '0' + balance = '0'; } else { - balance = '<1.0e-5' + balance = '<1.0e-5'; } } else if (beforeDecimal !== '0') { - balance = `${beforeDecimal}.${afterDecimal.slice(0, decimalsToKeep)}` + balance = `${beforeDecimal}.${afterDecimal.slice(0, decimalsToKeep)}`; } - return { balance, label, shortBalance } + return { balance, label, shortBalance }; } export function shortenBalance(balance, decimalsToKeep = 1) { - let truncatedValue - const convertedBalance = parseFloat(balance) + let truncatedValue; + const convertedBalance = parseFloat(balance); if (convertedBalance > 1000000) { - truncatedValue = (balance / 1000000).toFixed(decimalsToKeep) - return `${truncatedValue}m` + truncatedValue = (balance / 1000000).toFixed(decimalsToKeep); + return `${truncatedValue}m`; } else if (convertedBalance > 1000) { - truncatedValue = (balance / 1000).toFixed(decimalsToKeep) - return `${truncatedValue}k` + truncatedValue = (balance / 1000).toFixed(decimalsToKeep); + return `${truncatedValue}k`; } else if (convertedBalance === 0) { - return '0' + return '0'; } else if (convertedBalance < 0.001) { - return '<0.001' + return '<0.001'; } else if (convertedBalance < 1) { - const stringBalance = convertedBalance.toString() + const stringBalance = convertedBalance.toString(); if (stringBalance.split('.')[1].length > 3) { - return convertedBalance.toFixed(3) + return convertedBalance.toFixed(3); } - return stringBalance + return stringBalance; } - return convertedBalance.toFixed(decimalsToKeep) + return convertedBalance.toFixed(decimalsToKeep); } // Takes a BN and an ethereum currency name, // returns a BN in wei export function normalizeToWei(amount, currency) { try { - return amount.mul(bnTable.wei).div(bnTable[currency]) + return amount.mul(bnTable.wei).div(bnTable[currency]); } catch (e) { - return amount + return amount; } } export function normalizeEthStringToWei(str) { - const parts = str.split('.') - let eth = new ethUtil.BN(parts[0], 10).mul(bnTable.wei) + const parts = str.split('.'); + let eth = new ethUtil.BN(parts[0], 10).mul(bnTable.wei); if (parts[1]) { - let decimal = parts[1] + let decimal = parts[1]; while (decimal.length < 18) { - decimal += '0' + decimal += '0'; } if (decimal.length > 18) { - decimal = decimal.slice(0, 18) + decimal = decimal.slice(0, 18); } - const decimalBN = new ethUtil.BN(decimal, 10) - eth = eth.add(decimalBN) + const decimalBN = new ethUtil.BN(decimal, 10); + eth = eth.add(decimalBN); } - return eth + return eth; } -const multiple = new ethUtil.BN('10000', 10) +const multiple = new ethUtil.BN('10000', 10); export function normalizeNumberToWei(n, currency) { - const enlarged = n * 10000 - const amount = new ethUtil.BN(String(enlarged), 10) - return normalizeToWei(amount, currency).div(multiple) + const enlarged = n * 10000; + const amount = new ethUtil.BN(String(enlarged), 10); + return normalizeToWei(amount, currency).div(multiple); } export function isHex(str) { - return Boolean(str.match(/^(0x)?[0-9a-fA-F]+$/u)) + return Boolean(str.match(/^(0x)?[0-9a-fA-F]+$/u)); } export function getContractAtAddress(tokenAddress) { - return global.eth.contract(abi).at(tokenAddress) + return global.eth.contract(abi).at(tokenAddress); } export function getRandomFileName() { - let fileName = '' + let fileName = ''; const charBank = [ ...'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', - ] - const fileNameLength = Math.floor(Math.random() * 7 + 6) + ]; + const fileNameLength = Math.floor(Math.random() * 7 + 6); for (let i = 0; i < fileNameLength; i++) { - fileName += charBank[Math.floor(Math.random() * charBank.length)] + fileName += charBank[Math.floor(Math.random() * charBank.length)]; } - return fileName + return fileName; } export function exportAsFile(filename, data, type = 'text/csv') { // eslint-disable-next-line no-param-reassign - filename = filename || getRandomFileName() + filename = filename || getRandomFileName(); // source: https://stackoverflow.com/a/33542499 by Ludovic Feltz - const blob = new window.Blob([data], { type }) + const blob = new window.Blob([data], { type }); if (window.navigator.msSaveOrOpenBlob) { - window.navigator.msSaveBlob(blob, filename) + window.navigator.msSaveBlob(blob, filename); } else { - const elem = window.document.createElement('a') - elem.target = '_blank' - elem.href = window.URL.createObjectURL(blob) - elem.download = filename - document.body.appendChild(elem) - elem.click() - document.body.removeChild(elem) + const elem = window.document.createElement('a'); + elem.target = '_blank'; + elem.href = window.URL.createObjectURL(blob); + elem.download = filename; + document.body.appendChild(elem); + elem.click(); + document.body.removeChild(elem); } } @@ -307,8 +307,8 @@ export function exportAsFile(filename, data, type = 'text/csv') { * */ export function checksumAddress(address) { - const checksummed = address ? ethUtil.toChecksumAddress(address) : '' - return checksummed + const checksummed = address ? ethUtil.toChecksumAddress(address) : ''; + return checksummed; } /** @@ -324,21 +324,21 @@ export function checksumAddress(address) { */ export function shortenAddress(address = '') { if (address.length < 11) { - return address + return address; } - return `${address.slice(0, 6)}...${address.slice(-4)}` + return `${address.slice(0, 6)}...${address.slice(-4)}`; } export function isValidAddressHead(address) { - const addressLengthIsLessThanFull = address.length < 42 - const addressIsHex = isHex(address) + const addressLengthIsLessThanFull = address.length < 42; + const addressIsHex = isHex(address); - return addressLengthIsLessThanFull && addressIsHex + return addressLengthIsLessThanFull && addressIsHex; } export function getAccountByAddress(accounts = [], targetAddress) { - return accounts.find(({ address }) => address === targetAddress) + return accounts.find(({ address }) => address === targetAddress); } /** @@ -350,7 +350,7 @@ export function getAccountByAddress(accounts = [], targetAddress) { * @returns {string} The URL string, without the scheme, if it was stripped. */ export function stripHttpSchemes(urlString) { - return urlString.replace(/^https?:\/\//u, '') + return urlString.replace(/^https?:\/\//u, ''); } /** @@ -360,20 +360,20 @@ export function stripHttpSchemes(urlString) { * @returns {boolean} Whether the URL-like value is an extension URL. */ export function isExtensionUrl(urlLike) { - const EXT_PROTOCOLS = ['chrome-extension:', 'moz-extension:'] + const EXT_PROTOCOLS = ['chrome-extension:', 'moz-extension:']; if (typeof urlLike === 'string') { for (const protocol of EXT_PROTOCOLS) { if (urlLike.startsWith(protocol)) { - return true + return true; } } } if (urlLike?.protocol) { - return EXT_PROTOCOLS.includes(urlLike.protocol) + return EXT_PROTOCOLS.includes(urlLike.protocol); } - return false + return false; } /** @@ -386,14 +386,14 @@ export function isExtensionUrl(urlLike) { */ export function checkExistingAddresses(address, list = []) { if (!address) { - return false + return false; } const matchesAddress = (obj) => { - return obj.address.toLowerCase() === address.toLowerCase() - } + return obj.address.toLowerCase() === address.toLowerCase(); + }; - return list.some(matchesAddress) + return list.some(matchesAddress); } /** @@ -408,7 +408,7 @@ export function checkExistingAddresses(address, list = []) { export function toPrecisionWithoutTrailingZeros(n, precision) { return new BigNumber(n) .toPrecision(precision) - .replace(/(\.[0-9]*[1-9])0*|(\.0*)/u, '$1') + .replace(/(\.[0-9]*[1-9])0*|(\.0*)/u, '$1'); } /** @@ -417,8 +417,8 @@ export function toPrecisionWithoutTrailingZeros(n, precision) { */ export function addHexPrefixToObjectValues(obj) { return Object.keys(obj).reduce((newObj, key) => { - return { ...newObj, [key]: addHexPrefix(obj[key]) } - }, {}) + return { ...newObj, [key]: addHexPrefix(obj[key]) }; + }, {}); } /** @@ -448,13 +448,13 @@ export function constructTxParams({ value: '0', gas, gasPrice, - } + }; if (!sendToken) { - txParams.value = amount - txParams.to = to + txParams.value = amount; + txParams.to = to; } - return addHexPrefixToObjectValues(txParams) + return addHexPrefixToObjectValues(txParams); } /** @@ -467,19 +467,19 @@ export function constructTxParams({ * or throws an error in case of failure. */ export async function jsonRpcRequest(rpcUrl, rpcMethod, rpcParams = []) { - let fetchUrl = rpcUrl + let fetchUrl = rpcUrl; const headers = { 'Content-Type': 'application/json', - } + }; // Convert basic auth URL component to Authorization header - const { origin, pathname, username, password, search } = new URL(rpcUrl) + const { origin, pathname, username, password, search } = new URL(rpcUrl); // URLs containing username and password needs special processing if (username && password) { const encodedAuth = Buffer.from(`${username}:${password}`).toString( 'base64', - ) - headers.Authorization = `Basic ${encodedAuth}` - fetchUrl = `${origin}${pathname}${search}` + ); + headers.Authorization = `Basic ${encodedAuth}`; + fetchUrl = `${origin}${pathname}${search}`; } const jsonRpcResponse = await fetchWithTimeout(fetchUrl, { method: 'POST', @@ -491,19 +491,19 @@ export async function jsonRpcRequest(rpcUrl, rpcMethod, rpcParams = []) { }), headers, cache: 'default', - }).then((httpResponse) => httpResponse.json()) + }).then((httpResponse) => httpResponse.json()); if ( !jsonRpcResponse || Array.isArray(jsonRpcResponse) || typeof jsonRpcResponse !== 'object' ) { - throw new Error(`RPC endpoint ${rpcUrl} returned non-object response.`) + throw new Error(`RPC endpoint ${rpcUrl} returned non-object response.`); } - const { error, result } = jsonRpcResponse + const { error, result } = jsonRpcResponse; if (error) { - throw new Error(error?.message || error) + throw new Error(error?.message || error); } - return result + return result; } diff --git a/ui/app/helpers/utils/util.test.js b/ui/app/helpers/utils/util.test.js index 9f319c362..9f9c7ba54 100644 --- a/ui/app/helpers/utils/util.test.js +++ b/ui/app/helpers/utils/util.test.js @@ -1,216 +1,216 @@ -import assert from 'assert' -import ethUtil from 'ethereumjs-util' -import * as util from './util' +import assert from 'assert'; +import ethUtil from 'ethereumjs-util'; +import * as util from './util'; describe('util', function () { - let ethInWei = '1' + let ethInWei = '1'; for (let i = 0; i < 18; i++) { - ethInWei += '0' + ethInWei += '0'; } describe('#parseBalance', function () { it('should render 0.01 eth correctly', function () { - const input = '0x2386F26FC10000' - const output = util.parseBalance(input) - assert.deepStrictEqual(output, ['0', '01']) - }) + const input = '0x2386F26FC10000'; + const output = util.parseBalance(input); + assert.deepStrictEqual(output, ['0', '01']); + }); it('should render 12.023 eth correctly', function () { - const input = 'A6DA46CCA6858000' - const output = util.parseBalance(input) - assert.deepStrictEqual(output, ['12', '023']) - }) + const input = 'A6DA46CCA6858000'; + const output = util.parseBalance(input); + assert.deepStrictEqual(output, ['12', '023']); + }); it('should render 0.0000000342422 eth correctly', function () { - const input = '0x7F8FE81C0' - const output = util.parseBalance(input) - assert.deepStrictEqual(output, ['0', '0000000342422']) - }) + const input = '0x7F8FE81C0'; + const output = util.parseBalance(input); + assert.deepStrictEqual(output, ['0', '0000000342422']); + }); it('should render 0 eth correctly', function () { - const input = '0x0' - const output = util.parseBalance(input) - assert.deepStrictEqual(output, ['0', '0']) - }) - }) + const input = '0x0'; + const output = util.parseBalance(input); + assert.deepStrictEqual(output, ['0', '0']); + }); + }); describe('#addressSummary', function () { it('should add case-sensitive checksum', function () { - const address = '0xfdea65c8e26263f6d9a1b5de9555d2931a33b825' - const result = util.addressSummary(address) - assert.strictEqual(result, '0xFDEa65C8...b825') - }) + const address = '0xfdea65c8e26263f6d9a1b5de9555d2931a33b825'; + const result = util.addressSummary(address); + assert.strictEqual(result, '0xFDEa65C8...b825'); + }); it('should accept arguments for firstseg, lastseg, and keepPrefix', function () { - const address = '0xfdea65c8e26263f6d9a1b5de9555d2931a33b825' - const result = util.addressSummary(address, 4, 4, false) - assert.strictEqual(result, 'FDEa...b825') - }) - }) + const address = '0xfdea65c8e26263f6d9a1b5de9555d2931a33b825'; + const result = util.addressSummary(address, 4, 4, false); + assert.strictEqual(result, 'FDEa...b825'); + }); + }); describe('#isValidAddress', function () { it('should allow 40-char non-prefixed hex', function () { - const address = 'fdea65c8e26263f6d9a1b5de9555d2931a33b825' - const result = util.isValidAddress(address) - assert.ok(result) - }) + const address = 'fdea65c8e26263f6d9a1b5de9555d2931a33b825'; + const result = util.isValidAddress(address); + assert.ok(result); + }); it('should allow 42-char non-prefixed hex', function () { - const address = '0xfdea65c8e26263f6d9a1b5de9555d2931a33b825' - const result = util.isValidAddress(address) - assert.ok(result) - }) + const address = '0xfdea65c8e26263f6d9a1b5de9555d2931a33b825'; + const result = util.isValidAddress(address); + assert.ok(result); + }); it('should not allow less non hex-prefixed', function () { - const address = 'fdea65c8e26263f6d9a1b5de9555d2931a33b85' - const result = util.isValidAddress(address) - assert.ok(!result) - }) + const address = 'fdea65c8e26263f6d9a1b5de9555d2931a33b85'; + const result = util.isValidAddress(address); + assert.ok(!result); + }); it('should not allow less hex-prefixed', function () { - const address = '0xfdea65ce26263f6d9a1b5de9555d2931a33b85' - const result = util.isValidAddress(address) - assert.ok(!result) - }) + const address = '0xfdea65ce26263f6d9a1b5de9555d2931a33b85'; + const result = util.isValidAddress(address); + assert.ok(!result); + }); it('should recognize correct capitalized checksum', function () { - const address = '0xFDEa65C8e26263F6d9A1B5de9555D2931A33b825' - const result = util.isValidAddress(address) - assert.ok(result) - }) + const address = '0xFDEa65C8e26263F6d9A1B5de9555D2931A33b825'; + const result = util.isValidAddress(address); + assert.ok(result); + }); it('should recognize incorrect capitalized checksum', function () { - const address = '0xFDea65C8e26263F6d9A1B5de9555D2931A33b825' - const result = util.isValidAddress(address) - assert.ok(!result) - }) + const address = '0xFDea65C8e26263F6d9A1B5de9555D2931A33b825'; + const result = util.isValidAddress(address); + assert.ok(!result); + }); it('should recognize this sample hashed address', function () { - const address = '0x5Fda30Bb72B8Dfe20e48A00dFc108d0915BE9Bb0' - const result = util.isValidAddress(address) - const hashed = ethUtil.toChecksumAddress(address.toLowerCase()) - assert.strictEqual(hashed, address, 'example is hashed correctly') - assert.ok(result, 'is valid by our check') - }) - }) + const address = '0x5Fda30Bb72B8Dfe20e48A00dFc108d0915BE9Bb0'; + const result = util.isValidAddress(address); + const hashed = ethUtil.toChecksumAddress(address.toLowerCase()); + assert.strictEqual(hashed, address, 'example is hashed correctly'); + assert.ok(result, 'is valid by our check'); + }); + }); describe('isValidDomainName', function () { it('should return true when given a valid domain name', function () { - assert.strictEqual(util.isValidDomainName('foo.bar'), true) - }) + assert.strictEqual(util.isValidDomainName('foo.bar'), true); + }); it('should return true when given a valid subdomain', function () { - assert.strictEqual(util.isValidDomainName('foo.foo.bar'), true) - }) + assert.strictEqual(util.isValidDomainName('foo.foo.bar'), true); + }); it('should return true when given a single-character domain', function () { - assert.strictEqual(util.isValidDomainName('f.bar'), true) - }) + assert.strictEqual(util.isValidDomainName('f.bar'), true); + }); it('should return true when given a unicode TLD', function () { - assert.strictEqual(util.isValidDomainName('台灣.中国'), true) - }) + assert.strictEqual(util.isValidDomainName('台灣.中国'), true); + }); it('should return false when given a domain with unacceptable ASCII characters', function () { - assert.strictEqual(util.isValidDomainName('$.bar'), false) - }) + assert.strictEqual(util.isValidDomainName('$.bar'), false); + }); it('should return false when given a TLD that starts with a dash', function () { - assert.strictEqual(util.isValidDomainName('foo.-bar'), false) - }) + assert.strictEqual(util.isValidDomainName('foo.-bar'), false); + }); it('should return false when given a TLD that ends with a dash', function () { - assert.strictEqual(util.isValidDomainName('foo.bar-'), false) - }) + assert.strictEqual(util.isValidDomainName('foo.bar-'), false); + }); it('should return false when given a domain name with a chunk that starts with a dash', function () { - assert.strictEqual(util.isValidDomainName('-foo.bar'), false) - }) + assert.strictEqual(util.isValidDomainName('-foo.bar'), false); + }); it('should return false when given a domain name with a chunk that ends with a dash', function () { - assert.strictEqual(util.isValidDomainName('foo-.bar'), false) - }) + assert.strictEqual(util.isValidDomainName('foo-.bar'), false); + }); it('should return false when given a bare TLD', function () { - assert.strictEqual(util.isValidDomainName('bar'), false) - }) + assert.strictEqual(util.isValidDomainName('bar'), false); + }); it('should return false when given a domain that starts with a period', function () { - assert.strictEqual(util.isValidDomainName('.bar'), false) - }) + assert.strictEqual(util.isValidDomainName('.bar'), false); + }); it('should return false when given a subdomain that starts with a period', function () { - assert.strictEqual(util.isValidDomainName('.foo.bar'), false) - }) + assert.strictEqual(util.isValidDomainName('.foo.bar'), false); + }); it('should return false when given a domain that ends with a period', function () { - assert.strictEqual(util.isValidDomainName('bar.'), false) - }) + assert.strictEqual(util.isValidDomainName('bar.'), false); + }); it('should return false when given a 1-character TLD', function () { - assert.strictEqual(util.isValidDomainName('foo.b'), false) - }) - }) + assert.strictEqual(util.isValidDomainName('foo.b'), false); + }); + }); describe('#numericBalance', function () { it('should return a BN 0 if given nothing', function () { - const result = util.numericBalance() - assert.strictEqual(result.toString(10), '0') - }) + const result = util.numericBalance(); + assert.strictEqual(result.toString(10), '0'); + }); it('should work with hex prefix', function () { - const result = util.numericBalance('0x012') - assert.strictEqual(result.toString(10), '18') - }) + const result = util.numericBalance('0x012'); + assert.strictEqual(result.toString(10), '18'); + }); it('should work with no hex prefix', function () { - const result = util.numericBalance('012') - assert.strictEqual(result.toString(10), '18') - }) - }) + const result = util.numericBalance('012'); + assert.strictEqual(result.toString(10), '18'); + }); + }); describe('#formatBalance', function () { it('should return None when given nothing', function () { - const result = util.formatBalance() - assert.strictEqual(result, 'None', 'should return "None"') - }) + const result = util.formatBalance(); + assert.strictEqual(result, 'None', 'should return "None"'); + }); it('should return 1.0000 ETH', function () { - const input = new ethUtil.BN(ethInWei, 10).toJSON() - const result = util.formatBalance(input, 4) - assert.strictEqual(result, '1.0000 ETH') - }) + const input = new ethUtil.BN(ethInWei, 10).toJSON(); + const result = util.formatBalance(input, 4); + assert.strictEqual(result, '1.0000 ETH'); + }); it('should return 0.500 ETH', function () { const input = new ethUtil.BN(ethInWei, 10) .div(new ethUtil.BN('2', 10)) - .toJSON() - const result = util.formatBalance(input, 3) - assert.strictEqual(result, '0.500 ETH') - }) + .toJSON(); + const result = util.formatBalance(input, 3); + assert.strictEqual(result, '0.500 ETH'); + }); it('should display specified decimal points', function () { - const input = '0x128dfa6a90b28000' - const result = util.formatBalance(input, 2) - assert.strictEqual(result, '1.33 ETH') - }) + const input = '0x128dfa6a90b28000'; + const result = util.formatBalance(input, 2); + assert.strictEqual(result, '1.33 ETH'); + }); it('should default to 3 decimal points', function () { - const input = '0x128dfa6a90b28000' - const result = util.formatBalance(input) - assert.strictEqual(result, '1.337 ETH') - }) + const input = '0x128dfa6a90b28000'; + const result = util.formatBalance(input); + assert.strictEqual(result, '1.337 ETH'); + }); it('should show 2 significant digits for tiny balances', function () { - const input = '0x1230fa6a90b28' - const result = util.formatBalance(input) - assert.strictEqual(result, '0.00032 ETH') - }) + const input = '0x1230fa6a90b28'; + const result = util.formatBalance(input); + assert.strictEqual(result, '0.00032 ETH'); + }); it('should not parse the balance and return value with 2 decimal points with ETH at the end', function () { - const value = '1.2456789' - const needsParse = false - const result = util.formatBalance(value, 2, needsParse) - assert.strictEqual(result, '1.24 ETH') - }) - }) + const value = '1.2456789'; + const needsParse = false; + const result = util.formatBalance(value, 2, needsParse); + assert.strictEqual(result, '1.24 ETH'); + }); + }); describe('normalizing values', function () { describe('#normalizeToWei', function () { @@ -229,116 +229,116 @@ describe('util', function () { // I think they're big enough to ignore for now. // gether:'0.000000001', // tether:'0.000000000001', - } - const oneEthBn = new ethUtil.BN(ethInWei, 10) + }; + const oneEthBn = new ethUtil.BN(ethInWei, 10); Object.keys(valueTable).forEach((currency) => { - const value = new ethUtil.BN(valueTable[currency], 10) - const output = util.normalizeToWei(value, currency) + const value = new ethUtil.BN(valueTable[currency], 10); + const output = util.normalizeToWei(value, currency); assert.strictEqual( output.toString(10), valueTable.wei, `value of ${output.toString( 10, )} ${currency} should convert to ${oneEthBn}`, - ) - }) - }) - }) + ); + }); + }); + }); describe('#normalizeEthStringToWei', function () { it('should convert decimal eth to pure wei BN', function () { - const input = '1.23456789' - const output = util.normalizeEthStringToWei(input) - assert.strictEqual(output.toString(10), '1234567890000000000') - }) + const input = '1.23456789'; + const output = util.normalizeEthStringToWei(input); + assert.strictEqual(output.toString(10), '1234567890000000000'); + }); it('should convert 1 to expected wei', function () { - const input = '1' - const output = util.normalizeEthStringToWei(input) - assert.strictEqual(output.toString(10), ethInWei) - }) + const input = '1'; + const output = util.normalizeEthStringToWei(input); + assert.strictEqual(output.toString(10), ethInWei); + }); it('should account for overflow numbers gracefully by dropping extra precision.', function () { - const input = '1.11111111111111111111' - const output = util.normalizeEthStringToWei(input) - assert.strictEqual(output.toString(10), '1111111111111111111') - }) + const input = '1.11111111111111111111'; + const output = util.normalizeEthStringToWei(input); + assert.strictEqual(output.toString(10), '1111111111111111111'); + }); it('should not truncate very exact wei values that do not have extra precision.', function () { - const input = '1.100000000000000001' - const output = util.normalizeEthStringToWei(input) - assert.strictEqual(output.toString(10), '1100000000000000001') - }) - }) + const input = '1.100000000000000001'; + const output = util.normalizeEthStringToWei(input); + assert.strictEqual(output.toString(10), '1100000000000000001'); + }); + }); describe('#normalizeNumberToWei', function () { it('should handle a simple use case', function () { - const input = 0.0002 - const output = util.normalizeNumberToWei(input, 'ether') - const str = output.toString(10) - assert.strictEqual(str, '200000000000000') - }) + const input = 0.0002; + const output = util.normalizeNumberToWei(input, 'ether'); + const str = output.toString(10); + assert.strictEqual(str, '200000000000000'); + }); it('should convert a kwei number to the appropriate equivalent wei', function () { - const result = util.normalizeNumberToWei(1.111, 'kwei') - assert.strictEqual(result.toString(10), '1111', 'accepts decimals') - }) + const result = util.normalizeNumberToWei(1.111, 'kwei'); + assert.strictEqual(result.toString(10), '1111', 'accepts decimals'); + }); it('should convert a ether number to the appropriate equivalent wei', function () { - const result = util.normalizeNumberToWei(1.111, 'ether') + const result = util.normalizeNumberToWei(1.111, 'ether'); assert.strictEqual( result.toString(10), '1111000000000000000', 'accepts decimals', - ) - }) - }) + ); + }); + }); describe('#isHex', function () { it('should return true when given a hex string', function () { const result = util.isHex( 'c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2', - ) - assert(result) - }) + ); + assert(result); + }); it('should return false when given a non-hex string', function () { const result = util.isHex( 'c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714imnotreal', - ) - assert(!result) - }) + ); + assert(!result); + }); it('should return false when given a string containing a non letter/number character', function () { const result = util.isHex( 'c3ab8ff13720!8ad9047dd39466b3c%8974e592c2fa383d4a396071imnotreal', - ) - assert(!result) - }) + ); + assert(!result); + }); it('should return true when given a hex string with hex-prefix', function () { const result = util.isHex( '0xc3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2', - ) - assert(result) - }) - }) + ); + assert(result); + }); + }); describe('#getRandomFileName', function () { it('should only return a string containing alphanumeric characters', function () { - const result = util.getRandomFileName() - assert(result.match(/^[a-zA-Z0-9]*$/gu)) - }) + const result = util.getRandomFileName(); + assert(result.match(/^[a-zA-Z0-9]*$/gu)); + }); // 50 samples it('should return a string that is between 6 and 12 characters in length', function () { for (let i = 0; i < 50; i++) { - const result = util.getRandomFileName() - assert(result.length >= 6 && result.length <= 12) + const result = util.getRandomFileName(); + assert(result.length >= 6 && result.length <= 12); } - }) - }) - }) + }); + }); + }); describe('checkExistingAddresses', function () { const tokenList = [ @@ -346,28 +346,28 @@ describe('util', function () { { address: 'n' }, { address: 'Q' }, { address: 'z' }, - ] + ]; it('should return true when a lowercase address matches an uppercase address in the passed list', function () { - assert(util.checkExistingAddresses('q', tokenList) === true) - }) + assert(util.checkExistingAddresses('q', tokenList) === true); + }); it('should return true when an uppercase address matches a lowercase address in the passed list', function () { - assert(util.checkExistingAddresses('N', tokenList) === true) - }) + assert(util.checkExistingAddresses('N', tokenList) === true); + }); it('should return true when a lowercase address matches a lowercase address in the passed list', function () { - assert(util.checkExistingAddresses('z', tokenList) === true) - }) + assert(util.checkExistingAddresses('z', tokenList) === true); + }); it('should return true when an uppercase address matches an uppercase address in the passed list', function () { - assert(util.checkExistingAddresses('Q', tokenList) === true) - }) + assert(util.checkExistingAddresses('Q', tokenList) === true); + }); it('should return false when the passed address is not in the passed list', function () { - assert(util.checkExistingAddresses('b', tokenList) === false) - }) - }) + assert(util.checkExistingAddresses('b', tokenList) === false); + }); + }); describe('toPrecisionWithoutTrailingZeros', function () { const testData = [ @@ -404,17 +404,17 @@ describe('util', function () { { args: ['100000000000000000000', 10], result: '1e+20' }, { args: ['100005000000000000000', 10], result: '1.00005e+20' }, { args: ['100005000000000000000.0', 10], result: '1.00005e+20' }, - ] + ]; testData.forEach(({ args, result }) => { it(`should return ${result} when passed number ${args[0]} and precision ${args[1]}`, function () { assert.strictEqual( util.toPrecisionWithoutTrailingZeros(...args), result, - ) - }) - }) - }) + ); + }); + }); + }); describe('addHexPrefixToObjectValues()', function () { it('should return a new object with the same properties with a 0x prefix', function () { @@ -429,7 +429,7 @@ describe('util', function () { prop2: '0x456', prop3: '0xx', }, - ) - }) - }) -}) + ); + }); + }); +}); diff --git a/ui/app/hooks/tests/useCancelTransaction.test.js b/ui/app/hooks/tests/useCancelTransaction.test.js index 0d3d590f3..28957eb9c 100644 --- a/ui/app/hooks/tests/useCancelTransaction.test.js +++ b/ui/app/hooks/tests/useCancelTransaction.test.js @@ -1,60 +1,60 @@ -import assert from 'assert' -import * as reactRedux from 'react-redux' -import { renderHook } from '@testing-library/react-hooks' -import sinon from 'sinon' -import transactions from '../../../../test/data/transaction-data.json' -import { getConversionRate, getSelectedAccount } from '../../selectors' -import { useCancelTransaction } from '../useCancelTransaction' -import { showModal } from '../../store/actions' -import { increaseLastGasPrice } from '../../helpers/utils/confirm-tx.util' +import assert from 'assert'; +import * as reactRedux from 'react-redux'; +import { renderHook } from '@testing-library/react-hooks'; +import sinon from 'sinon'; +import transactions from '../../../../test/data/transaction-data.json'; +import { getConversionRate, getSelectedAccount } from '../../selectors'; +import { useCancelTransaction } from '../useCancelTransaction'; +import { showModal } from '../../store/actions'; +import { increaseLastGasPrice } from '../../helpers/utils/confirm-tx.util'; describe('useCancelTransaction', function () { - let useSelector - const dispatch = sinon.spy() + let useSelector; + const dispatch = sinon.spy(); before(function () { - sinon.stub(reactRedux, 'useDispatch').returns(dispatch) - }) + sinon.stub(reactRedux, 'useDispatch').returns(dispatch); + }); afterEach(function () { - dispatch.resetHistory() - }) + dispatch.resetHistory(); + }); describe('when account has insufficient balance to cover gas', function () { before(function () { - useSelector = sinon.stub(reactRedux, 'useSelector') + useSelector = sinon.stub(reactRedux, 'useSelector'); useSelector.callsFake((selector) => { if (selector === getConversionRate) { - return 280.46 + return 280.46; } else if (selector === getSelectedAccount) { return { balance: '0x3', - } + }; } - return undefined - }) - }) + return undefined; + }); + }); transactions.forEach((transactionGroup) => { const originalGasPrice = - transactionGroup.primaryTransaction.txParams?.gasPrice + transactionGroup.primaryTransaction.txParams?.gasPrice; const gasPrice = - originalGasPrice && increaseLastGasPrice(originalGasPrice) - const transactionId = transactionGroup.initialTransaction.id + originalGasPrice && increaseLastGasPrice(originalGasPrice); + const transactionId = transactionGroup.initialTransaction.id; it(`should indicate account has insufficient funds to cover ${gasPrice} gas price`, function () { const { result } = renderHook(() => useCancelTransaction(transactionGroup), - ) - assert.strictEqual(result.current[0], false) - }) + ); + assert.strictEqual(result.current[0], false); + }); it(`should return a function that kicks off cancellation for id ${transactionId}`, function () { const { result } = renderHook(() => useCancelTransaction(transactionGroup), - ) - assert.strictEqual(typeof result.current[1], 'function') + ); + assert.strictEqual(typeof result.current[1], 'function'); result.current[1]({ preventDefault: () => undefined, stopPropagation: () => undefined, - }) + }); assert.strictEqual( dispatch.calledWith( showModal({ @@ -64,49 +64,49 @@ describe('useCancelTransaction', function () { }), ), true, - ) - }) - }) + ); + }); + }); after(function () { - useSelector.restore() - }) - }) + useSelector.restore(); + }); + }); describe('when account has sufficient balance to cover gas', function () { before(function () { - useSelector = sinon.stub(reactRedux, 'useSelector') + useSelector = sinon.stub(reactRedux, 'useSelector'); useSelector.callsFake((selector) => { if (selector === getConversionRate) { - return 280.46 + return 280.46; } else if (selector === getSelectedAccount) { return { balance: '0x9C2007651B2500000', - } + }; } - return undefined - }) - }) + return undefined; + }); + }); transactions.forEach((transactionGroup) => { const originalGasPrice = - transactionGroup.primaryTransaction.txParams?.gasPrice + transactionGroup.primaryTransaction.txParams?.gasPrice; const gasPrice = - originalGasPrice && increaseLastGasPrice(originalGasPrice) - const transactionId = transactionGroup.initialTransaction.id + originalGasPrice && increaseLastGasPrice(originalGasPrice); + const transactionId = transactionGroup.initialTransaction.id; it(`should indicate account has funds to cover ${gasPrice} gas price`, function () { const { result } = renderHook(() => useCancelTransaction(transactionGroup), - ) - assert.strictEqual(result.current[0], true) - }) + ); + assert.strictEqual(result.current[0], true); + }); it(`should return a function that kicks off cancellation for id ${transactionId}`, function () { const { result } = renderHook(() => useCancelTransaction(transactionGroup), - ) - assert.strictEqual(typeof result.current[1], 'function') + ); + assert.strictEqual(typeof result.current[1], 'function'); result.current[1]({ preventDefault: () => undefined, stopPropagation: () => undefined, - }) + }); assert.strictEqual( dispatch.calledWith( showModal({ @@ -116,15 +116,15 @@ describe('useCancelTransaction', function () { }), ), true, - ) - }) - }) + ); + }); + }); after(function () { - useSelector.restore() - }) - }) + useSelector.restore(); + }); + }); after(function () { - sinon.restore() - }) -}) + sinon.restore(); + }); +}); diff --git a/ui/app/hooks/tests/useCurrencyDisplay.test.js b/ui/app/hooks/tests/useCurrencyDisplay.test.js index 4b90e9a79..8b019ab87 100644 --- a/ui/app/hooks/tests/useCurrencyDisplay.test.js +++ b/ui/app/hooks/tests/useCurrencyDisplay.test.js @@ -1,13 +1,13 @@ -import assert from 'assert' -import { renderHook } from '@testing-library/react-hooks' -import * as reactRedux from 'react-redux' -import sinon from 'sinon' -import { useCurrencyDisplay } from '../useCurrencyDisplay' +import assert from 'assert'; +import { renderHook } from '@testing-library/react-hooks'; +import * as reactRedux from 'react-redux'; +import sinon from 'sinon'; +import { useCurrencyDisplay } from '../useCurrencyDisplay'; import { getCurrentCurrency, getNativeCurrency, getConversionRate, -} from '../../selectors' +} from '../../selectors'; const tests = [ { @@ -97,34 +97,34 @@ const tests = [ displayValue: '0.000000001', }, }, -] +]; describe('useCurrencyDisplay', function () { tests.forEach(({ input: { value, ...restProps }, result }) => { describe(`when input is { value: ${value}, decimals: ${restProps.numberOfDecimals}, denomation: ${restProps.denomination} }`, function () { - const stub = sinon.stub(reactRedux, 'useSelector') + const stub = sinon.stub(reactRedux, 'useSelector'); stub.callsFake((selector) => { if (selector === getCurrentCurrency) { - return 'usd' + return 'usd'; } else if (selector === getNativeCurrency) { - return 'ETH' + return 'ETH'; } else if (selector === getConversionRate) { - return 280.45 + return 280.45; } - return undefined - }) - const hookReturn = renderHook(() => useCurrencyDisplay(value, restProps)) - const [displayValue, parts] = hookReturn.result.current - stub.restore() + return undefined; + }); + const hookReturn = renderHook(() => useCurrencyDisplay(value, restProps)); + const [displayValue, parts] = hookReturn.result.current; + stub.restore(); it(`should return ${result.displayValue} as displayValue`, function () { - assert.strictEqual(displayValue, result.displayValue) - }) + assert.strictEqual(displayValue, result.displayValue); + }); it(`should return ${result.value} as value`, function () { - assert.strictEqual(parts.value, result.value) - }) + assert.strictEqual(parts.value, result.value); + }); it(`should return ${result.suffix} as suffix`, function () { - assert.strictEqual(parts.suffix, result.suffix) - }) - }) - }) -}) + assert.strictEqual(parts.suffix, result.suffix); + }); + }); + }); +}); diff --git a/ui/app/hooks/tests/useRetryTransaction.test.js b/ui/app/hooks/tests/useRetryTransaction.test.js index 91d99026d..52be98fc1 100644 --- a/ui/app/hooks/tests/useRetryTransaction.test.js +++ b/ui/app/hooks/tests/useRetryTransaction.test.js @@ -1,32 +1,32 @@ -import assert from 'assert' -import * as reactRedux from 'react-redux' -import { renderHook } from '@testing-library/react-hooks' -import sinon from 'sinon' -import transactions from '../../../../test/data/transaction-data.json' -import * as methodDataHook from '../useMethodData' -import * as metricEventHook from '../useMetricEvent' -import { showSidebar } from '../../store/actions' -import { useRetryTransaction } from '../useRetryTransaction' +import assert from 'assert'; +import * as reactRedux from 'react-redux'; +import { renderHook } from '@testing-library/react-hooks'; +import sinon from 'sinon'; +import transactions from '../../../../test/data/transaction-data.json'; +import * as methodDataHook from '../useMethodData'; +import * as metricEventHook from '../useMetricEvent'; +import { showSidebar } from '../../store/actions'; +import { useRetryTransaction } from '../useRetryTransaction'; describe('useRetryTransaction', function () { describe('when transaction meets retry enabled criteria', function () { - const dispatch = sinon.spy(() => Promise.resolve({ blockTime: 0 })) - const trackEvent = sinon.spy() + const dispatch = sinon.spy(() => Promise.resolve({ blockTime: 0 })); + const trackEvent = sinon.spy(); const event = { preventDefault: () => undefined, stopPropagation: () => undefined, - } + }; before(function () { - sinon.stub(reactRedux, 'useDispatch').returns(dispatch) - sinon.stub(methodDataHook, 'useMethodData').returns({}) - sinon.stub(metricEventHook, 'useMetricEvent').returns(trackEvent) - }) + sinon.stub(reactRedux, 'useDispatch').returns(dispatch); + sinon.stub(methodDataHook, 'useMethodData').returns({}); + sinon.stub(metricEventHook, 'useMetricEvent').returns(trackEvent); + }); afterEach(function () { - dispatch.resetHistory() - trackEvent.resetHistory() - }) + dispatch.resetHistory(); + trackEvent.resetHistory(); + }); const retryEnabledTransaction = { ...transactions[0], transactions: [ @@ -35,23 +35,23 @@ describe('useRetryTransaction', function () { }, ], hasRetried: false, - } + }; it('retryTransaction function should track metrics', function () { const { result } = renderHook(() => useRetryTransaction(retryEnabledTransaction, true), - ) - const retry = result.current - retry(event) - assert.strictEqual(trackEvent.calledOnce, true) - }) + ); + const retry = result.current; + retry(event); + assert.strictEqual(trackEvent.calledOnce, true); + }); it('retryTransaction function should show retry sidebar', async function () { const { result } = renderHook(() => useRetryTransaction(retryEnabledTransaction, true), - ) - const retry = result.current - await retry(event) + ); + const retry = result.current; + await retry(event); assert.strictEqual( dispatch.calledWith( showSidebar({ @@ -61,11 +61,11 @@ describe('useRetryTransaction', function () { }), ), true, - ) - }) + ); + }); after(function () { - sinon.restore() - }) - }) -}) + sinon.restore(); + }); + }); +}); diff --git a/ui/app/hooks/tests/useTokenData.test.js b/ui/app/hooks/tests/useTokenData.test.js index ec473300d..593176105 100644 --- a/ui/app/hooks/tests/useTokenData.test.js +++ b/ui/app/hooks/tests/useTokenData.test.js @@ -1,8 +1,8 @@ -import assert from 'assert' -import { ethers } from 'ethers' -import { renderHook } from '@testing-library/react-hooks' -import { useTokenData } from '../useTokenData' -import { TRANSACTION_CATEGORIES } from '../../../../shared/constants/transaction' +import assert from 'assert'; +import { ethers } from 'ethers'; +import { renderHook } from '@testing-library/react-hooks'; +import { useTokenData } from '../useTokenData'; +import { TRANSACTION_CATEGORIES } from '../../../../shared/constants/transaction'; const tests = [ { @@ -42,26 +42,26 @@ const tests = [ data: undefined, tokenData: null, }, -] +]; describe('useTokenData', function () { tests.forEach((test) => { const testTitle = test.tokenData === null ? `should return null when no data provided` - : `should return properly decoded data with _value ${test.tokenData.args[1].value}` + : `should return properly decoded data with _value ${test.tokenData.args[1].value}`; it(testTitle, function () { - const { result } = renderHook(() => useTokenData(test.data)) + const { result } = renderHook(() => useTokenData(test.data)); if (test.tokenData) { - assert.strictEqual(result.current.name, test.tokenData.name) + assert.strictEqual(result.current.name, test.tokenData.name); assert.strictEqual( result.current.args[0].toLowerCase(), test.tokenData.args[0], - ) - assert.ok(test.tokenData.args[1].eq(result.current.args[1])) + ); + assert.ok(test.tokenData.args[1].eq(result.current.args[1])); } else { - assert.strictEqual(result.current, test.tokenData) + assert.strictEqual(result.current, test.tokenData); } - }) - }) -}) + }); + }); +}); diff --git a/ui/app/hooks/tests/useTokenDisplayValue.test.js b/ui/app/hooks/tests/useTokenDisplayValue.test.js index bc77bd6c7..6fc6f6105 100644 --- a/ui/app/hooks/tests/useTokenDisplayValue.test.js +++ b/ui/app/hooks/tests/useTokenDisplayValue.test.js @@ -1,9 +1,9 @@ -import assert from 'assert' -import { renderHook } from '@testing-library/react-hooks' -import sinon from 'sinon' -import * as tokenUtil from '../../helpers/utils/token-util' -import * as txUtil from '../../helpers/utils/transactions.util' -import { useTokenDisplayValue } from '../useTokenDisplayValue' +import assert from 'assert'; +import { renderHook } from '@testing-library/react-hooks'; +import sinon from 'sinon'; +import * as tokenUtil from '../../helpers/utils/token-util'; +import * as txUtil from '../../helpers/utils/transactions.util'; +import { useTokenDisplayValue } from '../useTokenDisplayValue'; const tests = [ { @@ -116,22 +116,22 @@ const tests = [ tokenValue: '25500000', displayValue: '25.5', }, -] +]; describe('useTokenDisplayValue', function () { tests.forEach((test, idx) => { describe(`when input is decimals: ${test.token.decimals} and value: ${test.tokenValue}`, function () { it(`should return ${test.displayValue} as displayValue`, function () { - const getTokenValueStub = sinon.stub(tokenUtil, 'getTokenValueParam') - const getTokenDataStub = sinon.stub(txUtil, 'getTokenData') - getTokenDataStub.callsFake(() => test.tokenData) - getTokenValueStub.callsFake(() => test.tokenValue) + const getTokenValueStub = sinon.stub(tokenUtil, 'getTokenValueParam'); + const getTokenDataStub = sinon.stub(txUtil, 'getTokenData'); + getTokenDataStub.callsFake(() => test.tokenData); + getTokenValueStub.callsFake(() => test.tokenValue); const { result } = renderHook(() => useTokenDisplayValue(`${idx}-fakestring`, test.token), - ) - sinon.restore() - assert.strictEqual(result.current, test.displayValue) - }) - }) - }) -}) + ); + sinon.restore(); + assert.strictEqual(result.current, test.displayValue); + }); + }); + }); +}); diff --git a/ui/app/hooks/tests/useTransactionDisplayData.test.js b/ui/app/hooks/tests/useTransactionDisplayData.test.js index 64c6a0366..96a24c08b 100644 --- a/ui/app/hooks/tests/useTransactionDisplayData.test.js +++ b/ui/app/hooks/tests/useTransactionDisplayData.test.js @@ -1,28 +1,28 @@ -import assert from 'assert' -import React from 'react' -import * as reactRedux from 'react-redux' -import { renderHook } from '@testing-library/react-hooks' -import sinon from 'sinon' -import { MemoryRouter } from 'react-router-dom' -import transactions from '../../../../test/data/transaction-data.json' -import { useTransactionDisplayData } from '../useTransactionDisplayData' -import * as useTokenFiatAmountHooks from '../useTokenFiatAmount' +import assert from 'assert'; +import React from 'react'; +import * as reactRedux from 'react-redux'; +import { renderHook } from '@testing-library/react-hooks'; +import sinon from 'sinon'; +import { MemoryRouter } from 'react-router-dom'; +import transactions from '../../../../test/data/transaction-data.json'; +import { useTransactionDisplayData } from '../useTransactionDisplayData'; +import * as useTokenFiatAmountHooks from '../useTokenFiatAmount'; import { getPreferences, getShouldShowFiat, getNativeCurrency, getCurrentCurrency, -} from '../../selectors' -import { getTokens } from '../../ducks/metamask/metamask' -import * as i18nhooks from '../useI18nContext' -import { getMessage } from '../../helpers/utils/i18n-helper' -import messages from '../../../../app/_locales/en/messages.json' -import { ASSET_ROUTE, DEFAULT_ROUTE } from '../../helpers/constants/routes' +} from '../../selectors'; +import { getTokens } from '../../ducks/metamask/metamask'; +import * as i18nhooks from '../useI18nContext'; +import { getMessage } from '../../helpers/utils/i18n-helper'; +import messages from '../../../../app/_locales/en/messages.json'; +import { ASSET_ROUTE, DEFAULT_ROUTE } from '../../helpers/constants/routes'; import { TRANSACTION_CATEGORIES, TRANSACTION_GROUP_CATEGORIES, TRANSACTION_STATUSES, -} from '../../../../shared/constants/transaction' +} from '../../../../shared/constants/transaction'; const expectedResults = [ { @@ -117,34 +117,34 @@ const expectedResults = [ isPending: false, displayedStatusKey: TRANSACTION_STATUSES.CONFIRMED, }, -] +]; -let useSelector, useI18nContext, useTokenFiatAmount +let useSelector, useI18nContext, useTokenFiatAmount; const renderHookWithRouter = (cb, tokenAddress) => { const initialEntries = [ tokenAddress ? `${ASSET_ROUTE}/${tokenAddress}` : DEFAULT_ROUTE, - ] + ]; const wrapper = ({ children }) => ( {children} - ) - return renderHook(cb, { wrapper }) -} + ); + return renderHook(cb, { wrapper }); +}; describe('useTransactionDisplayData', function () { before(function () { - useSelector = sinon.stub(reactRedux, 'useSelector') + useSelector = sinon.stub(reactRedux, 'useSelector'); useTokenFiatAmount = sinon.stub( useTokenFiatAmountHooks, 'useTokenFiatAmount', - ) + ); useTokenFiatAmount.returns((tokenAddress) => { - return tokenAddress ? '1 TST' : undefined - }) - useI18nContext = sinon.stub(i18nhooks, 'useI18nContext') + return tokenAddress ? '1 TST' : undefined; + }); + useI18nContext = sinon.stub(i18nhooks, 'useI18nContext'); useI18nContext.returns((key, variables) => getMessage('en', messages, key, variables), - ) + ); useSelector.callsFake((selector) => { if (selector === getTokens) { return [ @@ -153,104 +153,107 @@ describe('useTransactionDisplayData', function () { symbol: 'ABC', decimals: 18, }, - ] + ]; } else if (selector === getPreferences) { return { useNativeCurrencyAsPrimaryCurrency: true, - } + }; } else if (selector === getShouldShowFiat) { - return false + return false; } else if (selector === getNativeCurrency) { - return 'ETH' + return 'ETH'; } else if (selector === getCurrentCurrency) { - return 'ETH' + return 'ETH'; } - return null - }) - }) + return null; + }); + }); transactions.forEach((transactionGroup, idx) => { describe(`when called with group containing primaryTransaction id ${transactionGroup.primaryTransaction.id}`, function () { - const expected = expectedResults[idx] + const expected = expectedResults[idx]; const tokenAddress = - transactionGroup.primaryTransaction?.destinationTokenAddress + transactionGroup.primaryTransaction?.destinationTokenAddress; it(`should return a title of ${expected.title}`, function () { const { result } = renderHookWithRouter( () => useTransactionDisplayData(transactionGroup), tokenAddress, - ) - assert.strictEqual(result.current.title, expected.title) - }) + ); + assert.strictEqual(result.current.title, expected.title); + }); it(`should return a subtitle of ${expected.subtitle}`, function () { const { result } = renderHookWithRouter( () => useTransactionDisplayData(transactionGroup), tokenAddress, - ) - assert.strictEqual(result.current.subtitle, expected.subtitle) - }) + ); + assert.strictEqual(result.current.subtitle, expected.subtitle); + }); it(`should return a category of ${expected.category}`, function () { const { result } = renderHookWithRouter( () => useTransactionDisplayData(transactionGroup), tokenAddress, - ) - assert.strictEqual(result.current.category, expected.category) - }) + ); + assert.strictEqual(result.current.category, expected.category); + }); it(`should return a primaryCurrency of ${expected.primaryCurrency}`, function () { const { result } = renderHookWithRouter( () => useTransactionDisplayData(transactionGroup), tokenAddress, - ) + ); assert.strictEqual( result.current.primaryCurrency, expected.primaryCurrency, - ) - }) + ); + }); it(`should return a secondaryCurrency of ${expected.secondaryCurrency}`, function () { const { result } = renderHookWithRouter( () => useTransactionDisplayData(transactionGroup), tokenAddress, - ) + ); assert.strictEqual( result.current.secondaryCurrency, expected.secondaryCurrency, - ) - }) + ); + }); it(`should return a displayedStatusKey of ${expected.displayedStatusKey}`, function () { const { result } = renderHookWithRouter( () => useTransactionDisplayData(transactionGroup), tokenAddress, - ) + ); assert.strictEqual( result.current.displayedStatusKey, expected.displayedStatusKey, - ) - }) + ); + }); it(`should return a recipientAddress of ${expected.recipientAddress}`, function () { const { result } = renderHookWithRouter( () => useTransactionDisplayData(transactionGroup), tokenAddress, - ) + ); assert.strictEqual( result.current.recipientAddress, expected.recipientAddress, - ) - }) + ); + }); it(`should return a senderAddress of ${expected.senderAddress}`, function () { const { result } = renderHookWithRouter( () => useTransactionDisplayData(transactionGroup), tokenAddress, - ) - assert.strictEqual(result.current.senderAddress, expected.senderAddress) - }) - }) - }) + ); + assert.strictEqual( + result.current.senderAddress, + expected.senderAddress, + ); + }); + }); + }); it('should return an appropriate object', function () { const { result } = renderHookWithRouter(() => useTransactionDisplayData(transactions[0]), - ) - assert.deepStrictEqual(result.current, expectedResults[0]) - }) + ); + assert.deepStrictEqual(result.current, expectedResults[0]); + }); after(function () { - useSelector.restore() - useI18nContext.restore() - }) -}) + useSelector.restore(); + useI18nContext.restore(); + }); +}); diff --git a/ui/app/hooks/tests/useUserPreferencedCurrency.test.js b/ui/app/hooks/tests/useUserPreferencedCurrency.test.js index 0386e6ec4..75ee4cf66 100644 --- a/ui/app/hooks/tests/useUserPreferencedCurrency.test.js +++ b/ui/app/hooks/tests/useUserPreferencedCurrency.test.js @@ -1,9 +1,9 @@ -import assert from 'assert' -import { renderHook } from '@testing-library/react-hooks' -import * as reactRedux from 'react-redux' -import sinon from 'sinon' -import { useUserPreferencedCurrency } from '../useUserPreferencedCurrency' -import { getPreferences, getShouldShowFiat } from '../../selectors' +import assert from 'assert'; +import { renderHook } from '@testing-library/react-hooks'; +import * as reactRedux from 'react-redux'; +import sinon from 'sinon'; +import { useUserPreferencedCurrency } from '../useUserPreferencedCurrency'; +import { getPreferences, getShouldShowFiat } from '../../selectors'; const tests = [ { @@ -109,42 +109,42 @@ const tests = [ numberOfDecimals: 2, }, }, -] +]; function getFakeUseSelector(state) { return (selector) => { if (selector === getPreferences) { - return state + return state; } else if (selector === getShouldShowFiat) { - return state.showFiat + return state.showFiat; } - return state.nativeCurrency - } + return state.nativeCurrency; + }; } describe('useUserPreferencedCurrency', function () { tests.forEach(({ params: { type, ...otherParams }, state, result }) => { describe(`when showFiat is ${state.showFiat}, useNativeCurrencyAsPrimary is ${state.useNativeCurrencyAsPrimaryCurrency} and type is ${type}`, function () { - const stub = sinon.stub(reactRedux, 'useSelector') - stub.callsFake(getFakeUseSelector(state)) + const stub = sinon.stub(reactRedux, 'useSelector'); + stub.callsFake(getFakeUseSelector(state)); const { result: hookResult } = renderHook(() => useUserPreferencedCurrency(type, otherParams), - ) - stub.restore() + ); + stub.restore(); it(`should return currency as ${ result.currency || 'not modified by user preferences' }`, function () { - assert.strictEqual(hookResult.current.currency, result.currency) - }) + assert.strictEqual(hookResult.current.currency, result.currency); + }); it(`should return decimals as ${ result.numberOfDecimals || 'not modified by user preferences' }`, function () { assert.strictEqual( hookResult.current.numberOfDecimals, result.numberOfDecimals, - ) - }) - }) - }) -}) + ); + }); + }); + }); +}); diff --git a/ui/app/hooks/useCancelTransaction.js b/ui/app/hooks/useCancelTransaction.js index 3d478e410..1ad4c12f8 100644 --- a/ui/app/hooks/useCancelTransaction.js +++ b/ui/app/hooks/useCancelTransaction.js @@ -1,12 +1,12 @@ -import { useDispatch, useSelector } from 'react-redux' -import { useCallback } from 'react' -import { showModal } from '../store/actions' -import { isBalanceSufficient } from '../pages/send/send.utils' +import { useDispatch, useSelector } from 'react-redux'; +import { useCallback } from 'react'; +import { showModal } from '../store/actions'; +import { isBalanceSufficient } from '../pages/send/send.utils'; import { getHexGasTotal, increaseLastGasPrice, -} from '../helpers/utils/confirm-tx.util' -import { getConversionRate, getSelectedAccount } from '../selectors' +} from '../helpers/utils/confirm-tx.util'; +import { getConversionRate, getSelectedAccount } from '../selectors'; /** * Determine whether a transaction can be cancelled and provide a method to @@ -19,17 +19,17 @@ import { getConversionRate, getSelectedAccount } from '../selectors' * @return {[boolean, Function]} */ export function useCancelTransaction(transactionGroup) { - const { primaryTransaction, initialTransaction } = transactionGroup + const { primaryTransaction, initialTransaction } = transactionGroup; const gasPrice = primaryTransaction.txParams?.gasPrice?.startsWith('-') ? '0x0' - : primaryTransaction.txParams?.gasPrice - const { id } = initialTransaction - const dispatch = useDispatch() - const selectedAccount = useSelector(getSelectedAccount) - const conversionRate = useSelector(getConversionRate) + : primaryTransaction.txParams?.gasPrice; + const { id } = initialTransaction; + const dispatch = useDispatch(); + const selectedAccount = useSelector(getSelectedAccount); + const conversionRate = useSelector(getConversionRate); const cancelTransaction = useCallback( (event) => { - event.stopPropagation() + event.stopPropagation(); return dispatch( showModal({ @@ -37,10 +37,10 @@ export function useCancelTransaction(transactionGroup) { transactionId: id, originalGasPrice: gasPrice, }), - ) + ); }, [dispatch, id, gasPrice], - ) + ); const hasEnoughCancelGas = primaryTransaction.txParams && @@ -52,7 +52,7 @@ export function useCancelTransaction(transactionGroup) { }), balance: selectedAccount.balance, conversionRate, - }) + }); - return [hasEnoughCancelGas, cancelTransaction] + return [hasEnoughCancelGas, cancelTransaction]; } diff --git a/ui/app/hooks/useCopyToClipboard.js b/ui/app/hooks/useCopyToClipboard.js index 542496e15..33635d722 100644 --- a/ui/app/hooks/useCopyToClipboard.js +++ b/ui/app/hooks/useCopyToClipboard.js @@ -1,6 +1,6 @@ -import { useState, useCallback } from 'react' -import copyToClipboard from 'copy-to-clipboard' -import { useTimeout } from './useTimeout' +import { useState, useCallback } from 'react'; +import copyToClipboard from 'copy-to-clipboard'; +import { useTimeout } from './useTimeout'; /** * useCopyToClipboard @@ -9,20 +9,20 @@ import { useTimeout } from './useTimeout' * * @return {[boolean, Function]} */ -const DEFAULT_DELAY = 3000 +const DEFAULT_DELAY = 3000; export function useCopyToClipboard(delay = DEFAULT_DELAY) { - const [copied, setCopied] = useState(false) - const startTimeout = useTimeout(() => setCopied(false), delay, false) + const [copied, setCopied] = useState(false); + const startTimeout = useTimeout(() => setCopied(false), delay, false); const handleCopy = useCallback( (text) => { - setCopied(true) - startTimeout() - copyToClipboard(text) + setCopied(true); + startTimeout(); + copyToClipboard(text); }, [startTimeout], - ) + ); - return [copied, handleCopy] + return [copied, handleCopy]; } diff --git a/ui/app/hooks/useCurrencyDisplay.js b/ui/app/hooks/useCurrencyDisplay.js index 14e274d2f..8b3f8271d 100644 --- a/ui/app/hooks/useCurrencyDisplay.js +++ b/ui/app/hooks/useCurrencyDisplay.js @@ -1,14 +1,14 @@ -import { useMemo } from 'react' -import { useSelector } from 'react-redux' +import { useMemo } from 'react'; +import { useSelector } from 'react-redux'; import { formatCurrency, getValueFromWeiHex, -} from '../helpers/utils/confirm-tx.util' +} from '../helpers/utils/confirm-tx.util'; import { getCurrentCurrency, getConversionRate, getNativeCurrency, -} from '../selectors' +} from '../selectors'; /** * Defines the shape of the options parameter for useCurrencyDisplay @@ -42,15 +42,15 @@ export function useCurrencyDisplay( inputValue, { displayValue, prefix, numberOfDecimals, denomination, currency, ...opts }, ) { - const currentCurrency = useSelector(getCurrentCurrency) - const nativeCurrency = useSelector(getNativeCurrency) - const conversionRate = useSelector(getConversionRate) + const currentCurrency = useSelector(getCurrentCurrency); + const nativeCurrency = useSelector(getNativeCurrency); + const conversionRate = useSelector(getConversionRate); - const toCurrency = currency || currentCurrency + const toCurrency = currency || currentCurrency; const value = useMemo(() => { if (displayValue) { - return displayValue + return displayValue; } return formatCurrency( getValueFromWeiHex({ @@ -62,7 +62,7 @@ export function useCurrencyDisplay( toDenomination: denomination, }), toCurrency, - ) + ); }, [ inputValue, nativeCurrency, @@ -71,16 +71,16 @@ export function useCurrencyDisplay( numberOfDecimals, denomination, toCurrency, - ]) + ]); - let suffix + let suffix; if (!opts.hideLabel) { - suffix = opts.suffix || toCurrency.toUpperCase() + suffix = opts.suffix || toCurrency.toUpperCase(); } return [ `${prefix || ''}${value}${suffix ? ` ${suffix}` : ''}`, { prefix, value, suffix }, - ] + ]; } diff --git a/ui/app/hooks/useCurrentAsset.js b/ui/app/hooks/useCurrentAsset.js index 80e905a94..d1d144bed 100644 --- a/ui/app/hooks/useCurrentAsset.js +++ b/ui/app/hooks/useCurrentAsset.js @@ -1,8 +1,8 @@ -import { useSelector } from 'react-redux' -import { useRouteMatch } from 'react-router-dom' -import { getTokens } from '../ducks/metamask/metamask' -import { ASSET_ROUTE } from '../helpers/constants/routes' -import { ETH_SWAPS_TOKEN_OBJECT } from '../helpers/constants/swaps' +import { useSelector } from 'react-redux'; +import { useRouteMatch } from 'react-router-dom'; +import { getTokens } from '../ducks/metamask/metamask'; +import { ASSET_ROUTE } from '../helpers/constants/routes'; +import { ETH_SWAPS_TOKEN_OBJECT } from '../helpers/constants/swaps'; /** * Returns a token object for the asset that is currently being viewed. @@ -17,11 +17,11 @@ export function useCurrentAsset() { path: `${ASSET_ROUTE}/:asset`, exact: true, strict: true, - }) - const tokenAddress = match?.params?.asset - const knownTokens = useSelector(getTokens) + }); + const tokenAddress = match?.params?.asset; + const knownTokens = useSelector(getTokens); const token = - tokenAddress && knownTokens.find(({ address }) => address === tokenAddress) + tokenAddress && knownTokens.find(({ address }) => address === tokenAddress); - return token ?? ETH_SWAPS_TOKEN_OBJECT + return token ?? ETH_SWAPS_TOKEN_OBJECT; } diff --git a/ui/app/hooks/useEqualityCheck.js b/ui/app/hooks/useEqualityCheck.js index 4212beeab..3cce17750 100644 --- a/ui/app/hooks/useEqualityCheck.js +++ b/ui/app/hooks/useEqualityCheck.js @@ -1,6 +1,6 @@ -import { useState, useLayoutEffect } from 'react' +import { useState, useLayoutEffect } from 'react'; -import { isEqual } from 'lodash' +import { isEqual } from 'lodash'; /** * Given a value and a function to determine equality, return a @@ -15,13 +15,13 @@ import { isEqual } from 'lodash' * @returns {T} */ export function useEqualityCheck(value, equalityFn = isEqual) { - const [computedValue, setComputedValue] = useState(value) + const [computedValue, setComputedValue] = useState(value); useLayoutEffect(() => { if (!equalityFn(value, computedValue)) { - setComputedValue(value) + setComputedValue(value); } - }, [value, equalityFn, computedValue]) + }, [value, equalityFn, computedValue]); - return computedValue + return computedValue; } diff --git a/ui/app/hooks/useEthFiatAmount.js b/ui/app/hooks/useEthFiatAmount.js index 7e89e3ad3..10ce71789 100644 --- a/ui/app/hooks/useEthFiatAmount.js +++ b/ui/app/hooks/useEthFiatAmount.js @@ -1,12 +1,12 @@ -import { useMemo } from 'react' -import { useSelector } from 'react-redux' +import { useMemo } from 'react'; +import { useSelector } from 'react-redux'; import { getConversionRate, getCurrentCurrency, getShouldShowFiat, -} from '../selectors' -import { decEthToConvertedCurrency } from '../helpers/utils/conversions.util' -import { formatCurrency } from '../helpers/utils/confirm-tx.util' +} from '../selectors'; +import { decEthToConvertedCurrency } from '../helpers/utils/conversions.util'; +import { formatCurrency } from '../helpers/utils/confirm-tx.util'; /** * Get an Eth amount converted to fiat and formatted for display @@ -23,14 +23,14 @@ export function useEthFiatAmount( overrides = {}, hideCurrencySymbol, ) { - const conversionRate = useSelector(getConversionRate) - const currentCurrency = useSelector(getCurrentCurrency) - const userPrefersShownFiat = useSelector(getShouldShowFiat) - const showFiat = overrides.showFiat ?? userPrefersShownFiat + const conversionRate = useSelector(getConversionRate); + const currentCurrency = useSelector(getCurrentCurrency); + const userPrefersShownFiat = useSelector(getShouldShowFiat); + const showFiat = overrides.showFiat ?? userPrefersShownFiat; const formattedFiat = useMemo( () => decEthToConvertedCurrency(ethAmount, currentCurrency, conversionRate), [conversionRate, currentCurrency, ethAmount], - ) + ); if ( !showFiat || @@ -38,7 +38,7 @@ export function useEthFiatAmount( conversionRate <= 0 || ethAmount === undefined ) { - return undefined + return undefined; } return hideCurrencySymbol @@ -46,5 +46,5 @@ export function useEthFiatAmount( : `${formatCurrency( formattedFiat, currentCurrency, - )} ${currentCurrency.toUpperCase()}` + )} ${currentCurrency.toUpperCase()}`; } diff --git a/ui/app/hooks/useI18nContext.js b/ui/app/hooks/useI18nContext.js index d2fb087c3..3a1dfa652 100644 --- a/ui/app/hooks/useI18nContext.js +++ b/ui/app/hooks/useI18nContext.js @@ -1,5 +1,5 @@ -import { useContext } from 'react' -import { I18nContext } from '../contexts/i18n' +import { useContext } from 'react'; +import { I18nContext } from '../contexts/i18n'; /** * useI18ncContext @@ -9,5 +9,5 @@ import { I18nContext } from '../contexts/i18n' * @return {Function} I18n function from contexts/I18n.js */ export function useI18nContext() { - return useContext(I18nContext) + return useContext(I18nContext); } diff --git a/ui/app/hooks/useMethodData.js b/ui/app/hooks/useMethodData.js index 124e130b1..f4ce2f634 100644 --- a/ui/app/hooks/useMethodData.js +++ b/ui/app/hooks/useMethodData.js @@ -1,8 +1,8 @@ -import { useEffect, useCallback } from 'react' -import { useDispatch, useSelector } from 'react-redux' -import { getContractMethodData as getContractMethodDataAction } from '../store/actions' +import { useEffect, useCallback } from 'react'; +import { useDispatch, useSelector } from 'react-redux'; +import { getContractMethodData as getContractMethodDataAction } from '../store/actions'; -import { getKnownMethodData } from '../selectors/selectors' +import { getKnownMethodData } from '../selectors/selectors'; /** * Access known method data and attempt to resolve unknown method data @@ -17,19 +17,19 @@ import { getKnownMethodData } from '../selectors/selectors' * @return {Object} contract method data */ export function useMethodData(data) { - const dispatch = useDispatch() + const dispatch = useDispatch(); const knownMethodData = useSelector((state) => getKnownMethodData(state, data), - ) + ); const getContractMethodData = useCallback( (methodData) => dispatch(getContractMethodDataAction(methodData)), [dispatch], - ) + ); useEffect(() => { if (data) { - getContractMethodData(data) + getContractMethodData(data); } - }, [getContractMethodData, data]) - return knownMethodData + }, [getContractMethodData, data]); + return knownMethodData; } diff --git a/ui/app/hooks/useMetricEvent.js b/ui/app/hooks/useMetricEvent.js index e428fc5d2..b30b37eb5 100644 --- a/ui/app/hooks/useMetricEvent.js +++ b/ui/app/hooks/useMetricEvent.js @@ -1,7 +1,7 @@ -import { useContext, useCallback } from 'react' -import { MetaMetricsContext } from '../contexts/metametrics' -import { MetaMetricsContext as NewMetaMetricsContext } from '../contexts/metametrics.new' -import { useEqualityCheck } from './useEqualityCheck' +import { useContext, useCallback } from 'react'; +import { MetaMetricsContext } from '../contexts/metametrics'; +import { MetaMetricsContext as NewMetaMetricsContext } from '../contexts/metametrics.new'; +import { useEqualityCheck } from './useEqualityCheck'; // Type imports /** @@ -10,13 +10,13 @@ import { useEqualityCheck } from './useEqualityCheck' */ export function useMetricEvent(config = {}, overrides = {}) { - const metricsEvent = useContext(MetaMetricsContext) + const metricsEvent = useContext(MetaMetricsContext); const trackEvent = useCallback(() => metricsEvent(config, overrides), [ config, metricsEvent, overrides, - ]) - return trackEvent + ]); + return trackEvent; } /** @@ -28,13 +28,13 @@ export function useMetricEvent(config = {}, overrides = {}) { * @return {() => Promise} function to execute the tracking event */ export function useNewMetricEvent(payload, options) { - const memoizedPayload = useEqualityCheck(payload) - const memoizedOptions = useEqualityCheck(options) - const metricsEvent = useContext(NewMetaMetricsContext) + const memoizedPayload = useEqualityCheck(payload); + const memoizedOptions = useEqualityCheck(options); + const metricsEvent = useContext(NewMetaMetricsContext); return useCallback(() => metricsEvent(memoizedPayload, memoizedOptions), [ metricsEvent, memoizedPayload, memoizedOptions, - ]) + ]); } diff --git a/ui/app/hooks/usePrevious.js b/ui/app/hooks/usePrevious.js index 64ff105f1..8e44b9453 100644 --- a/ui/app/hooks/usePrevious.js +++ b/ui/app/hooks/usePrevious.js @@ -1,9 +1,9 @@ -import { useEffect, useRef } from 'react' +import { useEffect, useRef } from 'react'; export function usePrevious(value) { - const ref = useRef() + const ref = useRef(); useEffect(() => { - ref.current = value - }, [value]) - return ref.current + ref.current = value; + }, [value]); + return ref.current; } diff --git a/ui/app/hooks/useRetryTransaction.js b/ui/app/hooks/useRetryTransaction.js index 63bd6f283..9081ea44d 100644 --- a/ui/app/hooks/useRetryTransaction.js +++ b/ui/app/hooks/useRetryTransaction.js @@ -1,13 +1,13 @@ -import { useDispatch } from 'react-redux' -import { useCallback } from 'react' -import { showSidebar } from '../store/actions' +import { useDispatch } from 'react-redux'; +import { useCallback } from 'react'; +import { showSidebar } from '../store/actions'; import { fetchBasicGasEstimates, setCustomGasPriceForRetry, setCustomGasLimit, -} from '../ducks/gas/gas.duck' -import { increaseLastGasPrice } from '../helpers/utils/confirm-tx.util' -import { useMetricEvent } from './useMetricEvent' +} from '../ducks/gas/gas.duck'; +import { increaseLastGasPrice } from '../helpers/utils/confirm-tx.util'; +import { useMetricEvent } from './useMetricEvent'; /** * Provides a reusable hook that, given a transactionGroup, will return @@ -16,42 +16,42 @@ import { useMetricEvent } from './useMetricEvent' * @return {Function} */ export function useRetryTransaction(transactionGroup) { - const { primaryTransaction, initialTransaction } = transactionGroup + const { primaryTransaction, initialTransaction } = transactionGroup; // Signature requests do not have a txParams, but this hook is called indiscriminately - const gasPrice = primaryTransaction.txParams?.gasPrice + const gasPrice = primaryTransaction.txParams?.gasPrice; const trackMetricsEvent = useMetricEvent({ eventOpts: { category: 'Navigation', action: 'Activity Log', name: 'Clicked "Speed Up"', }, - }) - const dispatch = useDispatch() + }); + const dispatch = useDispatch(); const retryTransaction = useCallback( async (event) => { - event.stopPropagation() + event.stopPropagation(); - trackMetricsEvent() - await dispatch(fetchBasicGasEstimates) - const transaction = initialTransaction - const increasedGasPrice = increaseLastGasPrice(gasPrice) + trackMetricsEvent(); + await dispatch(fetchBasicGasEstimates); + const transaction = initialTransaction; + const increasedGasPrice = increaseLastGasPrice(gasPrice); await dispatch( setCustomGasPriceForRetry( increasedGasPrice || transaction.txParams.gasPrice, ), - ) - dispatch(setCustomGasLimit(transaction.txParams.gas)) + ); + dispatch(setCustomGasLimit(transaction.txParams.gas)); dispatch( showSidebar({ transitionName: 'sidebar-left', type: 'customize-gas', props: { transaction }, }), - ) + ); }, [dispatch, trackMetricsEvent, initialTransaction, gasPrice], - ) + ); - return retryTransaction + return retryTransaction; } diff --git a/ui/app/hooks/useShouldShowSpeedUp.js b/ui/app/hooks/useShouldShowSpeedUp.js index 97c79044f..83c96ca3f 100644 --- a/ui/app/hooks/useShouldShowSpeedUp.js +++ b/ui/app/hooks/useShouldShowSpeedUp.js @@ -1,4 +1,4 @@ -import { useEffect, useState } from 'react' +import { useEffect, useState } from 'react'; /** * Evaluates whether the transaction is eligible to be sped up, and registers @@ -8,12 +8,12 @@ import { useEffect, useState } from 'react' * @param {boolean} isEarliestNonce - Whether this group is currently the earliest nonce */ export function useShouldShowSpeedUp(transactionGroup, isEarliestNonce) { - const { transactions, hasRetried } = transactionGroup - const [earliestTransaction = {}] = transactions - const { submittedTime } = earliestTransaction + const { transactions, hasRetried } = transactionGroup; + const [earliestTransaction = {}] = transactions; + const { submittedTime } = earliestTransaction; const [speedUpEnabled, setSpeedUpEnabled] = useState(() => { - return Date.now() - submittedTime > 5000 && isEarliestNonce && !hasRetried - }) + return Date.now() - submittedTime > 5000 && isEarliestNonce && !hasRetried; + }); useEffect(() => { // because this hook is optimized to only run on changes we have to // key into the changing time delta between submittedTime and now() @@ -22,25 +22,25 @@ export function useShouldShowSpeedUp(transactionGroup, isEarliestNonce) { // also immediately set retryEnabled and not create a timeout if the // condition is already met. This effect will run anytime the variables // for determining enabled status change - let timeoutId + let timeoutId; if (!hasRetried && isEarliestNonce && !speedUpEnabled) { if (Date.now() - submittedTime > 5000) { - setSpeedUpEnabled(true) + setSpeedUpEnabled(true); } else { timeoutId = setTimeout(() => { - setSpeedUpEnabled(true) - clearTimeout(timeoutId) - }, 5001 - (Date.now() - submittedTime)) + setSpeedUpEnabled(true); + clearTimeout(timeoutId); + }, 5001 - (Date.now() - submittedTime)); } } // Anytime the effect is re-ran, make sure to remove a previously set timeout // so as to avoid multiple timers potentially overlapping return () => { if (timeoutId) { - clearTimeout(timeoutId) + clearTimeout(timeoutId); } - } - }, [submittedTime, speedUpEnabled, hasRetried, isEarliestNonce]) + }; + }, [submittedTime, speedUpEnabled, hasRetried, isEarliestNonce]); - return speedUpEnabled + return speedUpEnabled; } diff --git a/ui/app/hooks/useSwappedTokenValue.js b/ui/app/hooks/useSwappedTokenValue.js index 952260c9b..0a5e5bc27 100644 --- a/ui/app/hooks/useSwappedTokenValue.js +++ b/ui/app/hooks/useSwappedTokenValue.js @@ -1,7 +1,7 @@ -import { TRANSACTION_CATEGORIES } from '../../../shared/constants/transaction' -import { ETH_SWAPS_TOKEN_ADDRESS } from '../helpers/constants/swaps' -import { getSwapsTokensReceivedFromTxMeta } from '../pages/swaps/swaps.util' -import { useTokenFiatAmount } from './useTokenFiatAmount' +import { TRANSACTION_CATEGORIES } from '../../../shared/constants/transaction'; +import { ETH_SWAPS_TOKEN_ADDRESS } from '../helpers/constants/swaps'; +import { getSwapsTokensReceivedFromTxMeta } from '../pages/swaps/swaps.util'; +import { useTokenFiatAmount } from './useTokenFiatAmount'; /** * @typedef {Object} SwappedTokenValue @@ -23,15 +23,15 @@ import { useTokenFiatAmount } from './useTokenFiatAmount' * @returns {SwappedTokenValue} */ export function useSwappedTokenValue(transactionGroup, currentAsset) { - const { symbol, decimals, address } = currentAsset - const { primaryTransaction, initialTransaction } = transactionGroup - const { transactionCategory } = initialTransaction - const { from: senderAddress } = initialTransaction.txParams || {} + const { symbol, decimals, address } = currentAsset; + const { primaryTransaction, initialTransaction } = transactionGroup; + const { transactionCategory } = initialTransaction; + const { from: senderAddress } = initialTransaction.txParams || {}; const isViewingReceivedTokenFromSwap = currentAsset?.symbol === primaryTransaction.destinationTokenSymbol || (currentAsset.address === ETH_SWAPS_TOKEN_ADDRESS && - primaryTransaction.destinationTokenSymbol === 'ETH') + primaryTransaction.destinationTokenSymbol === 'ETH'); const swapTokenValue = transactionCategory === TRANSACTION_CATEGORIES.SWAP && @@ -44,24 +44,24 @@ export function useSwappedTokenValue(transactionGroup, currentAsset) { decimals, ) : transactionCategory === TRANSACTION_CATEGORIES.SWAP && - primaryTransaction.swapTokenValue + primaryTransaction.swapTokenValue; const isNegative = typeof swapTokenValue === 'string' ? Math.sign(swapTokenValue) === -1 - : false + : false; const _swapTokenFiatAmount = useTokenFiatAmount( address, swapTokenValue || '', symbol, - ) + ); const swapTokenFiatAmount = - swapTokenValue && isViewingReceivedTokenFromSwap && _swapTokenFiatAmount + swapTokenValue && isViewingReceivedTokenFromSwap && _swapTokenFiatAmount; return { swapTokenValue, swapTokenFiatAmount, isViewingReceivedTokenFromSwap, isNegative, - } + }; } diff --git a/ui/app/hooks/useSwapsEthToken.js b/ui/app/hooks/useSwapsEthToken.js index cd531f6e3..d1707ed88 100644 --- a/ui/app/hooks/useSwapsEthToken.js +++ b/ui/app/hooks/useSwapsEthToken.js @@ -1,10 +1,10 @@ -import { useSelector } from 'react-redux' -import { getSelectedAccount } from '../selectors' -import { ETH_SWAPS_TOKEN_OBJECT } from '../helpers/constants/swaps' +import { useSelector } from 'react-redux'; +import { getSelectedAccount } from '../selectors'; +import { ETH_SWAPS_TOKEN_OBJECT } from '../helpers/constants/swaps'; import { getValueFromWeiHex, hexToDecimal, -} from '../helpers/utils/conversions.util' +} from '../helpers/utils/conversions.util'; /** * @typedef {Object} SwapsEthToken @@ -38,8 +38,8 @@ import { * selected account's ETH balance, as expected by the Swaps API. */ export function useSwapsEthToken() { - const selectedAccount = useSelector(getSelectedAccount) - const { balance } = selectedAccount + const selectedAccount = useSelector(getSelectedAccount); + const { balance } = selectedAccount; return { ...ETH_SWAPS_TOKEN_OBJECT, @@ -49,5 +49,5 @@ export function useSwapsEthToken() { numberOfDecimals: 4, toDenomination: 'ETH', }), - } + }; } diff --git a/ui/app/hooks/useTimeout.js b/ui/app/hooks/useTimeout.js index dc0a71434..d3b208896 100644 --- a/ui/app/hooks/useTimeout.js +++ b/ui/app/hooks/useTimeout.js @@ -1,4 +1,4 @@ -import { useState, useEffect, useRef, useCallback } from 'react' +import { useState, useEffect, useRef, useCallback } from 'react'; /** * useTimeout @@ -10,37 +10,37 @@ import { useState, useEffect, useRef, useCallback } from 'react' * @return {Function|undefined} */ export function useTimeout(cb, delay, immediate = true) { - const saveCb = useRef() - const [timeoutId, setTimeoutId] = useState(null) + const saveCb = useRef(); + const [timeoutId, setTimeoutId] = useState(null); useEffect(() => { - saveCb.current = cb - }, [cb]) + saveCb.current = cb; + }, [cb]); useEffect(() => { if (timeoutId !== 'start') { - return undefined + return undefined; } const id = setTimeout(() => { - saveCb.current() - }, delay) + saveCb.current(); + }, delay); - setTimeoutId(id) + setTimeoutId(id); return () => { - clearTimeout(timeoutId) - } - }, [delay, timeoutId]) + clearTimeout(timeoutId); + }; + }, [delay, timeoutId]); const startTimeout = useCallback(() => { - clearTimeout(timeoutId) - setTimeoutId('start') - }, [timeoutId]) + clearTimeout(timeoutId); + setTimeoutId('start'); + }, [timeoutId]); if (immediate) { - startTimeout() + startTimeout(); } - return startTimeout + return startTimeout; } diff --git a/ui/app/hooks/useTokenData.js b/ui/app/hooks/useTokenData.js index c9602f084..6a93f3512 100644 --- a/ui/app/hooks/useTokenData.js +++ b/ui/app/hooks/useTokenData.js @@ -1,5 +1,5 @@ -import { useMemo } from 'react' -import { getTokenData } from '../helpers/utils/transactions.util' +import { useMemo } from 'react'; +import { getTokenData } from '../helpers/utils/transactions.util'; /** * useTokenData @@ -16,8 +16,8 @@ import { getTokenData } from '../helpers/utils/transactions.util' export function useTokenData(transactionData, isTokenTransaction = true) { return useMemo(() => { if (!isTokenTransaction || !transactionData) { - return null + return null; } - return getTokenData(transactionData) - }, [isTokenTransaction, transactionData]) + return getTokenData(transactionData); + }, [isTokenTransaction, transactionData]); } diff --git a/ui/app/hooks/useTokenDisplayValue.js b/ui/app/hooks/useTokenDisplayValue.js index 331b53dfb..40c3b1de6 100644 --- a/ui/app/hooks/useTokenDisplayValue.js +++ b/ui/app/hooks/useTokenDisplayValue.js @@ -1,9 +1,9 @@ -import { useMemo } from 'react' +import { useMemo } from 'react'; import { getTokenValueParam, calcTokenAmount, -} from '../helpers/utils/token-util' -import { useTokenData } from './useTokenData' +} from '../helpers/utils/token-util'; +import { useTokenData } from './useTokenData'; /** * Defines the shape for the Token input parameter for useTokenDisplayValue @@ -32,7 +32,7 @@ export function useTokenDisplayValue( token, isTokenTransaction = true, ) { - const tokenData = useTokenData(transactionData, isTokenTransaction) + const tokenData = useTokenData(transactionData, isTokenTransaction); const shouldCalculateTokenValue = Boolean( // If we are currently processing a token transaction isTokenTransaction && @@ -42,15 +42,15 @@ export function useTokenDisplayValue( token && // and we are able to parse the token details from the raw data tokenData?.args?.length, - ) + ); const displayValue = useMemo(() => { if (!shouldCalculateTokenValue) { - return null + return null; } - const tokenValue = getTokenValueParam(tokenData) - return calcTokenAmount(tokenValue, token.decimals).toString(10) - }, [shouldCalculateTokenValue, tokenData, token]) + const tokenValue = getTokenValueParam(tokenData); + return calcTokenAmount(tokenValue, token.decimals).toString(10); + }, [shouldCalculateTokenValue, tokenData, token]); - return displayValue + return displayValue; } diff --git a/ui/app/hooks/useTokenFiatAmount.js b/ui/app/hooks/useTokenFiatAmount.js index 6f393c861..835b65936 100644 --- a/ui/app/hooks/useTokenFiatAmount.js +++ b/ui/app/hooks/useTokenFiatAmount.js @@ -1,12 +1,12 @@ -import { useMemo } from 'react' -import { useSelector } from 'react-redux' +import { useMemo } from 'react'; +import { useSelector } from 'react-redux'; import { getTokenExchangeRates, getConversionRate, getCurrentCurrency, getShouldShowFiat, -} from '../selectors' -import { getTokenFiatAmount } from '../helpers/utils/token-util' +} from '../selectors'; +import { getTokenFiatAmount } from '../helpers/utils/token-util'; /** * Get the token balance converted to fiat and formatted for display @@ -28,13 +28,13 @@ export function useTokenFiatAmount( overrides = {}, hideCurrencySymbol, ) { - const contractExchangeRates = useSelector(getTokenExchangeRates) - const conversionRate = useSelector(getConversionRate) - const currentCurrency = useSelector(getCurrentCurrency) - const userPrefersShownFiat = useSelector(getShouldShowFiat) - const showFiat = overrides.showFiat ?? userPrefersShownFiat + const contractExchangeRates = useSelector(getTokenExchangeRates); + const conversionRate = useSelector(getConversionRate); + const currentCurrency = useSelector(getCurrentCurrency); + const userPrefersShownFiat = useSelector(getShouldShowFiat); + const showFiat = overrides.showFiat ?? userPrefersShownFiat; const tokenExchangeRate = - overrides.exchangeRate ?? contractExchangeRates[tokenAddress] + overrides.exchangeRate ?? contractExchangeRates[tokenAddress]; const formattedFiat = useMemo( () => getTokenFiatAmount( @@ -54,11 +54,11 @@ export function useTokenFiatAmount( tokenSymbol, hideCurrencySymbol, ], - ) + ); if (!showFiat || currentCurrency.toUpperCase() === tokenSymbol) { - return undefined + return undefined; } - return formattedFiat + return formattedFiat; } diff --git a/ui/app/hooks/useTokenTracker.js b/ui/app/hooks/useTokenTracker.js index f94b0544f..ea7892b08 100644 --- a/ui/app/hooks/useTokenTracker.js +++ b/ui/app/hooks/useTokenTracker.js @@ -1,57 +1,57 @@ -import { useState, useEffect, useRef, useCallback } from 'react' -import TokenTracker from '@metamask/eth-token-tracker' -import { useSelector } from 'react-redux' -import { getCurrentNetwork, getSelectedAddress } from '../selectors' -import { useEqualityCheck } from './useEqualityCheck' +import { useState, useEffect, useRef, useCallback } from 'react'; +import TokenTracker from '@metamask/eth-token-tracker'; +import { useSelector } from 'react-redux'; +import { getCurrentNetwork, getSelectedAddress } from '../selectors'; +import { useEqualityCheck } from './useEqualityCheck'; export function useTokenTracker(tokens, includeFailedTokens = false) { - const network = useSelector(getCurrentNetwork) - const userAddress = useSelector(getSelectedAddress) + const network = useSelector(getCurrentNetwork); + const userAddress = useSelector(getSelectedAddress); - const [loading, setLoading] = useState(() => tokens?.length >= 0) - const [tokensWithBalances, setTokensWithBalances] = useState([]) - const [error, setError] = useState(null) - const tokenTracker = useRef(null) - const memoizedTokens = useEqualityCheck(tokens) + const [loading, setLoading] = useState(() => tokens?.length >= 0); + const [tokensWithBalances, setTokensWithBalances] = useState([]); + const [error, setError] = useState(null); + const tokenTracker = useRef(null); + const memoizedTokens = useEqualityCheck(tokens); const updateBalances = useCallback((tokenWithBalances) => { - setTokensWithBalances(tokenWithBalances) - setLoading(false) - setError(null) - }, []) + setTokensWithBalances(tokenWithBalances); + setLoading(false); + setError(null); + }, []); const showError = useCallback((err) => { - setError(err) - setLoading(false) - }, []) + setError(err); + setLoading(false); + }, []); const teardownTracker = useCallback(() => { if (tokenTracker.current) { - tokenTracker.current.stop() - tokenTracker.current.removeAllListeners('update') - tokenTracker.current.removeAllListeners('error') - tokenTracker.current = null + tokenTracker.current.stop(); + tokenTracker.current.removeAllListeners('update'); + tokenTracker.current.removeAllListeners('error'); + tokenTracker.current = null; } - }, []) + }, []); const buildTracker = useCallback( (address, tokenList) => { // clear out previous tracker, if it exists. - teardownTracker() + teardownTracker(); tokenTracker.current = new TokenTracker({ userAddress: address, provider: global.ethereumProvider, tokens: tokenList, includeFailedTokens, pollingInterval: 8000, - }) + }); - tokenTracker.current.on('update', updateBalances) - tokenTracker.current.on('error', showError) - tokenTracker.current.updateBalances() + tokenTracker.current.on('update', updateBalances); + tokenTracker.current.on('error', showError); + tokenTracker.current.updateBalances(); }, [updateBalances, includeFailedTokens, showError, teardownTracker], - ) + ); // Effect to remove the tracker when the component is removed from DOM // Do not overload this effect with additional dependencies. teardownTracker @@ -59,8 +59,8 @@ export function useTokenTracker(tokens, includeFailedTokens = false) { // never update. The lack of dependencies that change is what confirms // that this effect only runs on mount/unmount useEffect(() => { - return teardownTracker - }, [teardownTracker]) + return teardownTracker; + }, [teardownTracker]); // Effect to set loading state and initialize tracker when values change useEffect(() => { @@ -70,22 +70,22 @@ export function useTokenTracker(tokens, includeFailedTokens = false) { // 3. token list is updated and not equal to previous list // in any of these scenarios, we should indicate to the user that their token // values are in the process of updating by setting loading state. - setLoading(true) + setLoading(true); if (!userAddress || network === 'loading' || !global.ethereumProvider) { // If we do not have enough information to build a TokenTracker, we exit early // When the values above change, the effect will be restarted. We also teardown // tracker because inevitably this effect will run again momentarily. - teardownTracker() - return + teardownTracker(); + return; } if (memoizedTokens.length === 0) { // sets loading state to false and token list to empty - updateBalances([]) + updateBalances([]); } - buildTracker(userAddress, memoizedTokens) + buildTracker(userAddress, memoizedTokens); }, [ userAddress, teardownTracker, @@ -93,7 +93,7 @@ export function useTokenTracker(tokens, includeFailedTokens = false) { memoizedTokens, updateBalances, buildTracker, - ]) + ]); - return { loading, tokensWithBalances, error } + return { loading, tokensWithBalances, error }; } diff --git a/ui/app/hooks/useTokensToSearch.js b/ui/app/hooks/useTokensToSearch.js index a4e0e94f4..cbaf4df66 100644 --- a/ui/app/hooks/useTokensToSearch.js +++ b/ui/app/hooks/useTokensToSearch.js @@ -1,18 +1,18 @@ -import { useMemo } from 'react' -import { useSelector } from 'react-redux' -import contractMap from '@metamask/contract-metadata' -import BigNumber from 'bignumber.js' -import { isEqual, shuffle } from 'lodash' -import { checksumAddress } from '../helpers/utils/util' -import { getTokenFiatAmount } from '../helpers/utils/token-util' +import { useMemo } from 'react'; +import { useSelector } from 'react-redux'; +import contractMap from '@metamask/contract-metadata'; +import BigNumber from 'bignumber.js'; +import { isEqual, shuffle } from 'lodash'; +import { checksumAddress } from '../helpers/utils/util'; +import { getTokenFiatAmount } from '../helpers/utils/token-util'; import { getTokenExchangeRates, getConversionRate, getCurrentCurrency, -} from '../selectors' -import { getSwapsTokens } from '../ducks/swaps/swaps' -import { useSwapsEthToken } from './useSwapsEthToken' -import { useEqualityCheck } from './useEqualityCheck' +} from '../selectors'; +import { getSwapsTokens } from '../ducks/swaps/swaps'; +import { useSwapsEthToken } from './useSwapsEthToken'; +import { useEqualityCheck } from './useEqualityCheck'; const tokenList = shuffle( Object.entries(contractMap) @@ -21,7 +21,7 @@ const tokenList = shuffle( address: address.toLowerCase(), })) .filter((tokenData) => Boolean(tokenData.erc20)), -) +); export function getRenderableTokenData( token, @@ -29,7 +29,7 @@ export function getRenderableTokenData( conversionRate, currentCurrency, ) { - const { symbol, name, address, iconUrl, string, balance, decimals } = token + const { symbol, name, address, iconUrl, string, balance, decimals } = token; const formattedFiat = getTokenFiatAmount( @@ -39,7 +39,7 @@ export function getRenderableTokenData( string, symbol, true, - ) || '' + ) || ''; const rawFiat = getTokenFiatAmount( symbol === 'ETH' ? 1 : contractExchangeRates[address], @@ -48,11 +48,11 @@ export function getRenderableTokenData( string, symbol, false, - ) || '' + ) || ''; const usedIconUrl = iconUrl || (contractMap[checksumAddress(address)] && - `images/contract/${contractMap[checksumAddress(address)].logo}`) + `images/contract/${contractMap[checksumAddress(address)].logo}`); return { ...token, primaryLabel: symbol, @@ -66,7 +66,7 @@ export function getRenderableTokenData( decimals, name: name || contractMap[checksumAddress(address)]?.name, rawFiat, - } + }; } export function useTokensToSearch({ @@ -76,47 +76,47 @@ export function useTokensToSearch({ onlyEth, singleToken, }) { - const tokenConversionRates = useSelector(getTokenExchangeRates, isEqual) - const conversionRate = useSelector(getConversionRate) - const currentCurrency = useSelector(getCurrentCurrency) + const tokenConversionRates = useSelector(getTokenExchangeRates, isEqual); + const conversionRate = useSelector(getConversionRate); + const currentCurrency = useSelector(getCurrentCurrency); - const memoizedTopTokens = useEqualityCheck(topTokens) - const memoizedUsersToken = useEqualityCheck(usersTokens) + const memoizedTopTokens = useEqualityCheck(topTokens); + const memoizedUsersToken = useEqualityCheck(usersTokens); - const swapsEthToken = useSwapsEthToken() + const swapsEthToken = useSwapsEthToken(); const ethToken = getRenderableTokenData( swapsEthToken, tokenConversionRates, conversionRate, currentCurrency, - ) - const memoizedEthToken = useEqualityCheck(ethToken) + ); + const memoizedEthToken = useEqualityCheck(ethToken); - const swapsTokens = useSelector(getSwapsTokens) || [] - let tokensToSearch + const swapsTokens = useSelector(getSwapsTokens) || []; + let tokensToSearch; if (onlyEth) { - tokensToSearch = [memoizedEthToken] + tokensToSearch = [memoizedEthToken]; } else if (singleToken) { - tokensToSearch = providedTokens + tokensToSearch = providedTokens; } else if (providedTokens) { - tokensToSearch = [memoizedEthToken, ...providedTokens] + tokensToSearch = [memoizedEthToken, ...providedTokens]; } else if (swapsTokens.length) { - tokensToSearch = [memoizedEthToken, ...swapsTokens] + tokensToSearch = [memoizedEthToken, ...swapsTokens]; } else { - tokensToSearch = [memoizedEthToken, ...tokenList] + tokensToSearch = [memoizedEthToken, ...tokenList]; } - const memoizedTokensToSearch = useEqualityCheck(tokensToSearch) + const memoizedTokensToSearch = useEqualityCheck(tokensToSearch); return useMemo(() => { const usersTokensAddressMap = memoizedUsersToken.reduce( (acc, token) => ({ ...acc, [token.address]: token }), {}, - ) + ); const tokensToSearchBuckets = { owned: singleToken ? [] : [memoizedEthToken], top: [], others: [], - } + }; memoizedTokensToSearch.forEach((token) => { const renderableDataToken = getRenderableTokenData( @@ -124,33 +124,33 @@ export function useTokensToSearch({ tokenConversionRates, conversionRate, currentCurrency, - ) + ); if ( usersTokensAddressMap[token.address] && (renderableDataToken.symbol === 'ETH' || Number(renderableDataToken.balance ?? 0) !== 0) ) { - tokensToSearchBuckets.owned.push(renderableDataToken) + tokensToSearchBuckets.owned.push(renderableDataToken); } else if (memoizedTopTokens[token.address]) { tokensToSearchBuckets.top[ memoizedTopTokens[token.address].index - ] = renderableDataToken + ] = renderableDataToken; } else { - tokensToSearchBuckets.others.push(renderableDataToken) + tokensToSearchBuckets.others.push(renderableDataToken); } - }) + }); tokensToSearchBuckets.owned = tokensToSearchBuckets.owned.sort( ({ rawFiat }, { rawFiat: secondRawFiat }) => { - return new BigNumber(rawFiat || 0).gt(secondRawFiat || 0) ? -1 : 1 + return new BigNumber(rawFiat || 0).gt(secondRawFiat || 0) ? -1 : 1; }, - ) - tokensToSearchBuckets.top = tokensToSearchBuckets.top.filter(Boolean) + ); + tokensToSearchBuckets.top = tokensToSearchBuckets.top.filter(Boolean); return [ ...tokensToSearchBuckets.owned, ...tokensToSearchBuckets.top, ...tokensToSearchBuckets.others, - ] + ]; }, [ memoizedTokensToSearch, memoizedUsersToken, @@ -160,5 +160,5 @@ export function useTokensToSearch({ memoizedTopTokens, memoizedEthToken, singleToken, - ]) + ]); } diff --git a/ui/app/hooks/useTransactionDisplayData.js b/ui/app/hooks/useTransactionDisplayData.js index 2fe8ae691..ff0b7b6c9 100644 --- a/ui/app/hooks/useTransactionDisplayData.js +++ b/ui/app/hooks/useTransactionDisplayData.js @@ -1,32 +1,32 @@ -import { useSelector } from 'react-redux' -import { getKnownMethodData } from '../selectors/selectors' -import { getStatusKey } from '../helpers/utils/transactions.util' -import { camelCaseToCapitalize } from '../helpers/utils/common.util' -import { PRIMARY, SECONDARY } from '../helpers/constants/common' -import { getTokenAddressParam } from '../helpers/utils/token-util' +import { useSelector } from 'react-redux'; +import { getKnownMethodData } from '../selectors/selectors'; +import { getStatusKey } from '../helpers/utils/transactions.util'; +import { camelCaseToCapitalize } from '../helpers/utils/common.util'; +import { PRIMARY, SECONDARY } from '../helpers/constants/common'; +import { getTokenAddressParam } from '../helpers/utils/token-util'; import { formatDateWithYearContext, shortenAddress, stripHttpSchemes, -} from '../helpers/utils/util' +} from '../helpers/utils/util'; import { PENDING_STATUS_HASH, TOKEN_CATEGORY_HASH, -} from '../helpers/constants/transactions' -import { getTokens } from '../ducks/metamask/metamask' +} from '../helpers/constants/transactions'; +import { getTokens } from '../ducks/metamask/metamask'; import { TRANSACTION_CATEGORIES, TRANSACTION_GROUP_CATEGORIES, TRANSACTION_STATUSES, -} from '../../../shared/constants/transaction' -import { useI18nContext } from './useI18nContext' -import { useTokenFiatAmount } from './useTokenFiatAmount' -import { useUserPreferencedCurrency } from './useUserPreferencedCurrency' -import { useCurrencyDisplay } from './useCurrencyDisplay' -import { useTokenDisplayValue } from './useTokenDisplayValue' -import { useTokenData } from './useTokenData' -import { useSwappedTokenValue } from './useSwappedTokenValue' -import { useCurrentAsset } from './useCurrentAsset' +} from '../../../shared/constants/transaction'; +import { useI18nContext } from './useI18nContext'; +import { useTokenFiatAmount } from './useTokenFiatAmount'; +import { useUserPreferencedCurrency } from './useUserPreferencedCurrency'; +import { useCurrencyDisplay } from './useCurrencyDisplay'; +import { useTokenDisplayValue } from './useTokenDisplayValue'; +import { useTokenData } from './useTokenData'; +import { useSwappedTokenValue } from './useSwappedTokenValue'; +import { useCurrentAsset } from './useCurrentAsset'; /** * @typedef {Object} TransactionDisplayData @@ -54,35 +54,35 @@ import { useCurrentAsset } from './useCurrentAsset' export function useTransactionDisplayData(transactionGroup) { // To determine which primary currency to display for swaps transactions we need to be aware // of which asset, if any, we are viewing at present - const currentAsset = useCurrentAsset() - const knownTokens = useSelector(getTokens) - const t = useI18nContext() - const { initialTransaction, primaryTransaction } = transactionGroup + const currentAsset = useCurrentAsset(); + const knownTokens = useSelector(getTokens); + const t = useI18nContext(); + const { initialTransaction, primaryTransaction } = transactionGroup; // initialTransaction contains the data we need to derive the primary purpose of this transaction group - const { transactionCategory } = initialTransaction + const { transactionCategory } = initialTransaction; - const { from: senderAddress, to } = initialTransaction.txParams || {} + const { from: senderAddress, to } = initialTransaction.txParams || {}; // for smart contract interactions, methodData can be used to derive the name of the action being taken const methodData = useSelector((state) => getKnownMethodData(state, initialTransaction?.txParams?.data), - ) || {} + ) || {}; - const displayedStatusKey = getStatusKey(primaryTransaction) - const isPending = displayedStatusKey in PENDING_STATUS_HASH - const isSubmitted = displayedStatusKey === TRANSACTION_STATUSES.SUBMITTED + const displayedStatusKey = getStatusKey(primaryTransaction); + const isPending = displayedStatusKey in PENDING_STATUS_HASH; + const isSubmitted = displayedStatusKey === TRANSACTION_STATUSES.SUBMITTED; - const primaryValue = primaryTransaction.txParams?.value - let prefix = '-' - const date = formatDateWithYearContext(initialTransaction.time || 0) - let subtitle - let subtitleContainsOrigin = false - let recipientAddress = to + const primaryValue = primaryTransaction.txParams?.value; + let prefix = '-'; + const date = formatDateWithYearContext(initialTransaction.time || 0); + let subtitle; + let subtitleContainsOrigin = false; + let recipientAddress = to; // This value is used to determine whether we should look inside txParams.data // to pull out and render token related information - const isTokenCategory = TOKEN_CATEGORY_HASH[transactionCategory] + const isTokenCategory = TOKEN_CATEGORY_HASH[transactionCategory]; // these values are always instantiated because they are either // used by or returned from hooks. Hooks must be called at the top level, @@ -92,46 +92,46 @@ export function useTransactionDisplayData(transactionGroup) { // hook to return null const token = isTokenCategory && - knownTokens.find(({ address }) => address === recipientAddress) + knownTokens.find(({ address }) => address === recipientAddress); const tokenData = useTokenData( initialTransaction?.txParams?.data, isTokenCategory, - ) + ); const tokenDisplayValue = useTokenDisplayValue( initialTransaction?.txParams?.data, token, isTokenCategory, - ) + ); const tokenFiatAmount = useTokenFiatAmount( token?.address, tokenDisplayValue, token?.symbol, - ) + ); const origin = stripHttpSchemes( initialTransaction.origin || initialTransaction.msgParams?.origin || '', - ) + ); // used to append to the primary display value. initialized to either token.symbol or undefined // but can later be modified if dealing with a swap - let primarySuffix = isTokenCategory ? token?.symbol : undefined + let primarySuffix = isTokenCategory ? token?.symbol : undefined; // used to display the primary value of tx. initialized to either tokenDisplayValue or undefined // but can later be modified if dealing with a swap - let primaryDisplayValue = isTokenCategory ? tokenDisplayValue : undefined + let primaryDisplayValue = isTokenCategory ? tokenDisplayValue : undefined; // used to display fiat amount of tx. initialized to either tokenFiatAmount or undefined // but can later be modified if dealing with a swap - let secondaryDisplayValue = isTokenCategory ? tokenFiatAmount : undefined + let secondaryDisplayValue = isTokenCategory ? tokenFiatAmount : undefined; // The transaction group category that will be used for rendering the icon in the activity list - let category + let category; // The primary title of the Tx that will be displayed in the activity list - let title + let title; const { swapTokenValue, isNegative, swapTokenFiatAmount, isViewingReceivedTokenFromSwap, - } = useSwappedTokenValue(transactionGroup, currentAsset) + } = useSwappedTokenValue(transactionGroup, currentAsset); // There are seven types of transaction entries that are currently differentiated in the design // 1. Signature request @@ -143,89 +143,89 @@ export function useTransactionDisplayData(transactionGroup) { // 7. Swap Approval if (transactionCategory === null || transactionCategory === undefined) { - category = TRANSACTION_GROUP_CATEGORIES.SIGNATURE_REQUEST - title = t('signatureRequest') - subtitle = origin - subtitleContainsOrigin = true + category = TRANSACTION_GROUP_CATEGORIES.SIGNATURE_REQUEST; + title = t('signatureRequest'); + subtitle = origin; + subtitleContainsOrigin = true; } else if (transactionCategory === TRANSACTION_CATEGORIES.SWAP) { - category = TRANSACTION_GROUP_CATEGORIES.SWAP + category = TRANSACTION_GROUP_CATEGORIES.SWAP; title = t('swapTokenToToken', [ initialTransaction.sourceTokenSymbol, initialTransaction.destinationTokenSymbol, - ]) - subtitle = origin - subtitleContainsOrigin = true + ]); + subtitle = origin; + subtitleContainsOrigin = true; primarySuffix = isViewingReceivedTokenFromSwap ? currentAsset.symbol - : initialTransaction.sourceTokenSymbol - primaryDisplayValue = swapTokenValue - secondaryDisplayValue = swapTokenFiatAmount + : initialTransaction.sourceTokenSymbol; + primaryDisplayValue = swapTokenValue; + secondaryDisplayValue = swapTokenFiatAmount; if (isNegative) { - prefix = '' + prefix = ''; } else if (isViewingReceivedTokenFromSwap) { - prefix = '+' + prefix = '+'; } else { - prefix = '-' + prefix = '-'; } } else if (transactionCategory === TRANSACTION_CATEGORIES.SWAP_APPROVAL) { - category = TRANSACTION_GROUP_CATEGORIES.APPROVAL - title = t('swapApproval', [primaryTransaction.sourceTokenSymbol]) - subtitle = origin - subtitleContainsOrigin = true - primarySuffix = primaryTransaction.sourceTokenSymbol + category = TRANSACTION_GROUP_CATEGORIES.APPROVAL; + title = t('swapApproval', [primaryTransaction.sourceTokenSymbol]); + subtitle = origin; + subtitleContainsOrigin = true; + primarySuffix = primaryTransaction.sourceTokenSymbol; } else if ( transactionCategory === TRANSACTION_CATEGORIES.TOKEN_METHOD_APPROVE ) { - category = TRANSACTION_GROUP_CATEGORIES.APPROVAL - prefix = '' - title = t('approveSpendLimit', [token?.symbol || t('token')]) - subtitle = origin - subtitleContainsOrigin = true + category = TRANSACTION_GROUP_CATEGORIES.APPROVAL; + prefix = ''; + title = t('approveSpendLimit', [token?.symbol || t('token')]); + subtitle = origin; + subtitleContainsOrigin = true; } else if ( transactionCategory === TRANSACTION_CATEGORIES.DEPLOY_CONTRACT || transactionCategory === TRANSACTION_CATEGORIES.CONTRACT_INTERACTION ) { - category = TRANSACTION_GROUP_CATEGORIES.INTERACTION + category = TRANSACTION_GROUP_CATEGORIES.INTERACTION; title = (methodData?.name && camelCaseToCapitalize(methodData.name)) || - t(transactionCategory) - subtitle = origin - subtitleContainsOrigin = true + t(transactionCategory); + subtitle = origin; + subtitleContainsOrigin = true; } else if (transactionCategory === TRANSACTION_CATEGORIES.INCOMING) { - category = TRANSACTION_GROUP_CATEGORIES.RECEIVE - title = t('receive') - prefix = '' - subtitle = t('fromAddress', [shortenAddress(senderAddress)]) + category = TRANSACTION_GROUP_CATEGORIES.RECEIVE; + title = t('receive'); + prefix = ''; + subtitle = t('fromAddress', [shortenAddress(senderAddress)]); } else if ( transactionCategory === TRANSACTION_CATEGORIES.TOKEN_METHOD_TRANSFER_FROM || transactionCategory === TRANSACTION_CATEGORIES.TOKEN_METHOD_TRANSFER ) { - category = TRANSACTION_GROUP_CATEGORIES.SEND - title = t('sendSpecifiedTokens', [token?.symbol || t('token')]) - recipientAddress = getTokenAddressParam(tokenData) - subtitle = t('toAddress', [shortenAddress(recipientAddress)]) + category = TRANSACTION_GROUP_CATEGORIES.SEND; + title = t('sendSpecifiedTokens', [token?.symbol || t('token')]); + recipientAddress = getTokenAddressParam(tokenData); + subtitle = t('toAddress', [shortenAddress(recipientAddress)]); } else if (transactionCategory === TRANSACTION_CATEGORIES.SENT_ETHER) { - category = TRANSACTION_GROUP_CATEGORIES.SEND - title = t('sendETH') - subtitle = t('toAddress', [shortenAddress(recipientAddress)]) + category = TRANSACTION_GROUP_CATEGORIES.SEND; + title = t('sendETH'); + subtitle = t('toAddress', [shortenAddress(recipientAddress)]); } - const primaryCurrencyPreferences = useUserPreferencedCurrency(PRIMARY) - const secondaryCurrencyPreferences = useUserPreferencedCurrency(SECONDARY) + const primaryCurrencyPreferences = useUserPreferencedCurrency(PRIMARY); + const secondaryCurrencyPreferences = useUserPreferencedCurrency(SECONDARY); const [primaryCurrency] = useCurrencyDisplay(primaryValue, { prefix, displayValue: primaryDisplayValue, suffix: primarySuffix, ...primaryCurrencyPreferences, - }) + }); const [secondaryCurrency] = useCurrencyDisplay(primaryValue, { prefix, displayValue: secondaryDisplayValue, hideLabel: isTokenCategory || Boolean(swapTokenValue), ...secondaryCurrencyPreferences, - }) + }); return { title, @@ -248,5 +248,5 @@ export function useTransactionDisplayData(transactionGroup) { displayedStatusKey, isPending, isSubmitted, - } + }; } diff --git a/ui/app/hooks/useUserPreferencedCurrency.js b/ui/app/hooks/useUserPreferencedCurrency.js index 1764fa24e..d1a080954 100644 --- a/ui/app/hooks/useUserPreferencedCurrency.js +++ b/ui/app/hooks/useUserPreferencedCurrency.js @@ -1,10 +1,10 @@ -import { useSelector } from 'react-redux' +import { useSelector } from 'react-redux'; import { getPreferences, getShouldShowFiat, getNativeCurrency, -} from '../selectors' -import { PRIMARY, SECONDARY, ETH } from '../helpers/constants/common' +} from '../selectors'; +import { PRIMARY, SECONDARY, ETH } from '../helpers/constants/common'; /** * Defines the shape of the options parameter for useUserPreferencedCurrency @@ -34,26 +34,26 @@ import { PRIMARY, SECONDARY, ETH } from '../helpers/constants/common' * @return {UserPreferredCurrency} */ export function useUserPreferencedCurrency(type, opts = {}) { - const nativeCurrency = useSelector(getNativeCurrency) - const { useNativeCurrencyAsPrimaryCurrency } = useSelector(getPreferences) - const showFiat = useSelector(getShouldShowFiat) + const nativeCurrency = useSelector(getNativeCurrency); + const { useNativeCurrencyAsPrimaryCurrency } = useSelector(getPreferences); + const showFiat = useSelector(getShouldShowFiat); - let currency, numberOfDecimals + let currency, numberOfDecimals; if ( !showFiat || (type === PRIMARY && useNativeCurrencyAsPrimaryCurrency) || (type === SECONDARY && !useNativeCurrencyAsPrimaryCurrency) ) { // Display ETH - currency = nativeCurrency || ETH - numberOfDecimals = opts.numberOfDecimals || opts.ethNumberOfDecimals || 6 + currency = nativeCurrency || ETH; + numberOfDecimals = opts.numberOfDecimals || opts.ethNumberOfDecimals || 6; } else if ( (type === SECONDARY && useNativeCurrencyAsPrimaryCurrency) || (type === PRIMARY && !useNativeCurrencyAsPrimaryCurrency) ) { // Display Fiat - numberOfDecimals = opts.numberOfDecimals || opts.fiatNumberOfDecimals || 2 + numberOfDecimals = opts.numberOfDecimals || opts.fiatNumberOfDecimals || 2; } - return { currency, numberOfDecimals } + return { currency, numberOfDecimals }; } diff --git a/ui/app/pages/add-token/add-token.component.js b/ui/app/pages/add-token/add-token.component.js index 20d673f73..40f4a3675 100644 --- a/ui/app/pages/add-token/add-token.component.js +++ b/ui/app/pages/add-token/add-token.component.js @@ -1,22 +1,22 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import ethUtil from 'ethereumjs-util' -import { checkExistingAddresses } from '../../helpers/utils/util' -import { tokenInfoGetter } from '../../helpers/utils/token-util' -import { CONFIRM_ADD_TOKEN_ROUTE } from '../../helpers/constants/routes' -import TextField from '../../components/ui/text-field' -import PageContainer from '../../components/ui/page-container' -import { Tabs, Tab } from '../../components/ui/tabs' -import { addHexPrefix } from '../../../../app/scripts/lib/util' -import TokenList from './token-list' -import TokenSearch from './token-search' +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import ethUtil from 'ethereumjs-util'; +import { checkExistingAddresses } from '../../helpers/utils/util'; +import { tokenInfoGetter } from '../../helpers/utils/token-util'; +import { CONFIRM_ADD_TOKEN_ROUTE } from '../../helpers/constants/routes'; +import TextField from '../../components/ui/text-field'; +import PageContainer from '../../components/ui/page-container'; +import { Tabs, Tab } from '../../components/ui/tabs'; +import { addHexPrefix } from '../../../../app/scripts/lib/util'; +import TokenList from './token-list'; +import TokenSearch from './token-search'; -const emptyAddr = '0x0000000000000000000000000000000000000000' +const emptyAddr = '0x0000000000000000000000000000000000000000'; class AddToken extends Component { static contextTypes = { t: PropTypes.func, - } + }; static propTypes = { history: PropTypes.object, @@ -26,7 +26,7 @@ class AddToken extends Component { tokens: PropTypes.array, identities: PropTypes.object, mostRecentOverviewPage: PropTypes.string.isRequired, - } + }; state = { customAddress: '', @@ -40,58 +40,58 @@ class AddToken extends Component { customDecimalsError: null, autoFilled: false, forceEditSymbol: false, - } + }; componentDidMount() { - this.tokenInfoGetter = tokenInfoGetter() - const { pendingTokens = {} } = this.props - const pendingTokenKeys = Object.keys(pendingTokens) + this.tokenInfoGetter = tokenInfoGetter(); + const { pendingTokens = {} } = this.props; + const pendingTokenKeys = Object.keys(pendingTokens); if (pendingTokenKeys.length > 0) { - let selectedTokens = {} - let customToken = {} + let selectedTokens = {}; + let customToken = {}; pendingTokenKeys.forEach((tokenAddress) => { - const token = pendingTokens[tokenAddress] - const { isCustom } = token + const token = pendingTokens[tokenAddress]; + const { isCustom } = token; if (isCustom) { - customToken = { ...token } + customToken = { ...token }; } else { - selectedTokens = { ...selectedTokens, [tokenAddress]: { ...token } } + selectedTokens = { ...selectedTokens, [tokenAddress]: { ...token } }; } - }) + }); const { address: customAddress = '', symbol: customSymbol = '', decimals: customDecimals = 0, - } = customToken + } = customToken; this.setState({ selectedTokens, customAddress, customSymbol, customDecimals, - }) + }); } } handleToggleToken(token) { - const { address } = token - const { selectedTokens = {} } = this.state - const selectedTokensCopy = { ...selectedTokens } + const { address } = token; + const { selectedTokens = {} } = this.state; + const selectedTokensCopy = { ...selectedTokens }; if (address in selectedTokensCopy) { - delete selectedTokensCopy[address] + delete selectedTokensCopy[address]; } else { - selectedTokensCopy[address] = token + selectedTokensCopy[address] = token; } this.setState({ selectedTokens: selectedTokensCopy, tokenSelectorError: null, - }) + }); } hasError() { @@ -100,69 +100,69 @@ class AddToken extends Component { customAddressError, customSymbolError, customDecimalsError, - } = this.state + } = this.state; return ( tokenSelectorError || customAddressError || customSymbolError || customDecimalsError - ) + ); } hasSelected() { - const { customAddress = '', selectedTokens = {} } = this.state - return customAddress || Object.keys(selectedTokens).length > 0 + const { customAddress = '', selectedTokens = {} } = this.state; + return customAddress || Object.keys(selectedTokens).length > 0; } handleNext() { if (this.hasError()) { - return + return; } if (!this.hasSelected()) { - this.setState({ tokenSelectorError: this.context.t('mustSelectOne') }) - return + this.setState({ tokenSelectorError: this.context.t('mustSelectOne') }); + return; } - const { setPendingTokens, history } = this.props + const { setPendingTokens, history } = this.props; const { customAddress: address, customSymbol: symbol, customDecimals: decimals, selectedTokens, - } = this.state + } = this.state; const customToken = { address, symbol, decimals, - } + }; - setPendingTokens({ customToken, selectedTokens }) - history.push(CONFIRM_ADD_TOKEN_ROUTE) + setPendingTokens({ customToken, selectedTokens }); + history.push(CONFIRM_ADD_TOKEN_ROUTE); } async attemptToAutoFillTokenParams(address) { - const { symbol = '', decimals = 0 } = await this.tokenInfoGetter(address) + const { symbol = '', decimals = 0 } = await this.tokenInfoGetter(address); - const autoFilled = Boolean(symbol && decimals) - this.setState({ autoFilled }) - this.handleCustomSymbolChange(symbol || '') - this.handleCustomDecimalsChange(decimals) + const autoFilled = Boolean(symbol && decimals); + this.setState({ autoFilled }); + this.handleCustomSymbolChange(symbol || ''); + this.handleCustomDecimalsChange(decimals); } handleCustomAddressChange(value) { - const customAddress = value.trim() + const customAddress = value.trim(); this.setState({ customAddress, customAddressError: null, tokenSelectorError: null, autoFilled: false, - }) + }); - const isValidAddress = ethUtil.isValidAddress(customAddress) - const standardAddress = addHexPrefix(customAddress).toLowerCase() + const isValidAddress = ethUtil.isValidAddress(customAddress); + const standardAddress = addHexPrefix(customAddress).toLowerCase(); switch (true) { case !isValidAddress: @@ -172,54 +172,54 @@ class AddToken extends Component { customDecimals: 0, customSymbolError: null, customDecimalsError: null, - }) + }); - break + break; case Boolean(this.props.identities[standardAddress]): this.setState({ customAddressError: this.context.t('personalAddressDetected'), - }) + }); - break + break; case checkExistingAddresses(customAddress, this.props.tokens): this.setState({ customAddressError: this.context.t('tokenAlreadyAdded'), - }) + }); - break + break; default: if (customAddress !== emptyAddr) { - this.attemptToAutoFillTokenParams(customAddress) + this.attemptToAutoFillTokenParams(customAddress); } } } handleCustomSymbolChange(value) { - const customSymbol = value.trim() - const symbolLength = customSymbol.length - let customSymbolError = null + const customSymbol = value.trim(); + const symbolLength = customSymbol.length; + let customSymbolError = null; if (symbolLength <= 0 || symbolLength >= 12) { - customSymbolError = this.context.t('symbolBetweenZeroTwelve') + customSymbolError = this.context.t('symbolBetweenZeroTwelve'); } - this.setState({ customSymbol, customSymbolError }) + this.setState({ customSymbol, customSymbolError }); } handleCustomDecimalsChange(value) { - const customDecimals = value.trim() + const customDecimals = value.trim(); const validDecimals = customDecimals !== null && customDecimals !== '' && customDecimals >= 0 && - customDecimals <= 36 - let customDecimalsError = null + customDecimals <= 36; + let customDecimalsError = null; if (!validDecimals) { - customDecimalsError = this.context.t('decimalsMustZerotoTen') + customDecimalsError = this.context.t('decimalsMustZerotoTen'); } - this.setState({ customDecimals, customDecimalsError }) + this.setState({ customDecimals, customDecimalsError }); } renderCustomTokenForm() { @@ -232,7 +232,7 @@ class AddToken extends Component { customDecimalsError, autoFilled, forceEditSymbol, - } = this.state + } = this.state; return (
    @@ -284,11 +284,11 @@ class AddToken extends Component { disabled={autoFilled} />
    - ) + ); } renderSearchToken() { - const { tokenSelectorError, selectedTokens, searchResults } = this.state + const { tokenSelectorError, selectedTokens, searchResults } = this.state; return (
    @@ -306,7 +306,7 @@ class AddToken extends Component { />
    - ) + ); } renderTabs() { @@ -317,11 +317,11 @@ class AddToken extends Component { {this.renderCustomTokenForm()} - ) + ); } render() { - const { history, clearPendingTokens, mostRecentOverviewPage } = this.props + const { history, clearPendingTokens, mostRecentOverviewPage } = this.props; return ( this.handleNext()} disabled={Boolean(this.hasError()) || !this.hasSelected()} onCancel={() => { - clearPendingTokens() - history.push(mostRecentOverviewPage) + clearPendingTokens(); + history.push(mostRecentOverviewPage); }} /> - ) + ); } } -export default AddToken +export default AddToken; diff --git a/ui/app/pages/add-token/add-token.container.js b/ui/app/pages/add-token/add-token.container.js index 80059a689..490b34583 100644 --- a/ui/app/pages/add-token/add-token.container.js +++ b/ui/app/pages/add-token/add-token.container.js @@ -1,26 +1,26 @@ -import { connect } from 'react-redux' +import { connect } from 'react-redux'; -import { setPendingTokens, clearPendingTokens } from '../../store/actions' -import { getMostRecentOverviewPage } from '../../ducks/history/history' -import AddToken from './add-token.component' +import { setPendingTokens, clearPendingTokens } from '../../store/actions'; +import { getMostRecentOverviewPage } from '../../ducks/history/history'; +import AddToken from './add-token.component'; const mapStateToProps = (state) => { const { metamask: { identities, tokens, pendingTokens }, - } = state + } = state; return { identities, mostRecentOverviewPage: getMostRecentOverviewPage(state), tokens, pendingTokens, - } -} + }; +}; const mapDispatchToProps = (dispatch) => { return { setPendingTokens: (tokens) => dispatch(setPendingTokens(tokens)), clearPendingTokens: () => dispatch(clearPendingTokens()), - } -} + }; +}; -export default connect(mapStateToProps, mapDispatchToProps)(AddToken) +export default connect(mapStateToProps, mapDispatchToProps)(AddToken); diff --git a/ui/app/pages/add-token/index.js b/ui/app/pages/add-token/index.js index ab78bb05d..e107950f1 100644 --- a/ui/app/pages/add-token/index.js +++ b/ui/app/pages/add-token/index.js @@ -1,3 +1,3 @@ -import AddToken from './add-token.container' +import AddToken from './add-token.container'; -export default AddToken +export default AddToken; diff --git a/ui/app/pages/add-token/tests/add-token.test.js b/ui/app/pages/add-token/tests/add-token.test.js index 697724dd7..bc130409c 100644 --- a/ui/app/pages/add-token/tests/add-token.test.js +++ b/ui/app/pages/add-token/tests/add-token.test.js @@ -1,21 +1,21 @@ -import assert from 'assert' -import React from 'react' -import { Provider } from 'react-redux' -import sinon from 'sinon' -import configureMockStore from 'redux-mock-store' -import { mountWithRouter } from '../../../../../test/lib/render-helpers' -import AddToken from '..' +import assert from 'assert'; +import React from 'react'; +import { Provider } from 'react-redux'; +import sinon from 'sinon'; +import configureMockStore from 'redux-mock-store'; +import { mountWithRouter } from '../../../../../test/lib/render-helpers'; +import AddToken from '..'; describe('Add Token', function () { - let wrapper + let wrapper; const state = { metamask: { tokens: [], }, - } + }; - const store = configureMockStore()(state) + const store = configureMockStore()(state); const props = { history: { @@ -26,7 +26,7 @@ describe('Add Token', function () { tokens: [], identities: {}, mostRecentOverviewPage: '/', - } + }; describe('Add Token', function () { before(function () { @@ -35,81 +35,81 @@ describe('Add Token', function () { , store, - ) + ); - wrapper.find({ name: 'customToken' }).simulate('click') - }) + wrapper.find({ name: 'customToken' }).simulate('click'); + }); afterEach(function () { - props.history.push.reset() - }) + props.history.push.reset(); + }); it('next button is disabled when no fields are populated', function () { const nextButton = wrapper.find( '.button.btn-secondary.page-container__footer-button', - ) + ); - assert.strictEqual(nextButton.props().disabled, true) - }) + assert.strictEqual(nextButton.props().disabled, true); + }); it('edits token address', function () { - const tokenAddress = '0x617b3f8050a0BD94b6b1da02B4384eE5B4DF13F4' - const event = { target: { value: tokenAddress } } - const customAddress = wrapper.find('input#custom-address') + const tokenAddress = '0x617b3f8050a0BD94b6b1da02B4384eE5B4DF13F4'; + const event = { target: { value: tokenAddress } }; + const customAddress = wrapper.find('input#custom-address'); - customAddress.simulate('change', event) + customAddress.simulate('change', event); assert.strictEqual( wrapper.find('AddToken').instance().state.customAddress, tokenAddress, - ) - }) + ); + }); it('edits token symbol', function () { - const tokenSymbol = 'META' - const event = { target: { value: tokenSymbol } } - const customAddress = wrapper.find('#custom-symbol') - customAddress.last().simulate('change', event) + const tokenSymbol = 'META'; + const event = { target: { value: tokenSymbol } }; + const customAddress = wrapper.find('#custom-symbol'); + customAddress.last().simulate('change', event); assert.strictEqual( wrapper.find('AddToken').instance().state.customSymbol, tokenSymbol, - ) - }) + ); + }); it('edits token decimal precision', function () { - const tokenPrecision = '2' - const event = { target: { value: tokenPrecision } } - const customAddress = wrapper.find('#custom-decimals') - customAddress.last().simulate('change', event) + const tokenPrecision = '2'; + const event = { target: { value: tokenPrecision } }; + const customAddress = wrapper.find('#custom-decimals'); + customAddress.last().simulate('change', event); assert.strictEqual( wrapper.find('AddToken').instance().state.customDecimals, tokenPrecision, - ) - }) + ); + }); it('next', function () { const nextButton = wrapper.find( '.button.btn-secondary.page-container__footer-button', - ) - nextButton.simulate('click') + ); + nextButton.simulate('click'); - assert(props.setPendingTokens.calledOnce) - assert(props.history.push.calledOnce) + assert(props.setPendingTokens.calledOnce); + assert(props.history.push.calledOnce); assert.strictEqual( props.history.push.getCall(0).args[0], '/confirm-add-token', - ) - }) + ); + }); it('cancels', function () { const cancelButton = wrapper.find( 'button.btn-default.page-container__footer-button', - ) - cancelButton.simulate('click') + ); + cancelButton.simulate('click'); - assert(props.clearPendingTokens.calledOnce) - assert.strictEqual(props.history.push.getCall(0).args[0], '/') - }) - }) -}) + assert(props.clearPendingTokens.calledOnce); + assert.strictEqual(props.history.push.getCall(0).args[0], '/'); + }); + }); +}); diff --git a/ui/app/pages/add-token/token-list/index.js b/ui/app/pages/add-token/token-list/index.js index 617485728..638d76a97 100644 --- a/ui/app/pages/add-token/token-list/index.js +++ b/ui/app/pages/add-token/token-list/index.js @@ -1,3 +1,3 @@ -import TokenList from './token-list.container' +import TokenList from './token-list.container'; -export default TokenList +export default TokenList; diff --git a/ui/app/pages/add-token/token-list/token-list-placeholder/index.js b/ui/app/pages/add-token/token-list/token-list-placeholder/index.js index 395e7b077..b23d23a29 100644 --- a/ui/app/pages/add-token/token-list/token-list-placeholder/index.js +++ b/ui/app/pages/add-token/token-list/token-list-placeholder/index.js @@ -1,3 +1,3 @@ -import TokenListPlaceholder from './token-list-placeholder.component' +import TokenListPlaceholder from './token-list-placeholder.component'; -export default TokenListPlaceholder +export default TokenListPlaceholder; diff --git a/ui/app/pages/add-token/token-list/token-list-placeholder/token-list-placeholder.component.js b/ui/app/pages/add-token/token-list/token-list-placeholder/token-list-placeholder.component.js index 1cefea294..75cef89d1 100644 --- a/ui/app/pages/add-token/token-list/token-list-placeholder/token-list-placeholder.component.js +++ b/ui/app/pages/add-token/token-list/token-list-placeholder/token-list-placeholder.component.js @@ -1,11 +1,11 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import Button from '../../../../components/ui/button' +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import Button from '../../../../components/ui/button'; export default class TokenListPlaceholder extends Component { static contextTypes = { t: PropTypes.func, - } + }; render() { return ( @@ -24,6 +24,6 @@ export default class TokenListPlaceholder extends Component { {this.context.t('learnMore')} - ) + ); } } diff --git a/ui/app/pages/add-token/token-list/token-list.component.js b/ui/app/pages/add-token/token-list/token-list.component.js index 54006136e..819be4173 100644 --- a/ui/app/pages/add-token/token-list/token-list.component.js +++ b/ui/app/pages/add-token/token-list/token-list.component.js @@ -1,20 +1,20 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import classnames from 'classnames' -import { checkExistingAddresses } from '../../../helpers/utils/util' -import TokenListPlaceholder from './token-list-placeholder' +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; +import { checkExistingAddresses } from '../../../helpers/utils/util'; +import TokenListPlaceholder from './token-list-placeholder'; export default class TokenList extends Component { static contextTypes = { t: PropTypes.func, - } + }; static propTypes = { tokens: PropTypes.array, results: PropTypes.array, selectedTokens: PropTypes.object, onToggleToken: PropTypes.func, - } + }; render() { const { @@ -22,7 +22,7 @@ export default class TokenList extends Component { selectedTokens = {}, onToggleToken, tokens = [], - } = this.props + } = this.props; return results.length === 0 ? ( @@ -35,10 +35,10 @@ export default class TokenList extends Component { {Array(6) .fill(undefined) .map((_, i) => { - const { logo, symbol, name, address } = results[i] || {} - const tokenAlreadyAdded = checkExistingAddresses(address, tokens) + const { logo, symbol, name, address } = results[i] || {}; + const tokenAlreadyAdded = checkExistingAddresses(address, tokens); const onClick = () => - !tokenAlreadyAdded && onToggleToken(results[i]) + !tokenAlreadyAdded && onToggleToken(results[i]); return ( Boolean(logo || symbol || name) && ( @@ -63,10 +63,10 @@ export default class TokenList extends Component { ) - ) + ); })} - ) + ); } } diff --git a/ui/app/pages/add-token/token-list/token-list.container.js b/ui/app/pages/add-token/token-list/token-list.container.js index cd7b07a37..4896067f7 100644 --- a/ui/app/pages/add-token/token-list/token-list.container.js +++ b/ui/app/pages/add-token/token-list/token-list.container.js @@ -1,11 +1,11 @@ -import { connect } from 'react-redux' -import TokenList from './token-list.component' +import { connect } from 'react-redux'; +import TokenList from './token-list.component'; const mapStateToProps = ({ metamask }) => { - const { tokens } = metamask + const { tokens } = metamask; return { tokens, - } -} + }; +}; -export default connect(mapStateToProps)(TokenList) +export default connect(mapStateToProps)(TokenList); diff --git a/ui/app/pages/add-token/token-search/index.js b/ui/app/pages/add-token/token-search/index.js index bec39b3cf..59aee9744 100644 --- a/ui/app/pages/add-token/token-search/index.js +++ b/ui/app/pages/add-token/token-search/index.js @@ -1,3 +1,3 @@ -import TokenSearch from './token-search.component' +import TokenSearch from './token-search.component'; -export default TokenSearch +export default TokenSearch; diff --git a/ui/app/pages/add-token/token-search/token-search.component.js b/ui/app/pages/add-token/token-search/token-search.component.js index 8b889b057..f58ca299f 100644 --- a/ui/app/pages/add-token/token-search/token-search.component.js +++ b/ui/app/pages/add-token/token-search/token-search.component.js @@ -1,13 +1,13 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import contractMap from '@metamask/contract-metadata' -import Fuse from 'fuse.js' -import InputAdornment from '@material-ui/core/InputAdornment' -import TextField from '../../../components/ui/text-field' +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import contractMap from '@metamask/contract-metadata'; +import Fuse from 'fuse.js'; +import InputAdornment from '@material-ui/core/InputAdornment'; +import TextField from '../../../components/ui/text-field'; const contractList = Object.entries(contractMap) .map(([address, tokenData]) => ({ ...tokenData, address })) - .filter((tokenData) => Boolean(tokenData.erc20)) + .filter((tokenData) => Boolean(tokenData.erc20)); const fuse = new Fuse(contractList, { shouldSort: true, @@ -20,34 +20,34 @@ const fuse = new Fuse(contractList, { { name: 'name', weight: 0.5 }, { name: 'symbol', weight: 0.5 }, ], -}) +}); export default class TokenSearch extends Component { static contextTypes = { t: PropTypes.func, - } + }; static defaultProps = { error: null, - } + }; static propTypes = { onSearch: PropTypes.func, error: PropTypes.string, - } + }; state = { searchQuery: '', - } + }; handleSearch(searchQuery) { - this.setState({ searchQuery }) - const fuseSearchResult = fuse.search(searchQuery) + this.setState({ searchQuery }); + const fuseSearchResult = fuse.search(searchQuery); const addressSearchResult = contractList.filter((token) => { - return token.address.toLowerCase() === searchQuery.toLowerCase() - }) - const results = [...addressSearchResult, ...fuseSearchResult] - this.props.onSearch({ searchQuery, results }) + return token.address.toLowerCase() === searchQuery.toLowerCase(); + }); + const results = [...addressSearchResult, ...fuseSearchResult]; + this.props.onSearch({ searchQuery, results }); } renderAdornment() { @@ -55,12 +55,12 @@ export default class TokenSearch extends Component { - ) + ); } render() { - const { error } = this.props - const { searchQuery } = this.state + const { error } = this.props; + const { searchQuery } = this.state; return ( - ) + ); } } diff --git a/ui/app/pages/asset/asset.js b/ui/app/pages/asset/asset.js index 22baaf68a..cafdb2285 100644 --- a/ui/app/pages/asset/asset.js +++ b/ui/app/pages/asset/asset.js @@ -1,28 +1,28 @@ -import React from 'react' -import { useSelector } from 'react-redux' -import { Redirect, useParams } from 'react-router-dom' -import { getTokens } from '../../ducks/metamask/metamask' -import { DEFAULT_ROUTE } from '../../helpers/constants/routes' +import React from 'react'; +import { useSelector } from 'react-redux'; +import { Redirect, useParams } from 'react-router-dom'; +import { getTokens } from '../../ducks/metamask/metamask'; +import { DEFAULT_ROUTE } from '../../helpers/constants/routes'; -import NativeAsset from './components/native-asset' -import TokenAsset from './components/token-asset' +import NativeAsset from './components/native-asset'; +import TokenAsset from './components/token-asset'; const Asset = () => { - const nativeCurrency = useSelector((state) => state.metamask.nativeCurrency) - const tokens = useSelector(getTokens) - const { asset } = useParams() + const nativeCurrency = useSelector((state) => state.metamask.nativeCurrency); + const tokens = useSelector(getTokens); + const { asset } = useParams(); - const token = tokens.find(({ address }) => address === asset) + const token = tokens.find(({ address }) => address === asset); - let content + let content; if (token) { - content = + content = ; } else if (asset === nativeCurrency) { - content = + content = ; } else { - content = + content = ; } - return
    {content}
    -} + return
    {content}
    ; +}; -export default Asset +export default Asset; diff --git a/ui/app/pages/asset/components/asset-breadcrumb.js b/ui/app/pages/asset/components/asset-breadcrumb.js index a081e5b36..ac11054c3 100644 --- a/ui/app/pages/asset/components/asset-breadcrumb.js +++ b/ui/app/pages/asset/components/asset-breadcrumb.js @@ -1,5 +1,5 @@ -import React from 'react' -import PropTypes from 'prop-types' +import React from 'react'; +import PropTypes from 'prop-types'; const AssetBreadcrumb = ({ accountName, assetName, onBack }) => { return ( @@ -12,13 +12,13 @@ const AssetBreadcrumb = ({ accountName, assetName, onBack }) => {  /  {assetName} - ) -} + ); +}; AssetBreadcrumb.propTypes = { accountName: PropTypes.string.isRequired, assetName: PropTypes.string.isRequired, onBack: PropTypes.func.isRequired, -} +}; -export default AssetBreadcrumb +export default AssetBreadcrumb; diff --git a/ui/app/pages/asset/components/asset-navigation.js b/ui/app/pages/asset/components/asset-navigation.js index 2af0fac82..75789afbf 100644 --- a/ui/app/pages/asset/components/asset-navigation.js +++ b/ui/app/pages/asset/components/asset-navigation.js @@ -1,7 +1,7 @@ -import React from 'react' -import PropTypes from 'prop-types' +import React from 'react'; +import PropTypes from 'prop-types'; -import AssetBreadcrumb from './asset-breadcrumb' +import AssetBreadcrumb from './asset-breadcrumb'; const AssetNavigation = ({ accountName, assetName, onBack, optionsButton }) => { return ( @@ -13,18 +13,18 @@ const AssetNavigation = ({ accountName, assetName, onBack, optionsButton }) => { /> {optionsButton} - ) -} + ); +}; AssetNavigation.propTypes = { accountName: PropTypes.string.isRequired, assetName: PropTypes.string.isRequired, onBack: PropTypes.func.isRequired, optionsButton: PropTypes.element, -} +}; AssetNavigation.defaultProps = { optionsButton: undefined, -} +}; -export default AssetNavigation +export default AssetNavigation; diff --git a/ui/app/pages/asset/components/native-asset.js b/ui/app/pages/asset/components/native-asset.js index cb7f85750..629609e92 100644 --- a/ui/app/pages/asset/components/native-asset.js +++ b/ui/app/pages/asset/components/native-asset.js @@ -1,20 +1,20 @@ -import React from 'react' -import PropTypes from 'prop-types' -import { useSelector } from 'react-redux' -import { useHistory } from 'react-router-dom' +import React from 'react'; +import PropTypes from 'prop-types'; +import { useSelector } from 'react-redux'; +import { useHistory } from 'react-router-dom'; -import TransactionList from '../../../components/app/transaction-list' -import { EthOverview } from '../../../components/app/wallet-overview' -import { getSelectedIdentity } from '../../../selectors/selectors' -import { DEFAULT_ROUTE } from '../../../helpers/constants/routes' +import TransactionList from '../../../components/app/transaction-list'; +import { EthOverview } from '../../../components/app/wallet-overview'; +import { getSelectedIdentity } from '../../../selectors/selectors'; +import { DEFAULT_ROUTE } from '../../../helpers/constants/routes'; -import AssetNavigation from './asset-navigation' +import AssetNavigation from './asset-navigation'; export default function NativeAsset({ nativeCurrency }) { const selectedAccountName = useSelector( (state) => getSelectedIdentity(state).name, - ) - const history = useHistory() + ); + const history = useHistory(); return ( <> @@ -26,9 +26,9 @@ export default function NativeAsset({ nativeCurrency }) { - ) + ); } NativeAsset.propTypes = { nativeCurrency: PropTypes.string.isRequired, -} +}; diff --git a/ui/app/pages/asset/components/token-asset.js b/ui/app/pages/asset/components/token-asset.js index 00296a59e..4c6647ec4 100644 --- a/ui/app/pages/asset/components/token-asset.js +++ b/ui/app/pages/asset/components/token-asset.js @@ -1,28 +1,28 @@ -import React from 'react' -import PropTypes from 'prop-types' -import { useDispatch, useSelector } from 'react-redux' -import { useHistory } from 'react-router-dom' -import { createTokenTrackerLink } from '@metamask/etherscan-link' +import React from 'react'; +import PropTypes from 'prop-types'; +import { useDispatch, useSelector } from 'react-redux'; +import { useHistory } from 'react-router-dom'; +import { createTokenTrackerLink } from '@metamask/etherscan-link'; -import TransactionList from '../../../components/app/transaction-list' -import { TokenOverview } from '../../../components/app/wallet-overview' +import TransactionList from '../../../components/app/transaction-list'; +import { TokenOverview } from '../../../components/app/wallet-overview'; import { getCurrentNetworkId, getSelectedIdentity, -} from '../../../selectors/selectors' -import { DEFAULT_ROUTE } from '../../../helpers/constants/routes' -import { showModal } from '../../../store/actions' +} from '../../../selectors/selectors'; +import { DEFAULT_ROUTE } from '../../../helpers/constants/routes'; +import { showModal } from '../../../store/actions'; -import AssetNavigation from './asset-navigation' -import TokenOptions from './token-options' +import AssetNavigation from './asset-navigation'; +import TokenOptions from './token-options'; export default function TokenAsset({ token }) { - const dispatch = useDispatch() - const network = useSelector(getCurrentNetworkId) - const selectedIdentity = useSelector(getSelectedIdentity) - const selectedAccountName = selectedIdentity.name - const selectedAddress = selectedIdentity.address - const history = useHistory() + const dispatch = useDispatch(); + const network = useSelector(getCurrentNetworkId); + const selectedIdentity = useSelector(getSelectedIdentity); + const selectedAccountName = selectedIdentity.name; + const selectedAddress = selectedIdentity.address; + const history = useHistory(); return ( <> @@ -40,8 +40,8 @@ export default function TokenAsset({ token }) { token.address, network, selectedAddress, - ) - global.platform.openTab({ url }) + ); + global.platform.openTab({ url }); }} tokenSymbol={token.symbol} /> @@ -50,7 +50,7 @@ export default function TokenAsset({ token }) { - ) + ); } TokenAsset.propTypes = { @@ -59,4 +59,4 @@ TokenAsset.propTypes = { decimals: PropTypes.number, symbol: PropTypes.string, }).isRequired, -} +}; diff --git a/ui/app/pages/asset/components/token-options.js b/ui/app/pages/asset/components/token-options.js index 613455f57..51b18079a 100644 --- a/ui/app/pages/asset/components/token-options.js +++ b/ui/app/pages/asset/components/token-options.js @@ -1,15 +1,15 @@ -import React, { useContext, useState } from 'react' -import PropTypes from 'prop-types' +import React, { useContext, useState } from 'react'; +import PropTypes from 'prop-types'; -import { I18nContext } from '../../../contexts/i18n' -import { Menu, MenuItem } from '../../../components/ui/menu' +import { I18nContext } from '../../../contexts/i18n'; +import { Menu, MenuItem } from '../../../components/ui/menu'; const TokenOptions = ({ onRemove, onViewEtherscan, tokenSymbol }) => { - const t = useContext(I18nContext) + const t = useContext(I18nContext); const [tokenOptionsButtonElement, setTokenOptionsButtonElement] = useState( null, - ) - const [tokenOptionsOpen, setTokenOptionsOpen] = useState(false) + ); + const [tokenOptionsOpen, setTokenOptionsOpen] = useState(false); return ( <> @@ -29,8 +29,8 @@ const TokenOptions = ({ onRemove, onViewEtherscan, tokenSymbol }) => { iconClassName="fas fa-external-link-alt token-options__icon" data-testid="token-options__etherscan" onClick={() => { - setTokenOptionsOpen(false) - onViewEtherscan() + setTokenOptionsOpen(false); + onViewEtherscan(); }} > {t('viewOnEtherscan')} @@ -39,8 +39,8 @@ const TokenOptions = ({ onRemove, onViewEtherscan, tokenSymbol }) => { iconClassName="fas fa-trash-alt token-options__icon" data-testid="token-options__hide" onClick={() => { - setTokenOptionsOpen(false) - onRemove() + setTokenOptionsOpen(false); + onRemove(); }} > {t('hideTokenSymbol', [tokenSymbol])} @@ -48,13 +48,13 @@ const TokenOptions = ({ onRemove, onViewEtherscan, tokenSymbol }) => { ) : null} - ) -} + ); +}; TokenOptions.propTypes = { onRemove: PropTypes.func.isRequired, onViewEtherscan: PropTypes.func.isRequired, tokenSymbol: PropTypes.string.isRequired, -} +}; -export default TokenOptions +export default TokenOptions; diff --git a/ui/app/pages/asset/index.js b/ui/app/pages/asset/index.js index c8aeeec70..851200aa6 100644 --- a/ui/app/pages/asset/index.js +++ b/ui/app/pages/asset/index.js @@ -1 +1 @@ -export { default } from './asset' +export { default } from './asset'; diff --git a/ui/app/pages/confirm-add-suggested-token/confirm-add-suggested-token.component.js b/ui/app/pages/confirm-add-suggested-token/confirm-add-suggested-token.component.js index b65af863b..5c8c0e1d6 100644 --- a/ui/app/pages/confirm-add-suggested-token/confirm-add-suggested-token.component.js +++ b/ui/app/pages/confirm-add-suggested-token/confirm-add-suggested-token.component.js @@ -1,16 +1,16 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import Button from '../../components/ui/button' -import Identicon from '../../components/ui/identicon' -import TokenBalance from '../../components/ui/token-balance' -import { getEnvironmentType } from '../../../../app/scripts/lib/util' -import { ENVIRONMENT_TYPE_NOTIFICATION } from '../../../../shared/constants/app' +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import Button from '../../components/ui/button'; +import Identicon from '../../components/ui/identicon'; +import TokenBalance from '../../components/ui/token-balance'; +import { getEnvironmentType } from '../../../../app/scripts/lib/util'; +import { ENVIRONMENT_TYPE_NOTIFICATION } from '../../../../shared/constants/app'; export default class ConfirmAddSuggestedToken extends Component { static contextTypes = { t: PropTypes.func, trackEvent: PropTypes.func, - } + }; static propTypes = { history: PropTypes.object, @@ -19,32 +19,32 @@ export default class ConfirmAddSuggestedToken extends Component { pendingTokens: PropTypes.object, removeSuggestedTokens: PropTypes.func, tokens: PropTypes.array, - } + }; componentDidMount() { - this._checkPendingTokens() + this._checkPendingTokens(); } componentDidUpdate() { - this._checkPendingTokens() + this._checkPendingTokens(); } _checkPendingTokens() { - const { mostRecentOverviewPage, pendingTokens = {}, history } = this.props + const { mostRecentOverviewPage, pendingTokens = {}, history } = this.props; if (Object.keys(pendingTokens).length > 0) { - return + return; } if (getEnvironmentType() === ENVIRONMENT_TYPE_NOTIFICATION) { - global.platform.closeCurrentWindow() + global.platform.closeCurrentWindow(); } else { - history.push(mostRecentOverviewPage) + history.push(mostRecentOverviewPage); } } getTokenName(name, symbol) { - return typeof name === 'undefined' ? symbol : `${name} (${symbol})` + return typeof name === 'undefined' ? symbol : `${name} (${symbol})`; } render() { @@ -55,11 +55,11 @@ export default class ConfirmAddSuggestedToken extends Component { removeSuggestedTokens, history, mostRecentOverviewPage, - } = this.props - const pendingTokenKey = Object.keys(pendingTokens)[0] - const pendingToken = pendingTokens[pendingTokenKey] - const hasTokenDuplicates = this.checkTokenDuplicates(pendingTokens, tokens) - const reusesName = this.checkNameReuse(pendingTokens, tokens) + } = this.props; + const pendingTokenKey = Object.keys(pendingTokens)[0]; + const pendingToken = pendingTokens[pendingTokenKey]; + const hasTokenDuplicates = this.checkTokenDuplicates(pendingTokens, tokens); + const reusesName = this.checkNameReuse(pendingTokens, tokens); return (
    @@ -91,7 +91,7 @@ export default class ConfirmAddSuggestedToken extends Component {
    {Object.entries(pendingTokens).map(([address, token]) => { - const { name, symbol, image } = token + const { name, symbol, image } = token; return (
    - ) + ); })} @@ -127,7 +127,7 @@ export default class ConfirmAddSuggestedToken extends Component { onClick={() => { removeSuggestedTokens().then(() => history.push(mostRecentOverviewPage), - ) + ); }} > {this.context.t('cancel')} @@ -151,9 +151,9 @@ export default class ConfirmAddSuggestedToken extends Component { unlisted: pendingToken.unlisted, source: 'dapp', }, - }) + }); }) - .then(() => history.push(mostRecentOverviewPage)) + .then(() => history.push(mostRecentOverviewPage)); }} > {this.context.t('addToken')} @@ -161,17 +161,17 @@ export default class ConfirmAddSuggestedToken extends Component { - ) + ); } checkTokenDuplicates(pendingTokens, tokens) { - const pending = Object.keys(pendingTokens) - const existing = tokens.map((token) => token.address) + const pending = Object.keys(pendingTokens); + const existing = tokens.map((token) => token.address); const dupes = pending.filter((proposed) => { - return existing.includes(proposed) - }) + return existing.includes(proposed); + }); - return dupes.length > 0 + return dupes.length > 0; } /** @@ -186,9 +186,9 @@ export default class ConfirmAddSuggestedToken extends Component { .filter((token) => { const dupes = tokens .filter((old) => old.symbol === token.symbol) - .filter((old) => old.address !== token.address) - return dupes.length > 0 - }) - return duplicates.length > 0 + .filter((old) => old.address !== token.address); + return dupes.length > 0; + }); + return duplicates.length > 0; } } diff --git a/ui/app/pages/confirm-add-suggested-token/confirm-add-suggested-token.container.js b/ui/app/pages/confirm-add-suggested-token/confirm-add-suggested-token.container.js index 51a29a555..ae7eb131f 100644 --- a/ui/app/pages/confirm-add-suggested-token/confirm-add-suggested-token.container.js +++ b/ui/app/pages/confirm-add-suggested-token/confirm-add-suggested-token.container.js @@ -1,32 +1,32 @@ -import { connect } from 'react-redux' -import { compose } from 'redux' -import { withRouter } from 'react-router-dom' -import { addToken, removeSuggestedTokens } from '../../store/actions' -import { getMostRecentOverviewPage } from '../../ducks/history/history' -import ConfirmAddSuggestedToken from './confirm-add-suggested-token.component' +import { connect } from 'react-redux'; +import { compose } from 'redux'; +import { withRouter } from 'react-router-dom'; +import { addToken, removeSuggestedTokens } from '../../store/actions'; +import { getMostRecentOverviewPage } from '../../ducks/history/history'; +import ConfirmAddSuggestedToken from './confirm-add-suggested-token.component'; const mapStateToProps = (state) => { const { metamask: { pendingTokens, suggestedTokens, tokens }, - } = state - const params = { ...pendingTokens, ...suggestedTokens } + } = state; + const params = { ...pendingTokens, ...suggestedTokens }; return { mostRecentOverviewPage: getMostRecentOverviewPage(state), pendingTokens: params, tokens, - } -} + }; +}; const mapDispatchToProps = (dispatch) => { return { addToken: ({ address, symbol, decimals, image }) => dispatch(addToken(address, symbol, Number(decimals), image)), removeSuggestedTokens: () => dispatch(removeSuggestedTokens()), - } -} + }; +}; export default compose( withRouter, connect(mapStateToProps, mapDispatchToProps), -)(ConfirmAddSuggestedToken) +)(ConfirmAddSuggestedToken); diff --git a/ui/app/pages/confirm-add-suggested-token/index.js b/ui/app/pages/confirm-add-suggested-token/index.js index 275e0287b..e04fe003b 100644 --- a/ui/app/pages/confirm-add-suggested-token/index.js +++ b/ui/app/pages/confirm-add-suggested-token/index.js @@ -1,3 +1,3 @@ -import ConfirmAddSuggestedToken from './confirm-add-suggested-token.container' +import ConfirmAddSuggestedToken from './confirm-add-suggested-token.container'; -export default ConfirmAddSuggestedToken +export default ConfirmAddSuggestedToken; diff --git a/ui/app/pages/confirm-add-token/confirm-add-token.component.js b/ui/app/pages/confirm-add-token/confirm-add-token.component.js index 4334f377a..fed9a60e4 100644 --- a/ui/app/pages/confirm-add-token/confirm-add-token.component.js +++ b/ui/app/pages/confirm-add-token/confirm-add-token.component.js @@ -1,15 +1,15 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import { ASSET_ROUTE, ADD_TOKEN_ROUTE } from '../../helpers/constants/routes' -import Button from '../../components/ui/button' -import Identicon from '../../components/ui/identicon' -import TokenBalance from '../../components/ui/token-balance' +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import { ASSET_ROUTE, ADD_TOKEN_ROUTE } from '../../helpers/constants/routes'; +import Button from '../../components/ui/button'; +import Identicon from '../../components/ui/identicon'; +import TokenBalance from '../../components/ui/token-balance'; export default class ConfirmAddToken extends Component { static contextTypes = { t: PropTypes.func, trackEvent: PropTypes.func, - } + }; static propTypes = { history: PropTypes.object, @@ -17,18 +17,18 @@ export default class ConfirmAddToken extends Component { addTokens: PropTypes.func, mostRecentOverviewPage: PropTypes.string.isRequired, pendingTokens: PropTypes.object, - } + }; componentDidMount() { - const { mostRecentOverviewPage, pendingTokens = {}, history } = this.props + const { mostRecentOverviewPage, pendingTokens = {}, history } = this.props; if (Object.keys(pendingTokens).length === 0) { - history.push(mostRecentOverviewPage) + history.push(mostRecentOverviewPage); } } getTokenName(name, symbol) { - return typeof name === 'undefined' ? symbol : `${name} (${symbol})` + return typeof name === 'undefined' ? symbol : `${name} (${symbol})`; } render() { @@ -38,7 +38,7 @@ export default class ConfirmAddToken extends Component { clearPendingTokens, mostRecentOverviewPage, pendingTokens, - } = this.props + } = this.props; return (
    @@ -62,7 +62,7 @@ export default class ConfirmAddToken extends Component {
    {Object.entries(pendingTokens).map(([address, token]) => { - const { name, symbol } = token + const { name, symbol } = token; return (
    - ) + ); })} @@ -104,7 +104,7 @@ export default class ConfirmAddToken extends Component { className="page-container__footer-button" onClick={() => { addTokens(pendingTokens).then(() => { - const pendingTokenValues = Object.values(pendingTokens) + const pendingTokenValues = Object.values(pendingTokens); pendingTokenValues.forEach((pendingToken) => { this.context.trackEvent({ event: 'Token Added', @@ -116,16 +116,16 @@ export default class ConfirmAddToken extends Component { unlisted: pendingToken.unlisted, source: pendingToken.isCustom ? 'custom' : 'list', }, - }) - }) - clearPendingTokens() - const firstTokenAddress = pendingTokenValues?.[0].address?.toLowerCase() + }); + }); + clearPendingTokens(); + const firstTokenAddress = pendingTokenValues?.[0].address?.toLowerCase(); if (firstTokenAddress) { - history.push(`${ASSET_ROUTE}/${firstTokenAddress}`) + history.push(`${ASSET_ROUTE}/${firstTokenAddress}`); } else { - history.push(mostRecentOverviewPage) + history.push(mostRecentOverviewPage); } - }) + }); }} > {this.context.t('addTokens')} @@ -133,6 +133,6 @@ export default class ConfirmAddToken extends Component { - ) + ); } } diff --git a/ui/app/pages/confirm-add-token/confirm-add-token.container.js b/ui/app/pages/confirm-add-token/confirm-add-token.container.js index 08a01163c..aef46d261 100644 --- a/ui/app/pages/confirm-add-token/confirm-add-token.container.js +++ b/ui/app/pages/confirm-add-token/confirm-add-token.container.js @@ -1,24 +1,24 @@ -import { connect } from 'react-redux' +import { connect } from 'react-redux'; -import { addTokens, clearPendingTokens } from '../../store/actions' -import { getMostRecentOverviewPage } from '../../ducks/history/history' -import ConfirmAddToken from './confirm-add-token.component' +import { addTokens, clearPendingTokens } from '../../store/actions'; +import { getMostRecentOverviewPage } from '../../ducks/history/history'; +import ConfirmAddToken from './confirm-add-token.component'; const mapStateToProps = (state) => { const { metamask: { pendingTokens }, - } = state + } = state; return { mostRecentOverviewPage: getMostRecentOverviewPage(state), pendingTokens, - } -} + }; +}; const mapDispatchToProps = (dispatch) => { return { addTokens: (tokens) => dispatch(addTokens(tokens)), clearPendingTokens: () => dispatch(clearPendingTokens()), - } -} + }; +}; -export default connect(mapStateToProps, mapDispatchToProps)(ConfirmAddToken) +export default connect(mapStateToProps, mapDispatchToProps)(ConfirmAddToken); diff --git a/ui/app/pages/confirm-add-token/index.js b/ui/app/pages/confirm-add-token/index.js index f6b9cc47c..8b399cdca 100644 --- a/ui/app/pages/confirm-add-token/index.js +++ b/ui/app/pages/confirm-add-token/index.js @@ -1,3 +1,3 @@ -import ConfirmAddToken from './confirm-add-token.container' +import ConfirmAddToken from './confirm-add-token.container'; -export default ConfirmAddToken +export default ConfirmAddToken; diff --git a/ui/app/pages/confirm-approve/confirm-approve-content/confirm-approve-content.component.js b/ui/app/pages/confirm-approve/confirm-approve-content/confirm-approve-content.component.js index 78fe41fe7..42798fcd6 100644 --- a/ui/app/pages/confirm-approve/confirm-approve-content/confirm-approve-content.component.js +++ b/ui/app/pages/confirm-approve/confirm-approve-content/confirm-approve-content.component.js @@ -1,14 +1,14 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import classnames from 'classnames' -import Identicon from '../../../components/ui/identicon' -import { addressSummary } from '../../../helpers/utils/util' -import { formatCurrency } from '../../../helpers/utils/confirm-tx.util' +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; +import Identicon from '../../../components/ui/identicon'; +import { addressSummary } from '../../../helpers/utils/util'; +import { formatCurrency } from '../../../helpers/utils/confirm-tx.util'; export default class ConfirmApproveContent extends Component { static contextTypes = { t: PropTypes.func, - } + }; static propTypes = { decimals: PropTypes.number, @@ -27,11 +27,11 @@ export default class ConfirmApproveContent extends Component { nativeCurrency: PropTypes.string, fiatTransactionTotal: PropTypes.string, ethTransactionTotal: PropTypes.string, - } + }; state = { showFullTxDetails: false, - } + }; renderApproveContentCard({ symbol, @@ -68,18 +68,18 @@ export default class ConfirmApproveContent extends Component {
    {content}
    {footer} - ) + ); } // TODO: Add "Learn Why" with link to the feeAssociatedRequest text renderTransactionDetailsContent() { - const { t } = this.context + const { t } = this.context; const { currentCurrency, nativeCurrency, ethTransactionTotal, fiatTransactionTotal, - } = this.props + } = this.props; return (
    @@ -94,18 +94,18 @@ export default class ConfirmApproveContent extends Component {
    - ) + ); } renderPermissionContent() { - const { t } = this.context + const { t } = this.context; const { customTokenAmount, tokenAmount, tokenSymbol, origin, toAddress, - } = this.props + } = this.props; return (
    @@ -129,12 +129,12 @@ export default class ConfirmApproveContent extends Component {
    - ) + ); } renderDataContent() { - const { t } = this.context - const { data } = this.props + const { t } = this.context; + const { data } = this.props; return (
    @@ -144,11 +144,11 @@ export default class ConfirmApproveContent extends Component { {data}
    - ) + ); } render() { - const { t } = this.context + const { t } = this.context; const { decimals, siteImage, @@ -160,8 +160,8 @@ export default class ConfirmApproveContent extends Component { showEditApprovalPermissionModal, setCustomAmount, tokenBalance, - } = this.props - const { showFullTxDetails } = this.state + } = this.props; + const { showFullTxDetails } = this.state; return (
    ) : null}
    - ) + ); } } diff --git a/ui/app/pages/confirm-approve/confirm-approve-content/index.js b/ui/app/pages/confirm-approve/confirm-approve-content/index.js index 8f225387a..b9d1c3650 100644 --- a/ui/app/pages/confirm-approve/confirm-approve-content/index.js +++ b/ui/app/pages/confirm-approve/confirm-approve-content/index.js @@ -1 +1 @@ -export { default } from './confirm-approve-content.component' +export { default } from './confirm-approve-content.component'; diff --git a/ui/app/pages/confirm-approve/confirm-approve.js b/ui/app/pages/confirm-approve/confirm-approve.js index 9b8d7abde..bb9cb6ccc 100644 --- a/ui/app/pages/confirm-approve/confirm-approve.js +++ b/ui/app/pages/confirm-approve/confirm-approve.js @@ -1,91 +1,91 @@ -import React, { useEffect, useRef, useState } from 'react' -import { useDispatch, useSelector } from 'react-redux' -import { useParams } from 'react-router-dom' -import ConfirmTransactionBase from '../confirm-transaction-base' -import { showModal } from '../../store/actions' -import { getTokenData } from '../../helpers/utils/transactions.util' +import React, { useEffect, useRef, useState } from 'react'; +import { useDispatch, useSelector } from 'react-redux'; +import { useParams } from 'react-router-dom'; +import ConfirmTransactionBase from '../confirm-transaction-base'; +import { showModal } from '../../store/actions'; +import { getTokenData } from '../../helpers/utils/transactions.util'; import { calcTokenAmount, getTokenAddressParam, getTokenValueParam, -} from '../../helpers/utils/token-util' -import { useTokenTracker } from '../../hooks/useTokenTracker' -import { getTokens } from '../../ducks/metamask/metamask' +} from '../../helpers/utils/token-util'; +import { useTokenTracker } from '../../hooks/useTokenTracker'; +import { getTokens } from '../../ducks/metamask/metamask'; import { transactionFeeSelector, txDataSelector, getCurrentCurrency, getDomainMetadata, getNativeCurrency, -} from '../../selectors' -import { currentNetworkTxListSelector } from '../../selectors/transactions' -import { getCustomTxParamsData } from './confirm-approve.util' -import ConfirmApproveContent from './confirm-approve-content' +} from '../../selectors'; +import { currentNetworkTxListSelector } from '../../selectors/transactions'; +import { getCustomTxParamsData } from './confirm-approve.util'; +import ConfirmApproveContent from './confirm-approve-content'; export default function ConfirmApprove() { - const dispatch = useDispatch() - const { id: paramsTransactionId } = useParams() + const dispatch = useDispatch(); + const { id: paramsTransactionId } = useParams(); const { id: transactionId, txParams: { to: tokenAddress, data } = {}, - } = useSelector(txDataSelector) + } = useSelector(txDataSelector); - const currentCurrency = useSelector(getCurrentCurrency) - const nativeCurrency = useSelector(getNativeCurrency) - const currentNetworkTxList = useSelector(currentNetworkTxListSelector) - const domainMetadata = useSelector(getDomainMetadata) - const tokens = useSelector(getTokens) + const currentCurrency = useSelector(getCurrentCurrency); + const nativeCurrency = useSelector(getNativeCurrency); + const currentNetworkTxList = useSelector(currentNetworkTxListSelector); + const domainMetadata = useSelector(getDomainMetadata); + const tokens = useSelector(getTokens); const transaction = currentNetworkTxList.find( ({ id }) => id === (Number(paramsTransactionId) || transactionId), - ) || {} + ) || {}; const { ethTransactionTotal, fiatTransactionTotal } = useSelector((state) => transactionFeeSelector(state, transaction), - ) + ); const currentToken = (tokens && tokens.find(({ address }) => tokenAddress === address)) || { address: tokenAddress, - } + }; - const { tokensWithBalances } = useTokenTracker([currentToken]) - const tokenTrackerBalance = tokensWithBalances[0]?.balance || '' + const { tokensWithBalances } = useTokenTracker([currentToken]); + const tokenTrackerBalance = tokensWithBalances[0]?.balance || ''; - const tokenSymbol = currentToken?.symbol - const decimals = Number(currentToken?.decimals) - const tokenData = getTokenData(data) - const tokenValue = getTokenValueParam(tokenData) - const toAddress = getTokenAddressParam(tokenData) + const tokenSymbol = currentToken?.symbol; + const decimals = Number(currentToken?.decimals); + const tokenData = getTokenData(data); + const tokenValue = getTokenValueParam(tokenData); + const toAddress = getTokenAddressParam(tokenData); const tokenAmount = - tokenData && calcTokenAmount(tokenValue, decimals).toString(10) + tokenData && calcTokenAmount(tokenValue, decimals).toString(10); - const [customPermissionAmount, setCustomPermissionAmount] = useState('') + const [customPermissionAmount, setCustomPermissionAmount] = useState(''); - const previousTokenAmount = useRef(tokenAmount) + const previousTokenAmount = useRef(tokenAmount); useEffect(() => { if (customPermissionAmount && previousTokenAmount.current !== tokenAmount) { - setCustomPermissionAmount(tokenAmount) + setCustomPermissionAmount(tokenAmount); } - previousTokenAmount.current = tokenAmount - }, [customPermissionAmount, tokenAmount]) + previousTokenAmount.current = tokenAmount; + }, [customPermissionAmount, tokenAmount]); - const { origin } = transaction + const { origin } = transaction; const formattedOrigin = origin ? origin[0].toUpperCase() + origin.slice(1) - : '' - const txData = transaction + : ''; + const txData = transaction; - const { icon: siteImage = '' } = domainMetadata[origin] || {} + const { icon: siteImage = '' } = domainMetadata[origin] || {}; - const tokensText = `${Number(tokenAmount)} ${tokenSymbol}` + const tokensText = `${Number(tokenAmount)} ${tokenSymbol}`; const tokenBalance = tokenTrackerBalance ? calcTokenAmount(tokenTrackerBalance, decimals).toString(10) - : '' + : ''; const customData = customPermissionAmount ? getCustomTxParamsData(data, { customPermissionAmount, decimals }) - : null + : null; return ( - ) + ); } diff --git a/ui/app/pages/confirm-approve/confirm-approve.util.js b/ui/app/pages/confirm-approve/confirm-approve.util.js index b652256a1..e724ba58e 100644 --- a/ui/app/pages/confirm-approve/confirm-approve.util.js +++ b/ui/app/pages/confirm-approve/confirm-approve.util.js @@ -1,46 +1,49 @@ -import { TRANSACTION_CATEGORIES } from '../../../../shared/constants/transaction' -import { decimalToHex } from '../../helpers/utils/conversions.util' +import { TRANSACTION_CATEGORIES } from '../../../../shared/constants/transaction'; +import { decimalToHex } from '../../helpers/utils/conversions.util'; import { calcTokenValue, getTokenAddressParam, -} from '../../helpers/utils/token-util' -import { getTokenData } from '../../helpers/utils/transactions.util' +} from '../../helpers/utils/token-util'; +import { getTokenData } from '../../helpers/utils/transactions.util'; export function getCustomTxParamsData( data, { customPermissionAmount, decimals }, ) { - const tokenData = getTokenData(data) + const tokenData = getTokenData(data); if (!tokenData) { - throw new Error('Invalid data') + throw new Error('Invalid data'); } else if (tokenData.name !== TRANSACTION_CATEGORIES.TOKEN_METHOD_APPROVE) { throw new Error( `Invalid data; should be 'approve' method, but instead is '${tokenData.name}'`, - ) + ); } - let spender = getTokenAddressParam(tokenData) + let spender = getTokenAddressParam(tokenData); if (spender.startsWith('0x')) { - spender = spender.substring(2) + spender = spender.substring(2); } - const [signature, tokenValue] = data.split(spender) + const [signature, tokenValue] = data.split(spender); if (!signature || !tokenValue) { - throw new Error('Invalid data') + throw new Error('Invalid data'); } else if (tokenValue.length !== 64) { throw new Error( 'Invalid token value; should be exactly 64 hex digits long (u256)', - ) + ); } let customPermissionValue = decimalToHex( calcTokenValue(customPermissionAmount, decimals), - ) + ); if (customPermissionValue.length > 64) { - throw new Error('Custom value is larger than u256') + throw new Error('Custom value is larger than u256'); } - customPermissionValue = customPermissionValue.padStart(tokenValue.length, '0') - const customTxParamsData = `${signature}${spender}${customPermissionValue}` - return customTxParamsData + customPermissionValue = customPermissionValue.padStart( + tokenValue.length, + '0', + ); + const customTxParamsData = `${signature}${spender}${customPermissionValue}`; + return customTxParamsData; } diff --git a/ui/app/pages/confirm-approve/index.js b/ui/app/pages/confirm-approve/index.js index 204209330..36d3ae135 100644 --- a/ui/app/pages/confirm-approve/index.js +++ b/ui/app/pages/confirm-approve/index.js @@ -1 +1 @@ -export { default } from './confirm-approve' +export { default } from './confirm-approve'; diff --git a/ui/app/pages/confirm-decrypt-message/confirm-decrypt-message.component.js b/ui/app/pages/confirm-decrypt-message/confirm-decrypt-message.component.js index 40e4a42e2..bae3e22eb 100644 --- a/ui/app/pages/confirm-decrypt-message/confirm-decrypt-message.component.js +++ b/ui/app/pages/confirm-decrypt-message/confirm-decrypt-message.component.js @@ -1,23 +1,23 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import copyToClipboard from 'copy-to-clipboard' -import classnames from 'classnames' +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import copyToClipboard from 'copy-to-clipboard'; +import classnames from 'classnames'; -import AccountListItem from '../../components/app/account-list-item' -import Button from '../../components/ui/button' -import Identicon from '../../components/ui/identicon' -import Tooltip from '../../components/ui/tooltip' -import Copy from '../../components/ui/icon/copy-icon.component' +import AccountListItem from '../../components/app/account-list-item'; +import Button from '../../components/ui/button'; +import Identicon from '../../components/ui/identicon'; +import Tooltip from '../../components/ui/tooltip'; +import Copy from '../../components/ui/icon/copy-icon.component'; -import { ENVIRONMENT_TYPE_NOTIFICATION } from '../../../../shared/constants/app' -import { getEnvironmentType } from '../../../../app/scripts/lib/util' -import { conversionUtil } from '../../helpers/utils/conversion-util' +import { ENVIRONMENT_TYPE_NOTIFICATION } from '../../../../shared/constants/app'; +import { getEnvironmentType } from '../../../../app/scripts/lib/util'; +import { conversionUtil } from '../../helpers/utils/conversion-util'; export default class ConfirmDecryptMessage extends Component { static contextTypes = { t: PropTypes.func.isRequired, metricsEvent: PropTypes.func.isRequired, - } + }; static propTypes = { fromAccount: PropTypes.shape({ @@ -35,60 +35,64 @@ export default class ConfirmDecryptMessage extends Component { requesterAddress: PropTypes.string, txData: PropTypes.object, domainMetadata: PropTypes.object, - } + }; state = { fromAccount: this.props.fromAccount, copyToClipboardPressed: false, hasCopied: false, - } + }; componentDidMount = () => { if ( getEnvironmentType(window.location.href) === ENVIRONMENT_TYPE_NOTIFICATION ) { - window.addEventListener('beforeunload', this._beforeUnload) + window.addEventListener('beforeunload', this._beforeUnload); } - } + }; componentWillUnmount = () => { - this._removeBeforeUnload() - } + this._removeBeforeUnload(); + }; _beforeUnload = async (event) => { - const { clearConfirmTransaction, cancelDecryptMessage, txData } = this.props - const { metricsEvent } = this.context - await cancelDecryptMessage(txData, event) + const { + clearConfirmTransaction, + cancelDecryptMessage, + txData, + } = this.props; + const { metricsEvent } = this.context; + await cancelDecryptMessage(txData, event); metricsEvent({ eventOpts: { category: 'Messages', action: 'Decrypt Message Request', name: 'Cancel Via Notification Close', }, - }) - clearConfirmTransaction() - } + }); + clearConfirmTransaction(); + }; _removeBeforeUnload = () => { if ( getEnvironmentType(window.location.href) === ENVIRONMENT_TYPE_NOTIFICATION ) { - window.removeEventListener('beforeunload', this._beforeUnload) + window.removeEventListener('beforeunload', this._beforeUnload); } - } + }; copyMessage = () => { - copyToClipboard(this.state.rawMessage) + copyToClipboard(this.state.rawMessage); this.context.metricsEvent({ eventOpts: { category: 'Messages', action: 'Decrypt Message Copy', name: 'Copy', }, - }) - this.setState({ hasCopied: true }) - setTimeout(() => this.setState({ hasCopied: false }), 3000) - } + }); + this.setState({ hasCopied: true }); + setTimeout(() => this.setState({ hasCopied: false }), 3000); + }; renderHeader = () => { return ( @@ -103,12 +107,12 @@ export default class ConfirmDecryptMessage extends Component {
    - ) - } + ); + }; renderAccount = () => { - const { fromAccount } = this.state - const { t } = this.context + const { fromAccount } = this.state; + const { t } = this.context; return (
    @@ -120,15 +124,15 @@ export default class ConfirmDecryptMessage extends Component {
    - ) - } + ); + }; renderBalance = () => { - const { conversionRate } = this.props + const { conversionRate } = this.props; const { fromAccount: { balance }, - } = this.state - const { t } = this.context + } = this.state; + const { t } = this.context; const balanceInEther = conversionUtil(balance, { fromNumericBase: 'hex', @@ -136,7 +140,7 @@ export default class ConfirmDecryptMessage extends Component { fromDenomination: 'WEI', numberOfDecimals: 6, conversionRate, - }) + }); return (
    @@ -147,18 +151,18 @@ export default class ConfirmDecryptMessage extends Component { {`${balanceInEther} ETH`}
    - ) - } + ); + }; renderRequestIcon = () => { - const { requesterAddress } = this.props + const { requesterAddress } = this.props; return (
    - ) - } + ); + }; renderAccountInfo = () => { return ( @@ -167,16 +171,16 @@ export default class ConfirmDecryptMessage extends Component { {this.renderRequestIcon()} {this.renderBalance()} - ) - } + ); + }; renderBody = () => { - const { decryptMessageInline, domainMetadata, txData } = this.props - const { t } = this.context + const { decryptMessageInline, domainMetadata, txData } = this.props; + const { t } = this.context; - const originMetadata = domainMetadata[txData.msgParams.origin] - const name = originMetadata?.name || txData.msgParams.origin - const notice = t('decryptMessageNotice', [txData.msgParams.origin]) + const originMetadata = domainMetadata[txData.msgParams.origin]; + const name = originMetadata?.name || txData.msgParams.origin; + const notice = t('decryptMessageNotice', [txData.msgParams.origin]); const { hasCopied, @@ -185,7 +189,7 @@ export default class ConfirmDecryptMessage extends Component { rawMessage, errorMessage, copyToClipboardPressed, - } = this.state + } = this.state; return (
    @@ -232,14 +236,14 @@ export default class ConfirmDecryptMessage extends Component { errorMessage: this.context.t('decryptInlineError', [ result.error, ]), - }) + }); } else { this.setState({ hasDecrypted: true, rawMessage: result.rawData, - }) + }); } - }) + }); }} > @@ -274,8 +278,8 @@ export default class ConfirmDecryptMessage extends Component {
    )}
    - ) - } + ); + }; renderFooter = () => { const { @@ -285,8 +289,8 @@ export default class ConfirmDecryptMessage extends Component { history, mostRecentOverviewPage, txData, - } = this.props - const { metricsEvent, t } = this.context + } = this.props; + const { metricsEvent, t } = this.context; return (
    @@ -295,17 +299,17 @@ export default class ConfirmDecryptMessage extends Component { large className="request-decrypt-message__footer__cancel-button" onClick={async (event) => { - this._removeBeforeUnload() - await cancelDecryptMessage(txData, event) + this._removeBeforeUnload(); + await cancelDecryptMessage(txData, event); metricsEvent({ eventOpts: { category: 'Messages', action: 'Decrypt Message Request', name: 'Cancel', }, - }) - clearConfirmTransaction() - history.push(mostRecentOverviewPage) + }); + clearConfirmTransaction(); + history.push(mostRecentOverviewPage); }} > {t('cancel')} @@ -315,24 +319,24 @@ export default class ConfirmDecryptMessage extends Component { large className="request-decrypt-message__footer__sign-button" onClick={async (event) => { - this._removeBeforeUnload() - await decryptMessage(txData, event) + this._removeBeforeUnload(); + await decryptMessage(txData, event); metricsEvent({ eventOpts: { category: 'Messages', action: 'Decrypt Message Request', name: 'Confirm', }, - }) - clearConfirmTransaction() - history.push(mostRecentOverviewPage) + }); + clearConfirmTransaction(); + history.push(mostRecentOverviewPage); }} > {t('decrypt')}
    - ) - } + ); + }; render = () => { return ( @@ -341,6 +345,6 @@ export default class ConfirmDecryptMessage extends Component { {this.renderBody()} {this.renderFooter()} - ) - } + ); + }; } diff --git a/ui/app/pages/confirm-decrypt-message/confirm-decrypt-message.container.js b/ui/app/pages/confirm-decrypt-message/confirm-decrypt-message.container.js index 6be21e2ea..800ec7abc 100644 --- a/ui/app/pages/confirm-decrypt-message/confirm-decrypt-message.container.js +++ b/ui/app/pages/confirm-decrypt-message/confirm-decrypt-message.container.js @@ -1,34 +1,34 @@ -import { connect } from 'react-redux' -import { compose } from 'redux' -import { withRouter } from 'react-router-dom' +import { connect } from 'react-redux'; +import { compose } from 'redux'; +import { withRouter } from 'react-router-dom'; import { goHome, decryptMsg, cancelDecryptMsg, decryptMsgInline, -} from '../../store/actions' +} from '../../store/actions'; import { getTargetAccountWithSendEtherInfo, conversionRateSelector, -} from '../../selectors' -import { clearConfirmTransaction } from '../../ducks/confirm-transaction/confirm-transaction.duck' -import { getMostRecentOverviewPage } from '../../ducks/history/history' -import ConfirmDecryptMessage from './confirm-decrypt-message.component' +} from '../../selectors'; +import { clearConfirmTransaction } from '../../ducks/confirm-transaction/confirm-transaction.duck'; +import { getMostRecentOverviewPage } from '../../ducks/history/history'; +import ConfirmDecryptMessage from './confirm-decrypt-message.component'; function mapStateToProps(state) { const { confirmTransaction, metamask: { domainMetadata = {} }, - } = state + } = state; - const { txData = {} } = confirmTransaction + const { txData = {} } = confirmTransaction; const { msgParams: { from }, - } = txData + } = txData; - const fromAccount = getTargetAccountWithSendEtherInfo(state, from) + const fromAccount = getTargetAccountWithSendEtherInfo(state, from); return { txData, @@ -38,7 +38,7 @@ function mapStateToProps(state) { requesterAddress: null, conversionRate: conversionRateSelector(state), mostRecentOverviewPage: getMostRecentOverviewPage(state), - } + }; } function mapDispatchToProps(dispatch) { @@ -46,25 +46,25 @@ function mapDispatchToProps(dispatch) { goHome: () => dispatch(goHome()), clearConfirmTransaction: () => dispatch(clearConfirmTransaction()), decryptMessage: (msgData, event) => { - const params = msgData.msgParams - params.metamaskId = msgData.id - event.stopPropagation(event) - return dispatch(decryptMsg(params)) + const params = msgData.msgParams; + params.metamaskId = msgData.id; + event.stopPropagation(event); + return dispatch(decryptMsg(params)); }, cancelDecryptMessage: (msgData, event) => { - event.stopPropagation(event) - return dispatch(cancelDecryptMsg(msgData)) + event.stopPropagation(event); + return dispatch(cancelDecryptMsg(msgData)); }, decryptMessageInline: (msgData, event) => { - const params = msgData.msgParams - params.metamaskId = msgData.id - event.stopPropagation(event) - return dispatch(decryptMsgInline(params)) + const params = msgData.msgParams; + params.metamaskId = msgData.id; + event.stopPropagation(event); + return dispatch(decryptMsgInline(params)); }, - } + }; } export default compose( withRouter, connect(mapStateToProps, mapDispatchToProps), -)(ConfirmDecryptMessage) +)(ConfirmDecryptMessage); diff --git a/ui/app/pages/confirm-decrypt-message/index.js b/ui/app/pages/confirm-decrypt-message/index.js index 9cc671681..c375f08a6 100644 --- a/ui/app/pages/confirm-decrypt-message/index.js +++ b/ui/app/pages/confirm-decrypt-message/index.js @@ -1 +1 @@ -export { default } from './confirm-decrypt-message.container' +export { default } from './confirm-decrypt-message.container'; diff --git a/ui/app/pages/confirm-deploy-contract/confirm-deploy-contract.component.js b/ui/app/pages/confirm-deploy-contract/confirm-deploy-contract.component.js index d799aa28d..49a192071 100644 --- a/ui/app/pages/confirm-deploy-contract/confirm-deploy-contract.component.js +++ b/ui/app/pages/confirm-deploy-contract/confirm-deploy-contract.component.js @@ -1,20 +1,20 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import ethUtil from 'ethereumjs-util' -import ConfirmTransactionBase from '../confirm-transaction-base' +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import ethUtil from 'ethereumjs-util'; +import ConfirmTransactionBase from '../confirm-transaction-base'; export default class ConfirmDeployContract extends Component { static contextTypes = { t: PropTypes.func, - } + }; static propTypes = { txData: PropTypes.object, - } + }; renderData() { - const { t } = this.context - const { txData: { origin, txParams: { data } = {} } = {} } = this.props + const { t } = this.context; + const { txData: { origin, txParams: { data } = {} } = {} } = this.props; return (
    @@ -37,7 +37,7 @@ export default class ConfirmDeployContract extends Component {
    {data}
    - ) + ); } render() { @@ -46,6 +46,6 @@ export default class ConfirmDeployContract extends Component { actionKey="contractDeployment" dataComponent={this.renderData()} /> - ) + ); } } diff --git a/ui/app/pages/confirm-deploy-contract/confirm-deploy-contract.container.js b/ui/app/pages/confirm-deploy-contract/confirm-deploy-contract.container.js index e66dd3b60..633454c0f 100644 --- a/ui/app/pages/confirm-deploy-contract/confirm-deploy-contract.container.js +++ b/ui/app/pages/confirm-deploy-contract/confirm-deploy-contract.container.js @@ -1,12 +1,12 @@ -import { connect } from 'react-redux' -import ConfirmDeployContract from './confirm-deploy-contract.component' +import { connect } from 'react-redux'; +import ConfirmDeployContract from './confirm-deploy-contract.component'; const mapStateToProps = (state) => { - const { confirmTransaction: { txData } = {} } = state + const { confirmTransaction: { txData } = {} } = state; return { txData, - } -} + }; +}; -export default connect(mapStateToProps)(ConfirmDeployContract) +export default connect(mapStateToProps)(ConfirmDeployContract); diff --git a/ui/app/pages/confirm-deploy-contract/index.js b/ui/app/pages/confirm-deploy-contract/index.js index c4fb01b52..02f222fb2 100644 --- a/ui/app/pages/confirm-deploy-contract/index.js +++ b/ui/app/pages/confirm-deploy-contract/index.js @@ -1 +1 @@ -export { default } from './confirm-deploy-contract.container' +export { default } from './confirm-deploy-contract.container'; diff --git a/ui/app/pages/confirm-encryption-public-key/confirm-encryption-public-key.component.js b/ui/app/pages/confirm-encryption-public-key/confirm-encryption-public-key.component.js index a1c1178f7..45e192da6 100644 --- a/ui/app/pages/confirm-encryption-public-key/confirm-encryption-public-key.component.js +++ b/ui/app/pages/confirm-encryption-public-key/confirm-encryption-public-key.component.js @@ -1,19 +1,19 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; -import AccountListItem from '../../components/app/account-list-item' -import Button from '../../components/ui/button' -import Identicon from '../../components/ui/identicon' +import AccountListItem from '../../components/app/account-list-item'; +import Button from '../../components/ui/button'; +import Identicon from '../../components/ui/identicon'; -import { ENVIRONMENT_TYPE_NOTIFICATION } from '../../../../shared/constants/app' -import { getEnvironmentType } from '../../../../app/scripts/lib/util' -import { conversionUtil } from '../../helpers/utils/conversion-util' +import { ENVIRONMENT_TYPE_NOTIFICATION } from '../../../../shared/constants/app'; +import { getEnvironmentType } from '../../../../app/scripts/lib/util'; +import { conversionUtil } from '../../helpers/utils/conversion-util'; export default class ConfirmEncryptionPublicKey extends Component { static contextTypes = { t: PropTypes.func.isRequired, metricsEvent: PropTypes.func.isRequired, - } + }; static propTypes = { fromAccount: PropTypes.shape({ @@ -30,49 +30,49 @@ export default class ConfirmEncryptionPublicKey extends Component { txData: PropTypes.object, domainMetadata: PropTypes.object, mostRecentOverviewPage: PropTypes.string.isRequired, - } + }; state = { fromAccount: this.props.fromAccount, - } + }; componentDidMount = () => { if ( getEnvironmentType(window.location.href) === ENVIRONMENT_TYPE_NOTIFICATION ) { - window.addEventListener('beforeunload', this._beforeUnload) + window.addEventListener('beforeunload', this._beforeUnload); } - } + }; componentWillUnmount = () => { - this._removeBeforeUnload() - } + this._removeBeforeUnload(); + }; _beforeUnload = async (event) => { const { clearConfirmTransaction, cancelEncryptionPublicKey, txData, - } = this.props - const { metricsEvent } = this.context - await cancelEncryptionPublicKey(txData, event) + } = this.props; + const { metricsEvent } = this.context; + await cancelEncryptionPublicKey(txData, event); metricsEvent({ eventOpts: { category: 'Messages', action: 'Encryption public key Request', name: 'Cancel Via Notification Close', }, - }) - clearConfirmTransaction() - } + }); + clearConfirmTransaction(); + }; _removeBeforeUnload = () => { if ( getEnvironmentType(window.location.href) === ENVIRONMENT_TYPE_NOTIFICATION ) { - window.removeEventListener('beforeunload', this._beforeUnload) + window.removeEventListener('beforeunload', this._beforeUnload); } - } + }; renderHeader = () => { return ( @@ -87,12 +87,12 @@ export default class ConfirmEncryptionPublicKey extends Component {
    - ) - } + ); + }; renderAccount = () => { - const { fromAccount } = this.state - const { t } = this.context + const { fromAccount } = this.state; + const { t } = this.context; return (
    @@ -104,15 +104,15 @@ export default class ConfirmEncryptionPublicKey extends Component {
    - ) - } + ); + }; renderBalance = () => { - const { conversionRate } = this.props - const { t } = this.context + const { conversionRate } = this.props; + const { t } = this.context; const { fromAccount: { balance }, - } = this.state + } = this.state; const balanceInEther = conversionUtil(balance, { fromNumericBase: 'hex', @@ -120,7 +120,7 @@ export default class ConfirmEncryptionPublicKey extends Component { fromDenomination: 'WEI', numberOfDecimals: 6, conversionRate, - }) + }); return (
    @@ -131,18 +131,18 @@ export default class ConfirmEncryptionPublicKey extends Component { {`${balanceInEther} ETH`}
    - ) - } + ); + }; renderRequestIcon = () => { - const { requesterAddress } = this.props + const { requesterAddress } = this.props; return (
    - ) - } + ); + }; renderAccountInfo = () => { return ( @@ -151,16 +151,16 @@ export default class ConfirmEncryptionPublicKey extends Component { {this.renderRequestIcon()} {this.renderBalance()} - ) - } + ); + }; renderBody = () => { - const { domainMetadata, txData } = this.props - const { t } = this.context + const { domainMetadata, txData } = this.props; + const { t } = this.context; - const originMetadata = domainMetadata[txData.origin] - const notice = t('encryptionPublicKeyNotice', [txData.origin]) - const name = originMetadata?.name || txData.origin + const originMetadata = domainMetadata[txData.origin]; + const notice = t('encryptionPublicKeyNotice', [txData.origin]); + const name = originMetadata?.name || txData.origin; return (
    @@ -184,8 +184,8 @@ export default class ConfirmEncryptionPublicKey extends Component {
    - ) - } + ); + }; renderFooter = () => { const { @@ -195,8 +195,8 @@ export default class ConfirmEncryptionPublicKey extends Component { history, mostRecentOverviewPage, txData, - } = this.props - const { t, metricsEvent } = this.context + } = this.props; + const { t, metricsEvent } = this.context; return (
    @@ -205,17 +205,17 @@ export default class ConfirmEncryptionPublicKey extends Component { large className="request-encryption-public-key__footer__cancel-button" onClick={async (event) => { - this._removeBeforeUnload() - await cancelEncryptionPublicKey(txData, event) + this._removeBeforeUnload(); + await cancelEncryptionPublicKey(txData, event); metricsEvent({ eventOpts: { category: 'Messages', action: 'Encryption public key Request', name: 'Cancel', }, - }) - clearConfirmTransaction() - history.push(mostRecentOverviewPage) + }); + clearConfirmTransaction(); + history.push(mostRecentOverviewPage); }} > {this.context.t('cancel')} @@ -225,24 +225,24 @@ export default class ConfirmEncryptionPublicKey extends Component { large className="request-encryption-public-key__footer__sign-button" onClick={async (event) => { - this._removeBeforeUnload() - await encryptionPublicKey(txData, event) + this._removeBeforeUnload(); + await encryptionPublicKey(txData, event); this.context.metricsEvent({ eventOpts: { category: 'Messages', action: 'Encryption public key Request', name: 'Confirm', }, - }) - clearConfirmTransaction() - history.push(mostRecentOverviewPage) + }); + clearConfirmTransaction(); + history.push(mostRecentOverviewPage); }} > {t('provide')}
    - ) - } + ); + }; render = () => { return ( @@ -251,6 +251,6 @@ export default class ConfirmEncryptionPublicKey extends Component { {this.renderBody()} {this.renderFooter()} - ) - } + ); + }; } diff --git a/ui/app/pages/confirm-encryption-public-key/confirm-encryption-public-key.container.js b/ui/app/pages/confirm-encryption-public-key/confirm-encryption-public-key.container.js index ea4c156e7..ee8061dcf 100644 --- a/ui/app/pages/confirm-encryption-public-key/confirm-encryption-public-key.container.js +++ b/ui/app/pages/confirm-encryption-public-key/confirm-encryption-public-key.container.js @@ -1,33 +1,33 @@ -import { connect } from 'react-redux' -import { compose } from 'redux' -import { withRouter } from 'react-router-dom' +import { connect } from 'react-redux'; +import { compose } from 'redux'; +import { withRouter } from 'react-router-dom'; import { goHome, encryptionPublicKeyMsg, cancelEncryptionPublicKeyMsg, -} from '../../store/actions' +} from '../../store/actions'; import { conversionRateSelector, getTargetAccountWithSendEtherInfo, -} from '../../selectors' +} from '../../selectors'; -import { clearConfirmTransaction } from '../../ducks/confirm-transaction/confirm-transaction.duck' -import { getMostRecentOverviewPage } from '../../ducks/history/history' -import ConfirmEncryptionPublicKey from './confirm-encryption-public-key.component' +import { clearConfirmTransaction } from '../../ducks/confirm-transaction/confirm-transaction.duck'; +import { getMostRecentOverviewPage } from '../../ducks/history/history'; +import ConfirmEncryptionPublicKey from './confirm-encryption-public-key.component'; function mapStateToProps(state) { const { confirmTransaction, metamask: { domainMetadata = {} }, - } = state + } = state; - const { txData = {} } = confirmTransaction + const { txData = {} } = confirmTransaction; - const { msgParams: from } = txData + const { msgParams: from } = txData; - const fromAccount = getTargetAccountWithSendEtherInfo(state, from) + const fromAccount = getTargetAccountWithSendEtherInfo(state, from); return { txData, @@ -37,7 +37,7 @@ function mapStateToProps(state) { requesterAddress: null, conversionRate: conversionRateSelector(state), mostRecentOverviewPage: getMostRecentOverviewPage(state), - } + }; } function mapDispatchToProps(dispatch) { @@ -45,18 +45,18 @@ function mapDispatchToProps(dispatch) { goHome: () => dispatch(goHome()), clearConfirmTransaction: () => dispatch(clearConfirmTransaction()), encryptionPublicKey: (msgData, event) => { - const params = { data: msgData.msgParams, metamaskId: msgData.id } - event.stopPropagation() - return dispatch(encryptionPublicKeyMsg(params)) + const params = { data: msgData.msgParams, metamaskId: msgData.id }; + event.stopPropagation(); + return dispatch(encryptionPublicKeyMsg(params)); }, cancelEncryptionPublicKey: (msgData, event) => { - event.stopPropagation() - return dispatch(cancelEncryptionPublicKeyMsg(msgData)) + event.stopPropagation(); + return dispatch(cancelEncryptionPublicKeyMsg(msgData)); }, - } + }; } export default compose( withRouter, connect(mapStateToProps, mapDispatchToProps), -)(ConfirmEncryptionPublicKey) +)(ConfirmEncryptionPublicKey); diff --git a/ui/app/pages/confirm-encryption-public-key/index.js b/ui/app/pages/confirm-encryption-public-key/index.js index 9eb370e52..49bb4f367 100644 --- a/ui/app/pages/confirm-encryption-public-key/index.js +++ b/ui/app/pages/confirm-encryption-public-key/index.js @@ -1 +1 @@ -export { default } from './confirm-encryption-public-key.container' +export { default } from './confirm-encryption-public-key.container'; diff --git a/ui/app/pages/confirm-send-ether/confirm-send-ether.component.js b/ui/app/pages/confirm-send-ether/confirm-send-ether.component.js index 6cff21550..cbdbebb91 100644 --- a/ui/app/pages/confirm-send-ether/confirm-send-ether.component.js +++ b/ui/app/pages/confirm-send-ether/confirm-send-ether.component.js @@ -1,32 +1,32 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import ConfirmTransactionBase from '../confirm-transaction-base' -import { SEND_ROUTE } from '../../helpers/constants/routes' +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import ConfirmTransactionBase from '../confirm-transaction-base'; +import { SEND_ROUTE } from '../../helpers/constants/routes'; export default class ConfirmSendEther extends Component { static contextTypes = { t: PropTypes.func, - } + }; static propTypes = { editTransaction: PropTypes.func, history: PropTypes.object, txParams: PropTypes.object, - } + }; handleEdit({ txData }) { - const { editTransaction, history } = this.props - editTransaction(txData) - history.push(SEND_ROUTE) + const { editTransaction, history } = this.props; + editTransaction(txData); + history.push(SEND_ROUTE); } shouldHideData() { - const { txParams = {} } = this.props - return !txParams.data + const { txParams = {} } = this.props; + return !txParams.data; } render() { - const hideData = this.shouldHideData() + const hideData = this.shouldHideData(); return ( - ) + ); } } diff --git a/ui/app/pages/confirm-send-ether/confirm-send-ether.container.js b/ui/app/pages/confirm-send-ether/confirm-send-ether.container.js index 8eca1803f..35f1ccd73 100644 --- a/ui/app/pages/confirm-send-ether/confirm-send-ether.container.js +++ b/ui/app/pages/confirm-send-ether/confirm-send-ether.container.js @@ -1,25 +1,25 @@ -import { connect } from 'react-redux' -import { compose } from 'redux' -import { withRouter } from 'react-router-dom' -import { updateSend } from '../../store/actions' -import { clearConfirmTransaction } from '../../ducks/confirm-transaction/confirm-transaction.duck' -import ConfirmSendEther from './confirm-send-ether.component' +import { connect } from 'react-redux'; +import { compose } from 'redux'; +import { withRouter } from 'react-router-dom'; +import { updateSend } from '../../store/actions'; +import { clearConfirmTransaction } from '../../ducks/confirm-transaction/confirm-transaction.duck'; +import ConfirmSendEther from './confirm-send-ether.component'; const mapStateToProps = (state) => { const { confirmTransaction: { txData: { txParams } = {} }, - } = state + } = state; return { txParams, - } -} + }; +}; const mapDispatchToProps = (dispatch) => { return { editTransaction: (txData) => { - const { id, txParams } = txData - const { from, gas: gasLimit, gasPrice, to, value: amount } = txParams + const { id, txParams } = txData; + const { from, gas: gasLimit, gasPrice, to, value: amount } = txParams; dispatch( updateSend({ @@ -32,14 +32,14 @@ const mapDispatchToProps = (dispatch) => { errors: { to: null, amount: null }, editingTransactionId: id?.toString(), }), - ) + ); - dispatch(clearConfirmTransaction()) + dispatch(clearConfirmTransaction()); }, - } -} + }; +}; export default compose( withRouter, connect(mapStateToProps, mapDispatchToProps), -)(ConfirmSendEther) +)(ConfirmSendEther); diff --git a/ui/app/pages/confirm-send-ether/index.js b/ui/app/pages/confirm-send-ether/index.js index 2d5767c39..eba4b48b1 100644 --- a/ui/app/pages/confirm-send-ether/index.js +++ b/ui/app/pages/confirm-send-ether/index.js @@ -1 +1 @@ -export { default } from './confirm-send-ether.container' +export { default } from './confirm-send-ether.container'; diff --git a/ui/app/pages/confirm-send-token/confirm-send-token.component.js b/ui/app/pages/confirm-send-token/confirm-send-token.component.js index 3c68e564b..6e040fb06 100644 --- a/ui/app/pages/confirm-send-token/confirm-send-token.component.js +++ b/ui/app/pages/confirm-send-token/confirm-send-token.component.js @@ -1,23 +1,23 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import ConfirmTokenTransactionBaseContainer from '../confirm-token-transaction-base' -import { SEND_ROUTE } from '../../helpers/constants/routes' +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import ConfirmTokenTransactionBaseContainer from '../confirm-token-transaction-base'; +import { SEND_ROUTE } from '../../helpers/constants/routes'; export default class ConfirmSendToken extends Component { static propTypes = { history: PropTypes.object, editTransaction: PropTypes.func, tokenAmount: PropTypes.string, - } + }; handleEdit(confirmTransactionData) { - const { editTransaction, history } = this.props - editTransaction(confirmTransactionData) - history.push(SEND_ROUTE) + const { editTransaction, history } = this.props; + editTransaction(confirmTransactionData); + history.push(SEND_ROUTE); } render() { - const { tokenAmount } = this.props + const { tokenAmount } = this.props; return ( - ) + ); } } diff --git a/ui/app/pages/confirm-send-token/confirm-send-token.container.js b/ui/app/pages/confirm-send-token/confirm-send-token.container.js index 04bb1f7b2..e7514acf9 100644 --- a/ui/app/pages/confirm-send-token/confirm-send-token.container.js +++ b/ui/app/pages/confirm-send-token/confirm-send-token.container.js @@ -1,23 +1,23 @@ -import { connect } from 'react-redux' -import { compose } from 'redux' -import { withRouter } from 'react-router-dom' -import { clearConfirmTransaction } from '../../ducks/confirm-transaction/confirm-transaction.duck' -import { updateSend, showSendTokenPage } from '../../store/actions' -import { conversionUtil } from '../../helpers/utils/conversion-util' +import { connect } from 'react-redux'; +import { compose } from 'redux'; +import { withRouter } from 'react-router-dom'; +import { clearConfirmTransaction } from '../../ducks/confirm-transaction/confirm-transaction.duck'; +import { updateSend, showSendTokenPage } from '../../store/actions'; +import { conversionUtil } from '../../helpers/utils/conversion-util'; import { getTokenValueParam, getTokenAddressParam, -} from '../../helpers/utils/token-util' -import { sendTokenTokenAmountAndToAddressSelector } from '../../selectors' -import ConfirmSendToken from './confirm-send-token.component' +} from '../../helpers/utils/token-util'; +import { sendTokenTokenAmountAndToAddressSelector } from '../../selectors'; +import ConfirmSendToken from './confirm-send-token.component'; const mapStateToProps = (state) => { - const { tokenAmount } = sendTokenTokenAmountAndToAddressSelector(state) + const { tokenAmount } = sendTokenTokenAmountAndToAddressSelector(state); return { tokenAmount, - } -} + }; +}; const mapDispatchToProps = (dispatch) => { return { @@ -25,15 +25,15 @@ const mapDispatchToProps = (dispatch) => { const { id, txParams: { from, to: tokenAddress, gas: gasLimit, gasPrice } = {}, - } = txData + } = txData; - const to = getTokenValueParam(tokenData) - const tokenAmountInDec = getTokenAddressParam(tokenData) + const to = getTokenValueParam(tokenData); + const tokenAmountInDec = getTokenAddressParam(tokenData); const tokenAmountInHex = conversionUtil(tokenAmountInDec, { fromNumericBase: 'dec', toNumericBase: 'hex', - }) + }); dispatch( updateSend({ @@ -50,14 +50,14 @@ const mapDispatchToProps = (dispatch) => { address: tokenAddress, }, }), - ) - dispatch(clearConfirmTransaction()) - dispatch(showSendTokenPage()) + ); + dispatch(clearConfirmTransaction()); + dispatch(showSendTokenPage()); }, - } -} + }; +}; export default compose( withRouter, connect(mapStateToProps, mapDispatchToProps), -)(ConfirmSendToken) +)(ConfirmSendToken); diff --git a/ui/app/pages/confirm-send-token/index.js b/ui/app/pages/confirm-send-token/index.js index 409b6ef3d..25067ca43 100644 --- a/ui/app/pages/confirm-send-token/index.js +++ b/ui/app/pages/confirm-send-token/index.js @@ -1 +1 @@ -export { default } from './confirm-send-token.container' +export { default } from './confirm-send-token.container'; diff --git a/ui/app/pages/confirm-token-transaction-base/confirm-token-transaction-base.component.js b/ui/app/pages/confirm-token-transaction-base/confirm-token-transaction-base.component.js index e8bb69152..a03cee3ef 100644 --- a/ui/app/pages/confirm-token-transaction-base/confirm-token-transaction-base.component.js +++ b/ui/app/pages/confirm-token-transaction-base/confirm-token-transaction-base.component.js @@ -1,17 +1,17 @@ -import React, { useContext, useMemo } from 'react' -import PropTypes from 'prop-types' -import BigNumber from 'bignumber.js' -import { I18nContext } from '../../contexts/i18n' -import ConfirmTransactionBase from '../confirm-transaction-base' -import UserPreferencedCurrencyDisplay from '../../components/app/user-preferenced-currency-display' +import React, { useContext, useMemo } from 'react'; +import PropTypes from 'prop-types'; +import BigNumber from 'bignumber.js'; +import { I18nContext } from '../../contexts/i18n'; +import ConfirmTransactionBase from '../confirm-transaction-base'; +import UserPreferencedCurrencyDisplay from '../../components/app/user-preferenced-currency-display'; import { formatCurrency, convertTokenToFiat, addFiat, roundExponential, -} from '../../helpers/utils/confirm-tx.util' -import { getWeiHexFromDecimalValue } from '../../helpers/utils/conversions.util' -import { ETH, PRIMARY } from '../../helpers/constants/common' +} from '../../helpers/utils/confirm-tx.util'; +import { getWeiHexFromDecimalValue } from '../../helpers/utils/conversions.util'; +import { ETH, PRIMARY } from '../../helpers/constants/common'; export default function ConfirmTokenTransactionBase({ toAddress, @@ -24,27 +24,27 @@ export default function ConfirmTokenTransactionBase({ conversionRate, currentCurrency, }) { - const t = useContext(I18nContext) + const t = useContext(I18nContext); const hexWeiValue = useMemo(() => { if (tokenAmount === '0' || !contractExchangeRate) { - return '0' + return '0'; } const decimalEthValue = new BigNumber(tokenAmount) .times(new BigNumber(contractExchangeRate)) - .toFixed() + .toFixed(); return getWeiHexFromDecimalValue({ value: decimalEthValue, fromCurrency: ETH, fromDenomination: ETH, - }) - }, [tokenAmount, contractExchangeRate]) + }); + }, [tokenAmount, contractExchangeRate]); const secondaryTotalTextOverride = useMemo(() => { if (typeof contractExchangeRate === 'undefined') { - return formatCurrency(fiatTransactionTotal, currentCurrency) + return formatCurrency(fiatTransactionTotal, currentCurrency); } const fiatTransactionAmount = convertTokenToFiat({ @@ -52,19 +52,19 @@ export default function ConfirmTokenTransactionBase({ toCurrency: currentCurrency, conversionRate, contractExchangeRate, - }) - const fiatTotal = addFiat(fiatTransactionAmount, fiatTransactionTotal) - const roundedFiatTotal = roundExponential(fiatTotal) - return formatCurrency(roundedFiatTotal, currentCurrency) + }); + const fiatTotal = addFiat(fiatTransactionAmount, fiatTransactionTotal); + const roundedFiatTotal = roundExponential(fiatTotal); + return formatCurrency(roundedFiatTotal, currentCurrency); }, [ currentCurrency, conversionRate, contractExchangeRate, fiatTransactionTotal, tokenAmount, - ]) + ]); - const tokensText = `${tokenAmount} ${tokenSymbol}` + const tokensText = `${tokenAmount} ${tokenSymbol}`; return ( - ) + ); } ConfirmTokenTransactionBase.propTypes = { @@ -105,4 +105,4 @@ ConfirmTokenTransactionBase.propTypes = { contractExchangeRate: PropTypes.number, conversionRate: PropTypes.number, currentCurrency: PropTypes.string, -} +}; diff --git a/ui/app/pages/confirm-token-transaction-base/confirm-token-transaction-base.container.js b/ui/app/pages/confirm-token-transaction-base/confirm-token-transaction-base.container.js index 5c01aa9bd..2d7bbde85 100644 --- a/ui/app/pages/confirm-token-transaction-base/confirm-token-transaction-base.container.js +++ b/ui/app/pages/confirm-token-transaction-base/confirm-token-transaction-base.container.js @@ -1,55 +1,55 @@ -import { connect } from 'react-redux' -import { compose } from 'redux' -import { withRouter } from 'react-router-dom' +import { connect } from 'react-redux'; +import { compose } from 'redux'; +import { withRouter } from 'react-router-dom'; import { contractExchangeRateSelector, transactionFeeSelector, -} from '../../selectors' -import { getTokens } from '../../ducks/metamask/metamask' -import { getTokenData } from '../../helpers/utils/transactions.util' +} from '../../selectors'; +import { getTokens } from '../../ducks/metamask/metamask'; +import { getTokenData } from '../../helpers/utils/transactions.util'; import { calcTokenAmount, getTokenAddressParam, getTokenValueParam, -} from '../../helpers/utils/token-util' -import ConfirmTokenTransactionBase from './confirm-token-transaction-base.component' +} from '../../helpers/utils/token-util'; +import ConfirmTokenTransactionBase from './confirm-token-transaction-base.component'; const mapStateToProps = (state, ownProps) => { const { match: { params = {} }, - } = ownProps - const { id: paramsTransactionId } = params + } = ownProps; + const { id: paramsTransactionId } = params; const { confirmTransaction, metamask: { currentCurrency, conversionRate, currentNetworkTxList }, - } = state + } = state; const { txData: { id: transactionId, txParams: { to: tokenAddress, data } = {}, } = {}, - } = confirmTransaction + } = confirmTransaction; const transaction = currentNetworkTxList.find( ({ id }) => id === (Number(paramsTransactionId) || transactionId), - ) || {} + ) || {}; const { ethTransactionTotal, fiatTransactionTotal } = transactionFeeSelector( state, transaction, - ) - const tokens = getTokens(state) - const currentToken = tokens?.find(({ address }) => tokenAddress === address) - const { decimals, symbol: tokenSymbol } = currentToken || {} + ); + const tokens = getTokens(state); + const currentToken = tokens?.find(({ address }) => tokenAddress === address); + const { decimals, symbol: tokenSymbol } = currentToken || {}; - const tokenData = getTokenData(data) - const tokenValue = getTokenValueParam(tokenData) - const toAddress = getTokenAddressParam(tokenData) + const tokenData = getTokenData(data); + const tokenValue = getTokenValueParam(tokenData); + const toAddress = getTokenAddressParam(tokenData); const tokenAmount = - tokenData && calcTokenAmount(tokenValue, decimals).toFixed() - const contractExchangeRate = contractExchangeRateSelector(state) + tokenData && calcTokenAmount(tokenValue, decimals).toFixed(); + const contractExchangeRate = contractExchangeRateSelector(state); return { toAddress, @@ -61,10 +61,10 @@ const mapStateToProps = (state, ownProps) => { contractExchangeRate, fiatTransactionTotal, ethTransactionTotal, - } -} + }; +}; export default compose( withRouter, connect(mapStateToProps), -)(ConfirmTokenTransactionBase) +)(ConfirmTokenTransactionBase); diff --git a/ui/app/pages/confirm-token-transaction-base/index.js b/ui/app/pages/confirm-token-transaction-base/index.js index e15c5d56b..e5b6df031 100644 --- a/ui/app/pages/confirm-token-transaction-base/index.js +++ b/ui/app/pages/confirm-token-transaction-base/index.js @@ -1,2 +1,2 @@ -export { default } from './confirm-token-transaction-base.container' -export { default as ConfirmTokenTransactionBase } from './confirm-token-transaction-base.component' +export { default } from './confirm-token-transaction-base.container'; +export { default as ConfirmTokenTransactionBase } from './confirm-token-transaction-base.component'; diff --git a/ui/app/pages/confirm-transaction-base/confirm-transaction-base.component.js b/ui/app/pages/confirm-transaction-base/confirm-transaction-base.component.js index eeec5a5cd..5d09b3198 100644 --- a/ui/app/pages/confirm-transaction-base/confirm-transaction-base.component.js +++ b/ui/app/pages/confirm-transaction-base/confirm-transaction-base.component.js @@ -1,33 +1,33 @@ -import ethUtil from 'ethereumjs-util' -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import { ENVIRONMENT_TYPE_NOTIFICATION } from '../../../../shared/constants/app' -import { getEnvironmentType } from '../../../../app/scripts/lib/util' +import ethUtil from 'ethereumjs-util'; +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import { ENVIRONMENT_TYPE_NOTIFICATION } from '../../../../shared/constants/app'; +import { getEnvironmentType } from '../../../../app/scripts/lib/util'; import ConfirmPageContainer, { ConfirmDetailRow, -} from '../../components/app/confirm-page-container' -import { isBalanceSufficient } from '../send/send.utils' -import { CONFIRM_TRANSACTION_ROUTE } from '../../helpers/constants/routes' +} from '../../components/app/confirm-page-container'; +import { isBalanceSufficient } from '../send/send.utils'; +import { CONFIRM_TRANSACTION_ROUTE } from '../../helpers/constants/routes'; import { INSUFFICIENT_FUNDS_ERROR_KEY, TRANSACTION_ERROR_KEY, GAS_LIMIT_TOO_LOW_ERROR_KEY, -} from '../../helpers/constants/error-keys' -import UserPreferencedCurrencyDisplay from '../../components/app/user-preferenced-currency-display' -import { PRIMARY, SECONDARY } from '../../helpers/constants/common' -import { hexToDecimal } from '../../helpers/utils/conversions.util' -import AdvancedGasInputs from '../../components/app/gas-customization/advanced-gas-inputs' -import TextField from '../../components/ui/text-field' +} from '../../helpers/constants/error-keys'; +import UserPreferencedCurrencyDisplay from '../../components/app/user-preferenced-currency-display'; +import { PRIMARY, SECONDARY } from '../../helpers/constants/common'; +import { hexToDecimal } from '../../helpers/utils/conversions.util'; +import AdvancedGasInputs from '../../components/app/gas-customization/advanced-gas-inputs'; +import TextField from '../../components/ui/text-field'; import { TRANSACTION_CATEGORIES, TRANSACTION_STATUSES, -} from '../../../../shared/constants/transaction' +} from '../../../../shared/constants/transaction'; export default class ConfirmTransactionBase extends Component { static contextTypes = { t: PropTypes.func, metricsEvent: PropTypes.func, - } + }; static propTypes = { // react-router props @@ -94,13 +94,13 @@ export default class ConfirmTransactionBase extends Component { showAccountInHeader: PropTypes.bool, mostRecentOverviewPage: PropTypes.string.isRequired, isMainnet: PropTypes.bool, - } + }; state = { submitting: false, submitError: null, submitWarning: '', - } + }; componentDidUpdate(prevProps) { const { @@ -113,17 +113,17 @@ export default class ConfirmTransactionBase extends Component { customNonceValue, toAddress, tryReverseResolveAddress, - } = this.props + } = this.props; const { customNonceValue: prevCustomNonceValue, nextNonce: prevNextNonce, toAddress: prevToAddress, transactionStatus: prevTxStatus, - } = prevProps - const statusUpdated = transactionStatus !== prevTxStatus + } = prevProps; + const statusUpdated = transactionStatus !== prevTxStatus; const txDroppedOrConfirmed = transactionStatus === TRANSACTION_STATUSES.DROPPED || - transactionStatus === TRANSACTION_STATUSES.CONFIRMED + transactionStatus === TRANSACTION_STATUSES.CONFIRMED; if ( nextNonce !== prevNextNonce || @@ -132,23 +132,23 @@ export default class ConfirmTransactionBase extends Component { if (nextNonce !== null && customNonceValue > nextNonce) { this.setState({ submitWarning: this.context.t('nextNonceWarning', [nextNonce]), - }) + }); } else { - this.setState({ submitWarning: '' }) + this.setState({ submitWarning: '' }); } } if (statusUpdated && txDroppedOrConfirmed) { showTransactionConfirmedModal({ onSubmit: () => { - clearConfirmTransaction() - history.push(mostRecentOverviewPage) + clearConfirmTransaction(); + history.push(mostRecentOverviewPage); }, - }) + }); } if (toAddress && toAddress !== prevToAddress) { - tryReverseResolveAddress(toAddress) + tryReverseResolveAddress(toAddress); } } @@ -159,7 +159,7 @@ export default class ConfirmTransactionBase extends Component { hexTransactionFee, txData: { simulationFails, txParams: { value: amount } = {} } = {}, customGas, - } = this.props + } = this.props; const insufficientBalance = balance && @@ -168,20 +168,20 @@ export default class ConfirmTransactionBase extends Component { gasTotal: hexTransactionFee || '0x0', balance, conversionRate, - }) + }); if (insufficientBalance) { return { valid: false, errorKey: INSUFFICIENT_FUNDS_ERROR_KEY, - } + }; } if (hexToDecimal(customGas.gasLimit) < 21000) { return { valid: false, errorKey: GAS_LIMIT_TOO_LOW_ERROR_KEY, - } + }; } if (simulationFails) { @@ -190,12 +190,12 @@ export default class ConfirmTransactionBase extends Component { errorKey: simulationFails.errorKey ? simulationFails.errorKey : TRANSACTION_ERROR_KEY, - } + }; } return { valid: true, - } + }; } handleEditGas() { @@ -204,7 +204,7 @@ export default class ConfirmTransactionBase extends Component { actionKey, txData: { origin }, methodData = {}, - } = this.props + } = this.props; this.context.metricsEvent({ eventOpts: { @@ -220,9 +220,9 @@ export default class ConfirmTransactionBase extends Component { TRANSACTION_CATEGORIES.CONTRACT_INTERACTION, origin, }, - }) + }); - showCustomizeGasModal() + showCustomizeGasModal(); } renderDetails() { @@ -242,9 +242,9 @@ export default class ConfirmTransactionBase extends Component { nextNonce, getNextNonce, isMainnet, - } = this.props + } = this.props; - const notMainnetOrTest = !(isMainnet || process.env.IN_TEST) + const notMainnetOrTest = !(isMainnet || process.env.IN_TEST); return (
    @@ -313,11 +313,11 @@ export default class ConfirmTransactionBase extends Component { } onChange={({ target: { value } }) => { if (!value.length || Number(value) < 0) { - updateCustomNonce('') + updateCustomNonce(''); } else { - updateCustomNonce(String(Math.floor(value))) + updateCustomNonce(String(Math.floor(value))); } - getNextNonce() + getNextNonce(); }} fullWidth margin="dense" @@ -328,20 +328,20 @@ export default class ConfirmTransactionBase extends Component {
    ) : null} - ) + ); } renderData(functionType) { - const { t } = this.context + const { t } = this.context; const { txData: { txParams: { data } = {} } = {}, methodData: { params } = {}, hideData, dataComponent, - } = this.props + } = this.props; if (hideData) { - return null + return null; } return ( @@ -369,7 +369,7 @@ export default class ConfirmTransactionBase extends Component {
    {data}
    ) - ) + ); } handleEdit() { @@ -381,7 +381,7 @@ export default class ConfirmTransactionBase extends Component { actionKey, txData: { origin }, methodData = {}, - } = this.props + } = this.props; this.context.metricsEvent({ eventOpts: { @@ -397,9 +397,9 @@ export default class ConfirmTransactionBase extends Component { TRANSACTION_CATEGORIES.CONTRACT_INTERACTION, origin, }, - }) + }); - onEdit({ txData, tokenData, tokenProps }) + onEdit({ txData, tokenData, tokenProps }); } handleCancelAll() { @@ -410,21 +410,21 @@ export default class ConfirmTransactionBase extends Component { mostRecentOverviewPage, showRejectTransactionsConfirmationModal, unapprovedTxCount, - } = this.props + } = this.props; showRejectTransactionsConfirmationModal({ unapprovedTxCount, onSubmit: async () => { - this._removeBeforeUnload() - await cancelAllTransactions() - clearConfirmTransaction() - history.push(mostRecentOverviewPage) + this._removeBeforeUnload(); + await cancelAllTransactions(); + clearConfirmTransaction(); + history.push(mostRecentOverviewPage); }, - }) + }); } handleCancel() { - const { metricsEvent } = this.context + const { metricsEvent } = this.context; const { txData, cancelTransaction, @@ -435,9 +435,9 @@ export default class ConfirmTransactionBase extends Component { txData: { origin }, methodData = {}, updateCustomNonce, - } = this.props + } = this.props; - this._removeBeforeUnload() + this._removeBeforeUnload(); metricsEvent({ eventOpts: { category: 'Transactions', @@ -452,16 +452,16 @@ export default class ConfirmTransactionBase extends Component { TRANSACTION_CATEGORIES.CONTRACT_INTERACTION, origin, }, - }) - updateCustomNonce('') + }); + updateCustomNonce(''); cancelTransaction(txData).then(() => { - clearConfirmTransaction() - history.push(mostRecentOverviewPage) - }) + clearConfirmTransaction(); + history.push(mostRecentOverviewPage); + }); } handleSubmit() { - const { metricsEvent } = this.context + const { metricsEvent } = this.context; const { txData: { origin }, sendTransaction, @@ -474,11 +474,11 @@ export default class ConfirmTransactionBase extends Component { setMetaMetricsSendCount, methodData = {}, updateCustomNonce, - } = this.props - const { submitting } = this.state + } = this.props; + const { submitting } = this.state; if (submitting) { - return + return; } this.setState( @@ -487,7 +487,7 @@ export default class ConfirmTransactionBase extends Component { submitError: null, }, () => { - this._removeBeforeUnload() + this._removeBeforeUnload(); metricsEvent({ eventOpts: { category: 'Transactions', @@ -502,40 +502,40 @@ export default class ConfirmTransactionBase extends Component { TRANSACTION_CATEGORIES.CONTRACT_INTERACTION, origin, }, - }) + }); setMetaMetricsSendCount(metaMetricsSendCount + 1).then(() => { sendTransaction(txData) .then(() => { - clearConfirmTransaction() + clearConfirmTransaction(); this.setState( { submitting: false, }, () => { - history.push(mostRecentOverviewPage) - updateCustomNonce('') + history.push(mostRecentOverviewPage); + updateCustomNonce(''); }, - ) + ); }) .catch((error) => { this.setState({ submitting: false, submitError: error.message, - }) - updateCustomNonce('') - }) - }) + }); + updateCustomNonce(''); + }); + }); }, - ) + ); } renderTitleComponent() { - const { title, hexTransactionAmount } = this.props + const { title, hexTransactionAmount } = this.props; // Title string passed in by props takes priority if (title) { - return null + return null; } return ( @@ -546,11 +546,11 @@ export default class ConfirmTransactionBase extends Component { ethLogoHeight="26" hideLabel /> - ) + ); } renderSubtitleComponent() { - const { subtitleComponent, hexTransactionAmount } = this.props + const { subtitleComponent, hexTransactionAmount } = this.props; return ( subtitleComponent || ( @@ -561,22 +561,22 @@ export default class ConfirmTransactionBase extends Component { hideLabel /> ) - ) + ); } handleNextTx(txId) { - const { history, clearConfirmTransaction } = this.props + const { history, clearConfirmTransaction } = this.props; if (txId) { - clearConfirmTransaction() - history.push(`${CONFIRM_TRANSACTION_ROUTE}/${txId}`) + clearConfirmTransaction(); + history.push(`${CONFIRM_TRANSACTION_ROUTE}/${txId}`); } } getNavigateTxData() { - const { currentNetworkUnapprovedTxs, txData: { id } = {} } = this.props - const enumUnapprovedTxs = Object.keys(currentNetworkUnapprovedTxs) - const currentPosition = enumUnapprovedTxs.indexOf(id ? id.toString() : '') + const { currentNetworkUnapprovedTxs, txData: { id } = {} } = this.props; + const enumUnapprovedTxs = Object.keys(currentNetworkUnapprovedTxs); + const currentPosition = enumUnapprovedTxs.indexOf(id ? id.toString() : ''); return { totalTx: enumUnapprovedTxs.length, @@ -588,12 +588,12 @@ export default class ConfirmTransactionBase extends Component { lastTx: enumUnapprovedTxs[enumUnapprovedTxs.length - 1], ofText: this.context.t('ofTextNofM'), requestsWaitingText: this.context.t('requestsAwaitingAcknowledgement'), - } + }; } _beforeUnload = () => { - const { txData: { origin, id } = {}, cancelTransaction } = this.props - const { metricsEvent } = this.context + const { txData: { origin, id } = {}, cancelTransaction } = this.props; + const { metricsEvent } = this.context; metricsEvent({ eventOpts: { category: 'Transactions', @@ -603,15 +603,15 @@ export default class ConfirmTransactionBase extends Component { customVariables: { origin, }, - }) - cancelTransaction({ id }) - } + }); + cancelTransaction({ id }); + }; _removeBeforeUnload = () => { if (getEnvironmentType() === ENVIRONMENT_TYPE_NOTIFICATION) { - window.removeEventListener('beforeunload', this._beforeUnload) + window.removeEventListener('beforeunload', this._beforeUnload); } - } + }; componentDidMount() { const { @@ -619,8 +619,8 @@ export default class ConfirmTransactionBase extends Component { txData: { origin } = {}, getNextNonce, tryReverseResolveAddress, - } = this.props - const { metricsEvent } = this.context + } = this.props; + const { metricsEvent } = this.context; metricsEvent({ eventOpts: { category: 'Transactions', @@ -630,24 +630,24 @@ export default class ConfirmTransactionBase extends Component { customVariables: { origin, }, - }) + }); if (getEnvironmentType() === ENVIRONMENT_TYPE_NOTIFICATION) { - window.addEventListener('beforeunload', this._beforeUnload) + window.addEventListener('beforeunload', this._beforeUnload); } - getNextNonce() + getNextNonce(); if (toAddress) { - tryReverseResolveAddress(toAddress) + tryReverseResolveAddress(toAddress); } } componentWillUnmount() { - this._removeBeforeUnload() + this._removeBeforeUnload(); } render() { - const { t } = this.context + const { t } = this.context; const { isTxReprice, fromName, @@ -670,11 +670,11 @@ export default class ConfirmTransactionBase extends Component { hideSenderToRecipient, showAccountInHeader, txData, - } = this.props - const { submitting, submitError, submitWarning } = this.state + } = this.props; + const { submitting, submitError, submitWarning } = this.state; - const { name } = methodData - const { valid, errorKey } = this.getErrorKey() + const { name } = methodData; + const { valid, errorKey } = this.getErrorKey(); const { totalTx, positionOfCurrentTx, @@ -685,14 +685,14 @@ export default class ConfirmTransactionBase extends Component { lastTx, ofText, requestsWaitingText, - } = this.getNavigateTxData() + } = this.getNavigateTxData(); - let functionType = getMethodName(name) + let functionType = getMethodName(name); if (!functionType) { if (transactionCategory) { - functionType = t(transactionCategory) || transactionCategory + functionType = t(transactionCategory) || transactionCategory; } else { - functionType = t('contractInteraction') + functionType = t('contractInteraction'); } } @@ -739,17 +739,17 @@ export default class ConfirmTransactionBase extends Component { hideSenderToRecipient={hideSenderToRecipient} origin={txData.origin} /> - ) + ); } } export function getMethodName(camelCase) { if (!camelCase || typeof camelCase !== 'string') { - return '' + return ''; } return camelCase .replace(/([a-z])([A-Z])/gu, '$1 $2') .replace(/([A-Z])([a-z])/gu, ' $1$2') - .replace(/ +/gu, ' ') + .replace(/ +/gu, ' '); } diff --git a/ui/app/pages/confirm-transaction-base/confirm-transaction-base.container.js b/ui/app/pages/confirm-transaction-base/confirm-transaction-base.container.js index 09cece00e..0875f8892 100644 --- a/ui/app/pages/confirm-transaction-base/confirm-transaction-base.container.js +++ b/ui/app/pages/confirm-transaction-base/confirm-transaction-base.container.js @@ -1,8 +1,8 @@ -import { connect } from 'react-redux' -import { compose } from 'redux' -import { withRouter } from 'react-router-dom' -import contractMap from '@metamask/contract-metadata' -import { clearConfirmTransaction } from '../../ducks/confirm-transaction/confirm-transaction.duck' +import { connect } from 'react-redux'; +import { compose } from 'redux'; +import { withRouter } from 'react-router-dom'; +import contractMap from '@metamask/contract-metadata'; +import { clearConfirmTransaction } from '../../ducks/confirm-transaction/confirm-transaction.duck'; import { updateCustomNonce, @@ -14,20 +14,20 @@ import { updateTransaction, getNextNonce, tryReverseResolveAddress, -} from '../../store/actions' +} from '../../store/actions'; import { INSUFFICIENT_FUNDS_ERROR_KEY, GAS_LIMIT_TOO_LOW_ERROR_KEY, -} from '../../helpers/constants/error-keys' -import { getHexGasTotal } from '../../helpers/utils/confirm-tx.util' -import { isBalanceSufficient, calcGasTotal } from '../send/send.utils' -import { conversionGreaterThan } from '../../helpers/utils/conversion-util' -import { MIN_GAS_LIMIT_DEC } from '../send/send.constants' +} from '../../helpers/constants/error-keys'; +import { getHexGasTotal } from '../../helpers/utils/confirm-tx.util'; +import { isBalanceSufficient, calcGasTotal } from '../send/send.utils'; +import { conversionGreaterThan } from '../../helpers/utils/conversion-util'; +import { MIN_GAS_LIMIT_DEC } from '../send/send.constants'; import { checksumAddress, shortenAddress, valuesFor, -} from '../../helpers/utils/util' +} from '../../helpers/utils/util'; import { getAdvancedInlineGasShown, getCustomNonceValue, @@ -37,36 +37,36 @@ import { getUseNonceField, getPreferences, transactionFeeSelector, -} from '../../selectors' -import { getMostRecentOverviewPage } from '../../ducks/history/history' -import ConfirmTransactionBase from './confirm-transaction-base.component' +} from '../../selectors'; +import { getMostRecentOverviewPage } from '../../ducks/history/history'; +import ConfirmTransactionBase from './confirm-transaction-base.component'; const casedContractMap = Object.keys(contractMap).reduce((acc, base) => { return { ...acc, [base.toLowerCase()]: contractMap[base], - } -}, {}) + }; +}, {}); -let customNonceValue = '' +let customNonceValue = ''; const customNonceMerge = (txData) => customNonceValue ? { ...txData, customNonceValue, } - : txData + : txData; const mapStateToProps = (state, ownProps) => { const { toAddress: propsToAddress, customTxParamsData, match: { params = {} }, - } = ownProps - const { id: paramsTransactionId } = params - const { showFiatInTestnets } = getPreferences(state) - const isMainnet = getIsMainnet(state) - const { confirmTransaction, metamask } = state + } = ownProps; + const { id: paramsTransactionId } = params; + const { showFiatInTestnets } = getPreferences(state); + const isMainnet = getIsMainnet(state); + const { confirmTransaction, metamask } = state; const { ensResolutionsByAddress, conversionRate, @@ -77,18 +77,18 @@ const mapStateToProps = (state, ownProps) => { unapprovedTxs, metaMetricsSendCount, nextNonce, - } = metamask - const { tokenData, txData, tokenProps, nonce } = confirmTransaction + } = metamask; + const { tokenData, txData, tokenProps, nonce } = confirmTransaction; const { txParams = {}, lastGasPrice, id: transactionId, transactionCategory, - } = txData + } = txData; const transaction = Object.values(unapprovedTxs).find( ({ id }) => id === (transactionId || Number(paramsTransactionId)), - ) || {} + ) || {}; const { from: fromAddress, to: txParamsToAddress, @@ -96,51 +96,51 @@ const mapStateToProps = (state, ownProps) => { gas: gasLimit, value: amount, data, - } = (transaction && transaction.txParams) || txParams - const accounts = getMetaMaskAccounts(state) - const assetImage = assetImages[txParamsToAddress] + } = (transaction && transaction.txParams) || txParams; + const accounts = getMetaMaskAccounts(state); + const assetImage = assetImages[txParamsToAddress]; - const { balance } = accounts[fromAddress] - const { name: fromName } = identities[fromAddress] - const toAddress = propsToAddress || txParamsToAddress + const { balance } = accounts[fromAddress]; + const { name: fromName } = identities[fromAddress]; + const toAddress = propsToAddress || txParamsToAddress; const toName = identities[toAddress]?.name || casedContractMap[toAddress]?.name || - shortenAddress(checksumAddress(toAddress)) + shortenAddress(checksumAddress(toAddress)); - const checksummedAddress = checksumAddress(toAddress) - const addressBookObject = addressBook[checksummedAddress] - const toEns = ensResolutionsByAddress[checksummedAddress] || '' - const toNickname = addressBookObject ? addressBookObject.name : '' - const isTxReprice = Boolean(lastGasPrice) - const transactionStatus = transaction ? transaction.status : '' + const checksummedAddress = checksumAddress(toAddress); + const addressBookObject = addressBook[checksummedAddress]; + const toEns = ensResolutionsByAddress[checksummedAddress] || ''; + const toNickname = addressBookObject ? addressBookObject.name : ''; + const isTxReprice = Boolean(lastGasPrice); + const transactionStatus = transaction ? transaction.status : ''; const { hexTransactionAmount, hexTransactionFee, hexTransactionTotal, - } = transactionFeeSelector(state, transaction) + } = transactionFeeSelector(state, transaction); if (transaction && transaction.simulationFails) { - txData.simulationFails = transaction.simulationFails + txData.simulationFails = transaction.simulationFails; } const currentNetworkUnapprovedTxs = Object.keys(unapprovedTxs) .filter((key) => unapprovedTxs[key].metamaskNetworkId === network) - .reduce((acc, key) => ({ ...acc, [key]: unapprovedTxs[key] }), {}) - const unapprovedTxCount = valuesFor(currentNetworkUnapprovedTxs).length + .reduce((acc, key) => ({ ...acc, [key]: unapprovedTxs[key] }), {}); + const unapprovedTxCount = valuesFor(currentNetworkUnapprovedTxs).length; const insufficientBalance = !isBalanceSufficient({ amount, gasTotal: calcGasTotal(gasLimit, gasPrice), balance, conversionRate, - }) + }); - const methodData = getKnownMethodData(state, data) || {} + const methodData = getKnownMethodData(state, data) || {}; - let fullTxData = { ...txData, ...transaction } + let fullTxData = { ...txData, ...transaction }; if (customTxParamsData) { fullTxData = { ...fullTxData, @@ -148,7 +148,7 @@ const mapStateToProps = (state, ownProps) => { ...fullTxData.txParams, data: customTxParamsData, }, - } + }; } return { @@ -189,29 +189,29 @@ const mapStateToProps = (state, ownProps) => { nextNonce, mostRecentOverviewPage: getMostRecentOverviewPage(state), isMainnet, - } -} + }; +}; export const mapDispatchToProps = (dispatch) => { return { tryReverseResolveAddress: (address) => { - return dispatch(tryReverseResolveAddress(address)) + return dispatch(tryReverseResolveAddress(address)); }, updateCustomNonce: (value) => { - customNonceValue = value - dispatch(updateCustomNonce(value)) + customNonceValue = value; + dispatch(updateCustomNonce(value)); }, clearConfirmTransaction: () => dispatch(clearConfirmTransaction()), showTransactionConfirmedModal: ({ onSubmit }) => { - return dispatch(showModal({ name: 'TRANSACTION_CONFIRMED', onSubmit })) + return dispatch(showModal({ name: 'TRANSACTION_CONFIRMED', onSubmit })); }, showCustomizeGasModal: ({ txData, onSubmit, validate }) => { return dispatch( showModal({ name: 'CUSTOMIZE_GAS', txData, onSubmit, validate }), - ) + ); }, updateGasAndCalculate: (updatedTx) => { - return dispatch(updateTransaction(updatedTx)) + return dispatch(updateTransaction(updatedTx)); }, showRejectTransactionsConfirmationModal: ({ onSubmit, @@ -219,7 +219,7 @@ export const mapDispatchToProps = (dispatch) => { }) => { return dispatch( showModal({ name: 'REJECT_TRANSACTIONS', onSubmit, unapprovedTxCount }), - ) + ); }, cancelTransaction: ({ id }) => dispatch(cancelTx({ id })), cancelAllTransactions: (txList) => dispatch(cancelTxs(txList)), @@ -227,26 +227,26 @@ export const mapDispatchToProps = (dispatch) => { dispatch(updateAndApproveTx(customNonceMerge(txData))), setMetaMetricsSendCount: (val) => dispatch(setMetaMetricsSendCount(val)), getNextNonce: () => dispatch(getNextNonce()), - } -} + }; +}; const getValidateEditGas = ({ balance, conversionRate, txData }) => { - const { txParams: { value: amount } = {} } = txData + const { txParams: { value: amount } = {} } = txData; return ({ gasLimit, gasPrice }) => { - const gasTotal = getHexGasTotal({ gasLimit, gasPrice }) + const gasTotal = getHexGasTotal({ gasLimit, gasPrice }); const hasSufficientBalance = isBalanceSufficient({ amount, gasTotal, balance, conversionRate, - }) + }); if (!hasSufficientBalance) { return { valid: false, errorKey: INSUFFICIENT_FUNDS_ERROR_KEY, - } + }; } const gasLimitTooLow = @@ -261,35 +261,35 @@ const getValidateEditGas = ({ balance, conversionRate, txData }) => { value: gasLimit, fromNumericBase: 'hex', }, - ) + ); if (gasLimitTooLow) { return { valid: false, errorKey: GAS_LIMIT_TOO_LOW_ERROR_KEY, - } + }; } return { valid: true, - } - } -} + }; + }; +}; const mergeProps = (stateProps, dispatchProps, ownProps) => { - const { balance, conversionRate, txData, unapprovedTxs } = stateProps + const { balance, conversionRate, txData, unapprovedTxs } = stateProps; const { cancelAllTransactions: dispatchCancelAllTransactions, showCustomizeGasModal: dispatchShowCustomizeGasModal, updateGasAndCalculate: dispatchUpdateGasAndCalculate, ...otherDispatchProps - } = dispatchProps + } = dispatchProps; const validateEditGas = getValidateEditGas({ balance, conversionRate, txData, - }) + }); return { ...stateProps, @@ -311,13 +311,13 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => { gas: gasLimit, gasPrice, }, - } - dispatchUpdateGasAndCalculate(updatedTx) + }; + dispatchUpdateGasAndCalculate(updatedTx); }, - } -} + }; +}; export default compose( withRouter, connect(mapStateToProps, mapDispatchToProps, mergeProps), -)(ConfirmTransactionBase) +)(ConfirmTransactionBase); diff --git a/ui/app/pages/confirm-transaction-base/index.js b/ui/app/pages/confirm-transaction-base/index.js index 9996e9aeb..0ea19b073 100644 --- a/ui/app/pages/confirm-transaction-base/index.js +++ b/ui/app/pages/confirm-transaction-base/index.js @@ -1 +1 @@ -export { default } from './confirm-transaction-base.container' +export { default } from './confirm-transaction-base.container'; diff --git a/ui/app/pages/confirm-transaction-base/tests/confirm-transaction-base.component.test.js b/ui/app/pages/confirm-transaction-base/tests/confirm-transaction-base.component.test.js index 96ddc2ff4..a46d89f95 100644 --- a/ui/app/pages/confirm-transaction-base/tests/confirm-transaction-base.component.test.js +++ b/ui/app/pages/confirm-transaction-base/tests/confirm-transaction-base.component.test.js @@ -1,17 +1,17 @@ -import assert from 'assert' -import { getMethodName } from '../confirm-transaction-base.component' +import assert from 'assert'; +import { getMethodName } from '../confirm-transaction-base.component'; describe('ConfirmTransactionBase Component', function () { describe('getMethodName', function () { it('should get correct method names', function () { - assert.strictEqual(getMethodName(undefined), '') - assert.strictEqual(getMethodName({}), '') - assert.strictEqual(getMethodName('confirm'), 'confirm') - assert.strictEqual(getMethodName('balanceOf'), 'balance Of') + assert.strictEqual(getMethodName(undefined), ''); + assert.strictEqual(getMethodName({}), ''); + assert.strictEqual(getMethodName('confirm'), 'confirm'); + assert.strictEqual(getMethodName('balanceOf'), 'balance Of'); assert.strictEqual( getMethodName('ethToTokenSwapInput'), 'eth To Token Swap Input', - ) - }) - }) -}) + ); + }); + }); +}); diff --git a/ui/app/pages/confirm-transaction-switch/confirm-transaction-switch.component.js b/ui/app/pages/confirm-transaction-switch/confirm-transaction-switch.component.js index 0de4f2951..18969e233 100644 --- a/ui/app/pages/confirm-transaction-switch/confirm-transaction-switch.component.js +++ b/ui/app/pages/confirm-transaction-switch/confirm-transaction-switch.component.js @@ -1,7 +1,7 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import { Redirect } from 'react-router-dom' -import Loading from '../../components/ui/loading-screen' +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import { Redirect } from 'react-router-dom'; +import Loading from '../../components/ui/loading-screen'; import { CONFIRM_TRANSACTION_ROUTE, CONFIRM_DEPLOY_CONTRACT_PATH, @@ -13,68 +13,68 @@ import { SIGNATURE_REQUEST_PATH, DECRYPT_MESSAGE_REQUEST_PATH, ENCRYPTION_PUBLIC_KEY_REQUEST_PATH, -} from '../../helpers/constants/routes' -import { MESSAGE_TYPE } from '../../../../shared/constants/app' -import { TRANSACTION_CATEGORIES } from '../../../../shared/constants/transaction' +} from '../../helpers/constants/routes'; +import { MESSAGE_TYPE } from '../../../../shared/constants/app'; +import { TRANSACTION_CATEGORIES } from '../../../../shared/constants/transaction'; export default class ConfirmTransactionSwitch extends Component { static propTypes = { txData: PropTypes.object, - } + }; redirectToTransaction() { - const { txData } = this.props - const { id, txParams: { data } = {}, transactionCategory } = txData + const { txData } = this.props; + const { id, txParams: { data } = {}, transactionCategory } = txData; if (transactionCategory === TRANSACTION_CATEGORIES.DEPLOY_CONTRACT) { - const pathname = `${CONFIRM_TRANSACTION_ROUTE}/${id}${CONFIRM_DEPLOY_CONTRACT_PATH}` - return + const pathname = `${CONFIRM_TRANSACTION_ROUTE}/${id}${CONFIRM_DEPLOY_CONTRACT_PATH}`; + return ; } if (transactionCategory === TRANSACTION_CATEGORIES.SENT_ETHER) { - const pathname = `${CONFIRM_TRANSACTION_ROUTE}/${id}${CONFIRM_SEND_ETHER_PATH}` - return + const pathname = `${CONFIRM_TRANSACTION_ROUTE}/${id}${CONFIRM_SEND_ETHER_PATH}`; + return ; } if (data) { switch (transactionCategory) { case TRANSACTION_CATEGORIES.TOKEN_METHOD_TRANSFER: { - const pathname = `${CONFIRM_TRANSACTION_ROUTE}/${id}${CONFIRM_SEND_TOKEN_PATH}` - return + const pathname = `${CONFIRM_TRANSACTION_ROUTE}/${id}${CONFIRM_SEND_TOKEN_PATH}`; + return ; } case TRANSACTION_CATEGORIES.TOKEN_METHOD_APPROVE: { - const pathname = `${CONFIRM_TRANSACTION_ROUTE}/${id}${CONFIRM_APPROVE_PATH}` - return + const pathname = `${CONFIRM_TRANSACTION_ROUTE}/${id}${CONFIRM_APPROVE_PATH}`; + return ; } case TRANSACTION_CATEGORIES.TOKEN_METHOD_TRANSFER_FROM: { - const pathname = `${CONFIRM_TRANSACTION_ROUTE}/${id}${CONFIRM_TRANSFER_FROM_PATH}` - return + const pathname = `${CONFIRM_TRANSACTION_ROUTE}/${id}${CONFIRM_TRANSFER_FROM_PATH}`; + return ; } default: { - const pathname = `${CONFIRM_TRANSACTION_ROUTE}/${id}${CONFIRM_TOKEN_METHOD_PATH}` - return + const pathname = `${CONFIRM_TRANSACTION_ROUTE}/${id}${CONFIRM_TOKEN_METHOD_PATH}`; + return ; } } } - const pathname = `${CONFIRM_TRANSACTION_ROUTE}/${id}${CONFIRM_SEND_ETHER_PATH}` - return + const pathname = `${CONFIRM_TRANSACTION_ROUTE}/${id}${CONFIRM_SEND_ETHER_PATH}`; + return ; } render() { - const { txData } = this.props + const { txData } = this.props; if (txData.txParams) { - return this.redirectToTransaction() + return this.redirectToTransaction(); } else if (txData.msgParams) { - let pathname = `${CONFIRM_TRANSACTION_ROUTE}/${txData.id}${SIGNATURE_REQUEST_PATH}` + let pathname = `${CONFIRM_TRANSACTION_ROUTE}/${txData.id}${SIGNATURE_REQUEST_PATH}`; if (txData.type === MESSAGE_TYPE.ETH_DECRYPT) { - pathname = `${CONFIRM_TRANSACTION_ROUTE}/${txData.id}${DECRYPT_MESSAGE_REQUEST_PATH}` + pathname = `${CONFIRM_TRANSACTION_ROUTE}/${txData.id}${DECRYPT_MESSAGE_REQUEST_PATH}`; } else if (txData.type === MESSAGE_TYPE.ETH_GET_ENCRYPTION_PUBLIC_KEY) { - pathname = `${CONFIRM_TRANSACTION_ROUTE}/${txData.id}${ENCRYPTION_PUBLIC_KEY_REQUEST_PATH}` + pathname = `${CONFIRM_TRANSACTION_ROUTE}/${txData.id}${ENCRYPTION_PUBLIC_KEY_REQUEST_PATH}`; } - return + return ; } - return + return ; } } diff --git a/ui/app/pages/confirm-transaction-switch/confirm-transaction-switch.container.js b/ui/app/pages/confirm-transaction-switch/confirm-transaction-switch.container.js index 59d3f9555..f0d0c5ec0 100644 --- a/ui/app/pages/confirm-transaction-switch/confirm-transaction-switch.container.js +++ b/ui/app/pages/confirm-transaction-switch/confirm-transaction-switch.container.js @@ -1,27 +1,27 @@ -import { connect } from 'react-redux' -import { unconfirmedTransactionsListSelector } from '../../selectors' -import ConfirmTransactionSwitch from './confirm-transaction-switch.component' +import { connect } from 'react-redux'; +import { unconfirmedTransactionsListSelector } from '../../selectors'; +import ConfirmTransactionSwitch from './confirm-transaction-switch.component'; const mapStateToProps = (state, ownProps) => { const { metamask: { unapprovedTxs }, - } = state + } = state; const { match: { params = {}, url }, - } = ownProps - const urlId = url?.match(/\d+/u) && url?.match(/\d+/u)[0] - const { id: paramsId } = params - const transactionId = paramsId || urlId + } = ownProps; + const urlId = url?.match(/\d+/u) && url?.match(/\d+/u)[0]; + const { id: paramsId } = params; + const transactionId = paramsId || urlId; - const unconfirmedTransactions = unconfirmedTransactionsListSelector(state) - const totalUnconfirmed = unconfirmedTransactions.length + const unconfirmedTransactions = unconfirmedTransactionsListSelector(state); + const totalUnconfirmed = unconfirmedTransactions.length; const transaction = totalUnconfirmed ? unapprovedTxs[transactionId] || unconfirmedTransactions[0] - : {} + : {}; return { txData: transaction, - } -} + }; +}; -export default connect(mapStateToProps)(ConfirmTransactionSwitch) +export default connect(mapStateToProps)(ConfirmTransactionSwitch); diff --git a/ui/app/pages/confirm-transaction-switch/index.js b/ui/app/pages/confirm-transaction-switch/index.js index 86576d388..6b5e0cbbf 100644 --- a/ui/app/pages/confirm-transaction-switch/index.js +++ b/ui/app/pages/confirm-transaction-switch/index.js @@ -1,3 +1,3 @@ -import ConfirmTransactionSwitch from './confirm-transaction-switch.container' +import ConfirmTransactionSwitch from './confirm-transaction-switch.container'; -export default ConfirmTransactionSwitch +export default ConfirmTransactionSwitch; diff --git a/ui/app/pages/confirm-transaction/conf-tx.js b/ui/app/pages/confirm-transaction/conf-tx.js index 3298baae6..5acc1c435 100644 --- a/ui/app/pages/confirm-transaction/conf-tx.js +++ b/ui/app/pages/confirm-transaction/conf-tx.js @@ -1,26 +1,26 @@ -import PropTypes from 'prop-types' -import React, { Component } from 'react' -import { connect } from 'react-redux' -import { withRouter } from 'react-router-dom' -import { compose } from 'redux' -import log from 'loglevel' -import * as actions from '../../store/actions' -import txHelper from '../../../lib/tx-helper' -import SignatureRequest from '../../components/app/signature-request' -import SignatureRequestOriginal from '../../components/app/signature-request-original' -import Loading from '../../components/ui/loading-screen' -import { getMostRecentOverviewPage } from '../../ducks/history/history' -import { MESSAGE_TYPE } from '../../../../shared/constants/app' -import { TRANSACTION_STATUSES } from '../../../../shared/constants/transaction' +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { connect } from 'react-redux'; +import { withRouter } from 'react-router-dom'; +import { compose } from 'redux'; +import log from 'loglevel'; +import * as actions from '../../store/actions'; +import txHelper from '../../../lib/tx-helper'; +import SignatureRequest from '../../components/app/signature-request'; +import SignatureRequestOriginal from '../../components/app/signature-request-original'; +import Loading from '../../components/ui/loading-screen'; +import { getMostRecentOverviewPage } from '../../ducks/history/history'; +import { MESSAGE_TYPE } from '../../../../shared/constants/app'; +import { TRANSACTION_STATUSES } from '../../../../shared/constants/transaction'; function mapStateToProps(state) { - const { metamask, appState } = state + const { metamask, appState } = state; const { unapprovedMsgCount, unapprovedPersonalMsgCount, unapprovedTypedMessagesCount, - } = metamask - const { txId } = appState + } = metamask; + const { txId } = appState; return { identities: state.metamask.identities, @@ -39,7 +39,7 @@ function mapStateToProps(state) { unapprovedTypedMessagesCount, send: state.metamask.send, currentNetworkTxList: state.metamask.currentNetworkTxList, - } + }; } class ConfirmTxScreen extends Component { @@ -69,20 +69,20 @@ class ConfirmTxScreen extends Component { send: PropTypes.shape({ to: PropTypes.string, }).isRequired, - } + }; getUnapprovedMessagesTotal() { const { unapprovedMsgCount = 0, unapprovedPersonalMsgCount = 0, unapprovedTypedMessagesCount = 0, - } = this.props + } = this.props; return ( unapprovedTypedMessagesCount + unapprovedMsgCount + unapprovedPersonalMsgCount - ) + ); } getTxData() { @@ -94,7 +94,7 @@ class ConfirmTxScreen extends Component { unapprovedPersonalMsgs, unapprovedTypedMessages, match: { params: { id: transactionId } = {} }, - } = this.props + } = this.props; const unconfTxList = txHelper( unapprovedTxs, @@ -102,13 +102,13 @@ class ConfirmTxScreen extends Component { unapprovedPersonalMsgs, unapprovedTypedMessages, network, - ) + ); - log.info(`rendering a combined ${unconfTxList.length} unconf msgs & txs`) + log.info(`rendering a combined ${unconfTxList.length} unconf msgs & txs`); return transactionId ? unconfTxList.find(({ id }) => `${id}` === transactionId) - : unconfTxList[index] + : unconfTxList[index]; } signatureSelect(type, version) { @@ -117,58 +117,58 @@ class ConfirmTxScreen extends Component { type === MESSAGE_TYPE.ETH_SIGN_TYPED_DATA && (version === 'V3' || version === 'V4') ) { - return SignatureRequest + return SignatureRequest; } - return SignatureRequestOriginal + return SignatureRequestOriginal; } signMessage(msgData, event) { - log.info('conf-tx.js: signing message') - const params = msgData.msgParams - params.metamaskId = msgData.id - this.stopPropagation(event) - return this.props.dispatch(actions.signMsg(params)) + log.info('conf-tx.js: signing message'); + const params = msgData.msgParams; + params.metamaskId = msgData.id; + this.stopPropagation(event); + return this.props.dispatch(actions.signMsg(params)); } stopPropagation(event) { if (event.stopPropagation) { - event.stopPropagation() + event.stopPropagation(); } } signPersonalMessage(msgData, event) { - log.info('conf-tx.js: signing personal message') - const params = msgData.msgParams - params.metamaskId = msgData.id - this.stopPropagation(event) - return this.props.dispatch(actions.signPersonalMsg(params)) + log.info('conf-tx.js: signing personal message'); + const params = msgData.msgParams; + params.metamaskId = msgData.id; + this.stopPropagation(event); + return this.props.dispatch(actions.signPersonalMsg(params)); } signTypedMessage(msgData, event) { - log.info('conf-tx.js: signing typed message') - const params = msgData.msgParams - params.metamaskId = msgData.id - this.stopPropagation(event) - return this.props.dispatch(actions.signTypedMsg(params)) + log.info('conf-tx.js: signing typed message'); + const params = msgData.msgParams; + params.metamaskId = msgData.id; + this.stopPropagation(event); + return this.props.dispatch(actions.signTypedMsg(params)); } cancelMessage(msgData, event) { - log.info('canceling message') - this.stopPropagation(event) - return this.props.dispatch(actions.cancelMsg(msgData)) + log.info('canceling message'); + this.stopPropagation(event); + return this.props.dispatch(actions.cancelMsg(msgData)); } cancelPersonalMessage(msgData, event) { - log.info('canceling personal message') - this.stopPropagation(event) - return this.props.dispatch(actions.cancelPersonalMsg(msgData)) + log.info('canceling personal message'); + this.stopPropagation(event); + return this.props.dispatch(actions.cancelPersonalMsg(msgData)); } cancelTypedMessage(msgData, event) { - log.info('canceling typed message') - this.stopPropagation(event) - return this.props.dispatch(actions.cancelTypedMsg(msgData)) + log.info('canceling typed message'); + this.stopPropagation(event); + return this.props.dispatch(actions.cancelTypedMsg(msgData)); } componentDidMount() { @@ -178,15 +178,15 @@ class ConfirmTxScreen extends Component { mostRecentOverviewPage, network, send, - } = this.props - const unconfTxList = txHelper(unapprovedTxs, {}, {}, {}, network) + } = this.props; + const unconfTxList = txHelper(unapprovedTxs, {}, {}, {}, network); if ( unconfTxList.length === 0 && !send.to && this.getUnapprovedMessagesTotal() === 0 ) { - history.push(mostRecentOverviewPage) + history.push(mostRecentOverviewPage); } } @@ -199,20 +199,21 @@ class ConfirmTxScreen extends Component { history, match: { params: { id: transactionId } = {} }, mostRecentOverviewPage, - } = this.props + } = this.props; - let prevTx + let prevTx; if (transactionId) { - prevTx = currentNetworkTxList.find(({ id }) => `${id}` === transactionId) + prevTx = currentNetworkTxList.find(({ id }) => `${id}` === transactionId); } else { - const { index: prevIndex, unapprovedTxs: prevUnapprovedTxs } = prevProps - const prevUnconfTxList = txHelper(prevUnapprovedTxs, {}, {}, {}, network) - const prevTxData = prevUnconfTxList[prevIndex] || {} - prevTx = currentNetworkTxList.find(({ id }) => id === prevTxData.id) || {} + const { index: prevIndex, unapprovedTxs: prevUnapprovedTxs } = prevProps; + const prevUnconfTxList = txHelper(prevUnapprovedTxs, {}, {}, {}, network); + const prevTxData = prevUnconfTxList[prevIndex] || {}; + prevTx = + currentNetworkTxList.find(({ id }) => id === prevTxData.id) || {}; } - const unconfTxList = txHelper(unapprovedTxs, {}, {}, {}, network) + const unconfTxList = txHelper(unapprovedTxs, {}, {}, {}, network); if (prevTx && prevTx.status === TRANSACTION_STATUSES.DROPPED) { this.props.dispatch( @@ -220,9 +221,9 @@ class ConfirmTxScreen extends Component { name: 'TRANSACTION_CONFIRMED', onSubmit: () => history.push(mostRecentOverviewPage), }), - ) + ); - return + return; } if ( @@ -230,26 +231,26 @@ class ConfirmTxScreen extends Component { !send.to && this.getUnapprovedMessagesTotal() === 0 ) { - this.props.history.push(mostRecentOverviewPage) + this.props.history.push(mostRecentOverviewPage); } } render() { - const { currentCurrency, blockGasLimit } = this.props + const { currentCurrency, blockGasLimit } = this.props; - const txData = this.getTxData() || {} + const txData = this.getTxData() || {}; const { msgParams, type, msgParams: { version }, - } = txData - log.debug('msgParams detected, rendering pending msg') + } = txData; + log.debug('msgParams detected, rendering pending msg'); if (!msgParams) { - return + return ; } - const SigComponent = this.signatureSelect(type, version) + const SigComponent = this.signatureSelect(type, version); return ( - ) + ); } } -export default compose(withRouter, connect(mapStateToProps))(ConfirmTxScreen) +export default compose(withRouter, connect(mapStateToProps))(ConfirmTxScreen); diff --git a/ui/app/pages/confirm-transaction/confirm-transaction.component.js b/ui/app/pages/confirm-transaction/confirm-transaction.component.js index d794717ae..c08b4f387 100644 --- a/ui/app/pages/confirm-transaction/confirm-transaction.component.js +++ b/ui/app/pages/confirm-transaction/confirm-transaction.component.js @@ -1,16 +1,16 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import { Switch, Route } from 'react-router-dom' -import Loading from '../../components/ui/loading-screen' -import ConfirmTransactionSwitch from '../confirm-transaction-switch' -import ConfirmTransactionBase from '../confirm-transaction-base' -import ConfirmSendEther from '../confirm-send-ether' -import ConfirmSendToken from '../confirm-send-token' -import ConfirmDeployContract from '../confirm-deploy-contract' -import ConfirmApprove from '../confirm-approve' -import ConfirmTokenTransactionBaseContainer from '../confirm-token-transaction-base' -import ConfirmDecryptMessage from '../confirm-decrypt-message' -import ConfirmEncryptionPublicKey from '../confirm-encryption-public-key' +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import { Switch, Route } from 'react-router-dom'; +import Loading from '../../components/ui/loading-screen'; +import ConfirmTransactionSwitch from '../confirm-transaction-switch'; +import ConfirmTransactionBase from '../confirm-transaction-base'; +import ConfirmSendEther from '../confirm-send-ether'; +import ConfirmSendToken from '../confirm-send-token'; +import ConfirmDeployContract from '../confirm-deploy-contract'; +import ConfirmApprove from '../confirm-approve'; +import ConfirmTokenTransactionBaseContainer from '../confirm-token-transaction-base'; +import ConfirmDecryptMessage from '../confirm-decrypt-message'; +import ConfirmEncryptionPublicKey from '../confirm-encryption-public-key'; import { CONFIRM_TRANSACTION_ROUTE, @@ -23,13 +23,13 @@ import { SIGNATURE_REQUEST_PATH, DECRYPT_MESSAGE_REQUEST_PATH, ENCRYPTION_PUBLIC_KEY_REQUEST_PATH, -} from '../../helpers/constants/routes' -import ConfTx from './conf-tx' +} from '../../helpers/constants/routes'; +import ConfTx from './conf-tx'; export default class ConfirmTransaction extends Component { static contextTypes = { metricsEvent: PropTypes.func, - } + }; static propTypes = { history: PropTypes.object.isRequired, @@ -45,7 +45,7 @@ export default class ConfirmTransaction extends Component { paramsTransactionId: PropTypes.string, getTokenParams: PropTypes.func, isTokenMethodAction: PropTypes.bool, - } + }; componentDidMount() { const { @@ -60,21 +60,21 @@ export default class ConfirmTransaction extends Component { paramsTransactionId, getTokenParams, isTokenMethodAction, - } = this.props + } = this.props; if (!totalUnapprovedCount && !send.to) { - history.replace(mostRecentOverviewPage) - return + history.replace(mostRecentOverviewPage); + return; } - fetchBasicGasEstimates() - getContractMethodData(data) + fetchBasicGasEstimates(); + getContractMethodData(data); if (isTokenMethodAction) { - getTokenParams(to) + getTokenParams(to); } - const txId = transactionId || paramsTransactionId + const txId = transactionId || paramsTransactionId; if (txId) { - this.props.setTransactionToConfirm(txId) + this.props.setTransactionToConfirm(txId); } } @@ -89,33 +89,33 @@ export default class ConfirmTransaction extends Component { history, mostRecentOverviewPage, totalUnapprovedCount, - } = this.props + } = this.props; if ( paramsTransactionId && transactionId && prevProps.paramsTransactionId !== paramsTransactionId ) { - clearConfirmTransaction() - getContractMethodData(data) - setTransactionToConfirm(paramsTransactionId) + clearConfirmTransaction(); + getContractMethodData(data); + setTransactionToConfirm(paramsTransactionId); } else if ( prevProps.transactionId && !transactionId && !totalUnapprovedCount ) { - history.replace(mostRecentOverviewPage) + history.replace(mostRecentOverviewPage); } else if ( prevProps.transactionId && transactionId && prevProps.transactionId !== transactionId ) { - history.replace(mostRecentOverviewPage) + history.replace(mostRecentOverviewPage); } } render() { - const { transactionId, paramsTransactionId } = this.props + const { transactionId, paramsTransactionId } = this.props; // Show routes when state.confirmTransaction has been set and when either the ID in the params // isn't specified or is specified and matches the ID in state.confirmTransaction in order to // support URLs of /confirm-transaction or /confirm-transaction/ @@ -171,6 +171,6 @@ export default class ConfirmTransaction extends Component { ) : ( - ) + ); } } diff --git a/ui/app/pages/confirm-transaction/confirm-transaction.container.js b/ui/app/pages/confirm-transaction/confirm-transaction.container.js index 8dc56236d..d07665256 100644 --- a/ui/app/pages/confirm-transaction/confirm-transaction.container.js +++ b/ui/app/pages/confirm-transaction/confirm-transaction.container.js @@ -1,33 +1,33 @@ -import { connect } from 'react-redux' -import { compose } from 'redux' -import { withRouter } from 'react-router-dom' +import { connect } from 'react-redux'; +import { compose } from 'redux'; +import { withRouter } from 'react-router-dom'; import { setTransactionToConfirm, clearConfirmTransaction, -} from '../../ducks/confirm-transaction/confirm-transaction.duck' -import { isTokenMethodAction } from '../../helpers/utils/transactions.util' -import { fetchBasicGasEstimates } from '../../ducks/gas/gas.duck' +} from '../../ducks/confirm-transaction/confirm-transaction.duck'; +import { isTokenMethodAction } from '../../helpers/utils/transactions.util'; +import { fetchBasicGasEstimates } from '../../ducks/gas/gas.duck'; -import { getContractMethodData, getTokenParams } from '../../store/actions' -import { unconfirmedTransactionsListSelector } from '../../selectors' -import { getMostRecentOverviewPage } from '../../ducks/history/history' -import ConfirmTransaction from './confirm-transaction.component' +import { getContractMethodData, getTokenParams } from '../../store/actions'; +import { unconfirmedTransactionsListSelector } from '../../selectors'; +import { getMostRecentOverviewPage } from '../../ducks/history/history'; +import ConfirmTransaction from './confirm-transaction.component'; const mapStateToProps = (state, ownProps) => { const { metamask: { send, unapprovedTxs }, - } = state + } = state; const { match: { params = {} }, - } = ownProps - const { id } = params + } = ownProps; + const { id } = params; - const unconfirmedTransactions = unconfirmedTransactionsListSelector(state) - const totalUnconfirmed = unconfirmedTransactions.length + const unconfirmedTransactions = unconfirmedTransactionsListSelector(state); + const totalUnconfirmed = unconfirmedTransactions.length; const transaction = totalUnconfirmed ? unapprovedTxs[id] || unconfirmedTransactions[0] - : {} - const { id: transactionId, transactionCategory } = transaction + : {}; + const { id: transactionId, transactionCategory } = transaction; return { totalUnapprovedCount: totalUnconfirmed, @@ -39,22 +39,22 @@ const mapStateToProps = (state, ownProps) => { transactionId: transactionId && String(transactionId), transaction, isTokenMethodAction: isTokenMethodAction(transactionCategory), - } -} + }; +}; const mapDispatchToProps = (dispatch) => { return { setTransactionToConfirm: (transactionId) => { - dispatch(setTransactionToConfirm(transactionId)) + dispatch(setTransactionToConfirm(transactionId)); }, clearConfirmTransaction: () => dispatch(clearConfirmTransaction()), fetchBasicGasEstimates: () => dispatch(fetchBasicGasEstimates()), getContractMethodData: (data) => dispatch(getContractMethodData(data)), getTokenParams: (tokenAddress) => dispatch(getTokenParams(tokenAddress)), - } -} + }; +}; export default compose( withRouter, connect(mapStateToProps, mapDispatchToProps), -)(ConfirmTransaction) +)(ConfirmTransaction); diff --git a/ui/app/pages/confirm-transaction/index.js b/ui/app/pages/confirm-transaction/index.js index a51e7b162..108e7e887 100644 --- a/ui/app/pages/confirm-transaction/index.js +++ b/ui/app/pages/confirm-transaction/index.js @@ -1,3 +1,3 @@ -import ConfirmTransaction from './confirm-transaction.container' +import ConfirmTransaction from './confirm-transaction.container'; -export default ConfirmTransaction +export default ConfirmTransaction; diff --git a/ui/app/pages/connected-accounts/connected-accounts.component.js b/ui/app/pages/connected-accounts/connected-accounts.component.js index 5a0a30109..5b9e5f06f 100644 --- a/ui/app/pages/connected-accounts/connected-accounts.component.js +++ b/ui/app/pages/connected-accounts/connected-accounts.component.js @@ -1,18 +1,18 @@ -import PropTypes from 'prop-types' -import React, { PureComponent } from 'react' -import Popover from '../../components/ui/popover' -import ConnectedAccountsList from '../../components/app/connected-accounts-list' -import ConnectedAccountsPermissions from '../../components/app/connected-accounts-permissions' +import PropTypes from 'prop-types'; +import React, { PureComponent } from 'react'; +import Popover from '../../components/ui/popover'; +import ConnectedAccountsList from '../../components/app/connected-accounts-list'; +import ConnectedAccountsPermissions from '../../components/app/connected-accounts-permissions'; export default class ConnectedAccounts extends PureComponent { static contextTypes = { t: PropTypes.func.isRequired, - } + }; static defaultProps = { accountToConnect: null, permissions: undefined, - } + }; static propTypes = { accountToConnect: PropTypes.object, @@ -26,7 +26,7 @@ export default class ConnectedAccounts extends PureComponent { removePermittedAccount: PropTypes.func.isRequired, setSelectedAddress: PropTypes.func.isRequired, history: PropTypes.object.isRequired, - } + }; render() { const { @@ -41,13 +41,13 @@ export default class ConnectedAccounts extends PureComponent { selectedAddress, removePermittedAccount, setSelectedAddress, - } = this.props - const { t } = this.context + } = this.props; + const { t } = this.context; const connectedAccountsDescription = connectedAccounts.length > 1 ? t('connectedAccountsDescriptionPlural', [connectedAccounts.length]) - : t('connectedAccountsDescriptionSingular') + : t('connectedAccountsDescriptionSingular'); return ( - ) + ); } } diff --git a/ui/app/pages/connected-accounts/connected-accounts.container.js b/ui/app/pages/connected-accounts/connected-accounts.container.js index b1a1a2433..8a8cffb3b 100644 --- a/ui/app/pages/connected-accounts/connected-accounts.container.js +++ b/ui/app/pages/connected-accounts/connected-accounts.container.js @@ -1,27 +1,27 @@ -import { connect } from 'react-redux' +import { connect } from 'react-redux'; import { getAccountToConnectToActiveTab, getOrderedConnectedAccountsForActiveTab, getPermissionsForActiveTab, getSelectedAddress, -} from '../../selectors' -import { isExtensionUrl } from '../../helpers/utils/util' +} from '../../selectors'; +import { isExtensionUrl } from '../../helpers/utils/util'; import { addPermittedAccount, removePermittedAccount, setSelectedAddress, -} from '../../store/actions' -import { getMostRecentOverviewPage } from '../../ducks/history/history' -import ConnectedAccounts from './connected-accounts.component' +} from '../../store/actions'; +import { getMostRecentOverviewPage } from '../../ducks/history/history'; +import ConnectedAccounts from './connected-accounts.component'; const mapStateToProps = (state) => { - const { activeTab } = state - const accountToConnect = getAccountToConnectToActiveTab(state) - const connectedAccounts = getOrderedConnectedAccountsForActiveTab(state) - const permissions = getPermissionsForActiveTab(state) - const selectedAddress = getSelectedAddress(state) + const { activeTab } = state; + const accountToConnect = getAccountToConnectToActiveTab(state); + const connectedAccounts = getOrderedConnectedAccountsForActiveTab(state); + const permissions = getPermissionsForActiveTab(state); + const selectedAddress = getSelectedAddress(state); - const isActiveTabExtension = isExtensionUrl(activeTab) + const isActiveTabExtension = isExtensionUrl(activeTab); return { accountToConnect, isActiveTabExtension, @@ -30,8 +30,8 @@ const mapStateToProps = (state) => { mostRecentOverviewPage: getMostRecentOverviewPage(state), permissions, selectedAddress, - } -} + }; +}; const mapDispatchToProps = (dispatch) => { return { @@ -40,11 +40,11 @@ const mapDispatchToProps = (dispatch) => { removePermittedAccount: (origin, address) => dispatch(removePermittedAccount(origin, address)), setSelectedAddress: (address) => dispatch(setSelectedAddress(address)), - } -} + }; +}; const mergeProps = (stateProps, dispatchProps, ownProps) => { - const { activeTabOrigin } = stateProps + const { activeTabOrigin } = stateProps; return { ...ownProps, @@ -54,11 +54,11 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => { dispatchProps.addPermittedAccount(activeTabOrigin, address), removePermittedAccount: (address) => dispatchProps.removePermittedAccount(activeTabOrigin, address), - } -} + }; +}; export default connect( mapStateToProps, mapDispatchToProps, mergeProps, -)(ConnectedAccounts) +)(ConnectedAccounts); diff --git a/ui/app/pages/connected-accounts/index.js b/ui/app/pages/connected-accounts/index.js index 7497bc560..d97dbc5a8 100644 --- a/ui/app/pages/connected-accounts/index.js +++ b/ui/app/pages/connected-accounts/index.js @@ -1 +1 @@ -export { default } from './connected-accounts.container' +export { default } from './connected-accounts.container'; diff --git a/ui/app/pages/connected-sites/connected-sites.component.js b/ui/app/pages/connected-sites/connected-sites.component.js index 5c8f84e5f..90d880811 100644 --- a/ui/app/pages/connected-sites/connected-sites.component.js +++ b/ui/app/pages/connected-sites/connected-sites.component.js @@ -1,17 +1,17 @@ -import PropTypes from 'prop-types' -import React, { Component } from 'react' -import ConnectedSitesList from '../../components/app/connected-sites-list' -import Popover from '../../components/ui/popover/popover.component' -import Button from '../../components/ui/button' +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import ConnectedSitesList from '../../components/app/connected-sites-list'; +import Popover from '../../components/ui/popover/popover.component'; +import Button from '../../components/ui/button'; export default class ConnectedSites extends Component { static contextTypes = { t: PropTypes.func, - } + }; static defaultProps = { tabToConnect: null, - } + }; static propTypes = { accountLabel: PropTypes.string.isRequired, @@ -26,15 +26,15 @@ export default class ConnectedSites extends Component { ).isRequired, tabToConnect: PropTypes.object, requestAccountsPermission: PropTypes.func.isRequired, - } + }; state = { sitePendingDisconnect: null, - } + }; componentDidMount() { - const { getOpenMetamaskTabsIds } = this.props - getOpenMetamaskTabsIds() + const { getOpenMetamaskTabsIds } = this.props; + getOpenMetamaskTabsIds(); } setPendingDisconnect = (domainKey) => { @@ -42,30 +42,30 @@ export default class ConnectedSites extends Component { sitePendingDisconnect: { domainKey, }, - }) - } + }); + }; clearPendingDisconnect = () => { this.setState({ sitePendingDisconnect: null, - }) - } + }); + }; disconnectAccount = () => { - const { disconnectAccount } = this.props - const { sitePendingDisconnect } = this.state + const { disconnectAccount } = this.props; + const { sitePendingDisconnect } = this.state; - disconnectAccount(sitePendingDisconnect.domainKey) - this.clearPendingDisconnect() - } + disconnectAccount(sitePendingDisconnect.domainKey); + this.clearPendingDisconnect(); + }; disconnectAllAccounts = () => { - const { disconnectAllAccounts } = this.props - const { sitePendingDisconnect } = this.state + const { disconnectAllAccounts } = this.props; + const { sitePendingDisconnect } = this.state; - disconnectAllAccounts(sitePendingDisconnect.domainKey) - this.clearPendingDisconnect() - } + disconnectAllAccounts(sitePendingDisconnect.domainKey); + this.clearPendingDisconnect(); + }; renderConnectedSitesList() { return ( @@ -74,7 +74,7 @@ export default class ConnectedSites extends Component { connectedDomains={this.props.connectedDomains} onDisconnect={this.setPendingDisconnect} /> - ) + ); } renderConnectedSitesPopover() { @@ -84,8 +84,8 @@ export default class ConnectedSites extends Component { connectedDomains, tabToConnect, requestAccountsPermission, - } = this.props - const { t } = this.context + } = this.props; + const { t } = this.context; return ( {this.renderConnectedSitesList()} - ) + ); } renderDisconnectPopover() { - const { closePopover, permittedAccountsByOrigin } = this.props - const { t } = this.context + const { closePopover, permittedAccountsByOrigin } = this.props; + const { t } = this.context; const { sitePendingDisconnect: { domainKey }, - } = this.state + } = this.state; - const numPermittedAccounts = permittedAccountsByOrigin[domainKey].length + const numPermittedAccounts = permittedAccountsByOrigin[domainKey].length; return ( - ) + ); } render() { - const { sitePendingDisconnect } = this.state + const { sitePendingDisconnect } = this.state; return sitePendingDisconnect ? this.renderDisconnectPopover() - : this.renderConnectedSitesPopover() + : this.renderConnectedSitesPopover(); } } diff --git a/ui/app/pages/connected-sites/connected-sites.container.js b/ui/app/pages/connected-sites/connected-sites.container.js index ef5edd85b..39c8150c8 100644 --- a/ui/app/pages/connected-sites/connected-sites.container.js +++ b/ui/app/pages/connected-sites/connected-sites.container.js @@ -1,10 +1,10 @@ -import { connect } from 'react-redux' +import { connect } from 'react-redux'; import { getOpenMetamaskTabsIds, requestAccountsPermissionWithId, removePermissionsFor, removePermittedAccount, -} from '../../store/actions' +} from '../../store/actions'; import { getConnectedDomainsForSelectedAddress, getCurrentAccountWithSendEtherInfo, @@ -13,27 +13,27 @@ import { getPermissionsMetadataHostCounts, getPermittedAccountsByOrigin, getSelectedAddress, -} from '../../selectors' -import { CONNECT_ROUTE } from '../../helpers/constants/routes' -import { getMostRecentOverviewPage } from '../../ducks/history/history' -import ConnectedSites from './connected-sites.component' +} from '../../selectors'; +import { CONNECT_ROUTE } from '../../helpers/constants/routes'; +import { getMostRecentOverviewPage } from '../../ducks/history/history'; +import ConnectedSites from './connected-sites.component'; const mapStateToProps = (state) => { - const { openMetaMaskTabs } = state.appState - const { id } = state.activeTab - const connectedDomains = getConnectedDomainsForSelectedAddress(state) - const originOfCurrentTab = getOriginOfCurrentTab(state) - const permittedAccountsByOrigin = getPermittedAccountsByOrigin(state) - const selectedAddress = getSelectedAddress(state) + const { openMetaMaskTabs } = state.appState; + const { id } = state.activeTab; + const connectedDomains = getConnectedDomainsForSelectedAddress(state); + const originOfCurrentTab = getOriginOfCurrentTab(state); + const permittedAccountsByOrigin = getPermittedAccountsByOrigin(state); + const selectedAddress = getSelectedAddress(state); const currentTabHasNoAccounts = !permittedAccountsByOrigin[originOfCurrentTab] - ?.length + ?.length; - let tabToConnect + let tabToConnect; if (originOfCurrentTab && currentTabHasNoAccounts && !openMetaMaskTabs[id]) { tabToConnect = { origin: originOfCurrentTab, - } + }; } return { @@ -45,29 +45,29 @@ const mapStateToProps = (state) => { permittedAccountsByOrigin, selectedAddress, tabToConnect, - } -} + }; +}; const mapDispatchToProps = (dispatch) => { return { getOpenMetamaskTabsIds: () => dispatch(getOpenMetamaskTabsIds()), disconnectAccount: (domainKey, address) => { - dispatch(removePermittedAccount(domainKey, address)) + dispatch(removePermittedAccount(domainKey, address)); }, disconnectAllAccounts: (domainKey, domain) => { const permissionMethodNames = domain.permissions.map( ({ parentCapability }) => parentCapability, - ) + ); dispatch( removePermissionsFor({ [domainKey]: permissionMethodNames, }), - ) + ); }, requestAccountsPermissionWithId: (origin) => dispatch(requestAccountsPermissionWithId(origin)), - } -} + }; +}; const mergeProps = (stateProps, dispatchProps, ownProps) => { const { @@ -76,16 +76,16 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => { mostRecentOverviewPage, selectedAddress, tabToConnect, - } = stateProps + } = stateProps; const { disconnectAccount, disconnectAllAccounts, // eslint-disable-next-line no-shadow requestAccountsPermissionWithId, - } = dispatchProps - const { history } = ownProps + } = dispatchProps; + const { history } = ownProps; - const closePopover = () => history.push(mostRecentOverviewPage) + const closePopover = () => history.push(mostRecentOverviewPage); return { ...ownProps, @@ -93,26 +93,26 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => { ...dispatchProps, closePopover, disconnectAccount: (domainKey) => { - disconnectAccount(domainKey, selectedAddress) + disconnectAccount(domainKey, selectedAddress); if (connectedDomains.length === 1) { - closePopover() + closePopover(); } }, disconnectAllAccounts: (domainKey) => { - disconnectAllAccounts(domainKey, domains[domainKey]) + disconnectAllAccounts(domainKey, domains[domainKey]); if (connectedDomains.length === 1) { - closePopover() + closePopover(); } }, requestAccountsPermission: async () => { - const id = await requestAccountsPermissionWithId(tabToConnect.origin) - history.push(`${CONNECT_ROUTE}/${id}`) + const id = await requestAccountsPermissionWithId(tabToConnect.origin); + history.push(`${CONNECT_ROUTE}/${id}`); }, - } -} + }; +}; export default connect( mapStateToProps, mapDispatchToProps, mergeProps, -)(ConnectedSites) +)(ConnectedSites); diff --git a/ui/app/pages/connected-sites/index.js b/ui/app/pages/connected-sites/index.js index 96cf6e67d..c7daa8393 100644 --- a/ui/app/pages/connected-sites/index.js +++ b/ui/app/pages/connected-sites/index.js @@ -1 +1 @@ -export { default } from './connected-sites.container' +export { default } from './connected-sites.container'; diff --git a/ui/app/pages/create-account/connect-hardware/account-list.js b/ui/app/pages/create-account/connect-hardware/account-list.js index 2cf315ae7..df1ec8cdd 100644 --- a/ui/app/pages/create-account/connect-hardware/account-list.js +++ b/ui/app/pages/create-account/connect-hardware/account-list.js @@ -1,8 +1,8 @@ -import PropTypes from 'prop-types' -import React, { Component } from 'react' -import Select from 'react-select' -import getAccountLink from '../../../../lib/account-link' -import Button from '../../../components/ui/button' +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import Select from 'react-select'; +import getAccountLink from '../../../../lib/account-link'; +import Button from '../../../components/ui/button'; class AccountList extends Component { getHdPaths() { @@ -15,26 +15,26 @@ class AccountList extends Component { label: `Legacy (MEW / MyCrypto)`, value: `m/44'/60'/0'`, }, - ] + ]; } goToNextPage = () => { // If we have < 5 accounts, it's restricted by BIP-44 if (this.props.accounts.length === 5) { - this.props.getPage(this.props.device, 1, this.props.selectedPath) + this.props.getPage(this.props.device, 1, this.props.selectedPath); } else { - this.props.onAccountRestriction() + this.props.onAccountRestriction(); } - } + }; goToPreviousPage = () => { - this.props.getPage(this.props.device, -1, this.props.selectedPath) - } + this.props.getPage(this.props.device, -1, this.props.selectedPath); + }; renderHdPathSelector() { - const { onPathChange, selectedPath } = this.props + const { onPathChange, selectedPath } = this.props; - const options = this.getHdPaths() + const options = this.getHdPaths(); return (

    @@ -49,20 +49,20 @@ class AccountList extends Component { value={selectedPath} options={options} onChange={(opt) => { - onPathChange(opt.value) + onPathChange(opt.value); }} />

    - ) + ); } capitalizeDevice(device) { - return device.slice(0, 1).toUpperCase() + device.slice(1) + return device.slice(0, 1).toUpperCase() + device.slice(1); } renderHeader() { - const { device } = this.props + const { device } = this.props; return (

    @@ -76,7 +76,7 @@ class AccountList extends Component { {this.context.t('selectAnAccountHelp')}

    - ) + ); } renderAccounts() { @@ -120,7 +120,7 @@ class AccountList extends Component { ))} - ) + ); } renderPagination() { @@ -139,14 +139,14 @@ class AccountList extends Component { {`${this.context.t('next')} >`} - ) + ); } renderButtons() { - const disabled = this.props.selectedAccount === null - const buttonProps = {} + const disabled = this.props.selectedAccount === null; + const buttonProps = {}; if (disabled) { - buttonProps.disabled = true + buttonProps.disabled = true; } return ( @@ -169,7 +169,7 @@ class AccountList extends Component { {this.context.t('unlock')} - ) + ); } renderForgetDevice() { @@ -179,7 +179,7 @@ class AccountList extends Component { {this.context.t('forgetDevice')} - ) + ); } render() { @@ -191,7 +191,7 @@ class AccountList extends Component { {this.renderButtons()} {this.renderForgetDevice()} - ) + ); } } @@ -208,10 +208,10 @@ AccountList.propTypes = { onUnlockAccount: PropTypes.func, onCancel: PropTypes.func, onAccountRestriction: PropTypes.func, -} +}; AccountList.contextTypes = { t: PropTypes.func, -} +}; -export default AccountList +export default AccountList; diff --git a/ui/app/pages/create-account/connect-hardware/index.js b/ui/app/pages/create-account/connect-hardware/index.js index a17806207..153195088 100644 --- a/ui/app/pages/create-account/connect-hardware/index.js +++ b/ui/app/pages/create-account/connect-hardware/index.js @@ -1,14 +1,14 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import { connect } from 'react-redux' -import * as actions from '../../../store/actions' -import { getMetaMaskAccounts } from '../../../selectors' -import { formatBalance } from '../../../helpers/utils/util' -import { getMostRecentOverviewPage } from '../../../ducks/history/history' -import SelectHardware from './select-hardware' -import AccountList from './account-list' +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import { connect } from 'react-redux'; +import * as actions from '../../../store/actions'; +import { getMetaMaskAccounts } from '../../../selectors'; +import { formatBalance } from '../../../helpers/utils/util'; +import { getMostRecentOverviewPage } from '../../../ducks/history/history'; +import SelectHardware from './select-hardware'; +import AccountList from './account-list'; -const U2F_ERROR = 'U2F' +const U2F_ERROR = 'U2F'; class ConnectHardwareForm extends Component { state = { @@ -18,23 +18,23 @@ class ConnectHardwareForm extends Component { browserSupported: true, unlocked: false, device: null, - } + }; UNSAFE_componentWillReceiveProps(nextProps) { - const { accounts } = nextProps + const { accounts } = nextProps; const newAccounts = this.state.accounts.map((a) => { - const normalizedAddress = a.address.toLowerCase() + const normalizedAddress = a.address.toLowerCase(); const balanceValue = (accounts[normalizedAddress] && accounts[normalizedAddress].balance) || - null - a.balance = balanceValue ? formatBalance(balanceValue, 6) : '...' - return a - }) - this.setState({ accounts: newAccounts }) + null; + a.balance = balanceValue ? formatBalance(balanceValue, 6) : '...'; + return a; + }); + this.setState({ accounts: newAccounts }); } componentDidMount() { - this.checkIfUnlocked() + this.checkIfUnlocked(); } async checkIfUnlocked() { @@ -42,46 +42,46 @@ class ConnectHardwareForm extends Component { const unlocked = await this.props.checkHardwareStatus( device, this.props.defaultHdPaths[device], - ) + ); if (unlocked) { - this.setState({ unlocked: true }) - this.getPage(device, 0, this.props.defaultHdPaths[device]) + this.setState({ unlocked: true }); + this.getPage(device, 0, this.props.defaultHdPaths[device]); } } } connectToHardwareWallet = (device) => { - this.setState({ device }) + this.setState({ device }); if (this.state.accounts.length) { - return + return; } // Default values - this.getPage(device, 0, this.props.defaultHdPaths[device]) - } + this.getPage(device, 0, this.props.defaultHdPaths[device]); + }; onPathChange = (path) => { this.props.setHardwareWalletDefaultHdPath({ device: this.state.device, path, - }) - this.getPage(this.state.device, 0, path) - } + }); + this.getPage(this.state.device, 0, path); + }; onAccountChange = (account) => { - this.setState({ selectedAccount: account.toString(), error: null }) - } + this.setState({ selectedAccount: account.toString(), error: null }); + }; onAccountRestriction = () => { - this.setState({ error: this.context.t('ledgerAccountRestriction') }) - } + this.setState({ error: this.context.t('ledgerAccountRestriction') }); + }; showTemporaryAlert() { - this.props.showAlert(this.context.t('hardwareWalletConnected')) + this.props.showAlert(this.context.t('hardwareWalletConnected')); // Autohide the alert after 5 seconds setTimeout((_) => { - this.props.hideAlert() - }, 5000) + this.props.hideAlert(); + }, 5000); } getPage = (device, page, hdPath) => { @@ -92,56 +92,56 @@ class ConnectHardwareForm extends Component { // If we just loaded the accounts for the first time // (device previously locked) show the global alert if (this.state.accounts.length === 0 && !this.state.unlocked) { - this.showTemporaryAlert() + this.showTemporaryAlert(); } - const newState = { unlocked: true, device, error: null } + const newState = { unlocked: true, device, error: null }; // Default to the first account if (this.state.selectedAccount === null) { accounts.forEach((a) => { if (a.address.toLowerCase() === this.props.address) { - newState.selectedAccount = a.index.toString() + newState.selectedAccount = a.index.toString(); } - }) + }); // If the page doesn't contain the selected account, let's deselect it } else if ( !accounts.filter( (a) => a.index.toString() === this.state.selectedAccount, ).length ) { - newState.selectedAccount = null + newState.selectedAccount = null; } // Map accounts with balances newState.accounts = accounts.map((account) => { - const normalizedAddress = account.address.toLowerCase() + const normalizedAddress = account.address.toLowerCase(); const balanceValue = (this.props.accounts[normalizedAddress] && this.props.accounts[normalizedAddress].balance) || - null + null; account.balance = balanceValue ? formatBalance(balanceValue, 6) - : '...' - return account - }) + : '...'; + return account; + }); - this.setState(newState) + this.setState(newState); } }) .catch((e) => { - const errorMessage = typeof e === 'string' ? e : e.message + const errorMessage = typeof e === 'string' ? e : e.message; if (errorMessage === 'Window blocked') { - this.setState({ browserSupported: false, error: null }) + this.setState({ browserSupported: false, error: null }); } else if (errorMessage.includes(U2F_ERROR)) { - this.setState({ error: U2F_ERROR }) + this.setState({ error: U2F_ERROR }); } else if ( errorMessage !== 'Window closed' && errorMessage !== 'Popup closed' ) { - this.setState({ error: errorMessage }) + this.setState({ error: errorMessage }); } - }) - } + }); + }; onForgetDevice = (device) => { this.props @@ -152,22 +152,22 @@ class ConnectHardwareForm extends Component { selectedAccount: null, accounts: [], unlocked: false, - }) + }); }) .catch((e) => { - this.setState({ error: e.message }) - }) - } + this.setState({ error: e.message }); + }); + }; onUnlockAccount = (device) => { const { history, mostRecentOverviewPage, unlockHardwareWalletAccount, - } = this.props + } = this.props; if (this.state.selectedAccount === null) { - this.setState({ error: this.context.t('accountSelectionRequired') }) + this.setState({ error: this.context.t('accountSelectionRequired') }); } unlockHardwareWalletAccount(this.state.selectedAccount, device) @@ -178,8 +178,8 @@ class ConnectHardwareForm extends Component { action: 'Connected Hardware Wallet', name: `Connected Account with: ${device}`, }, - }) - history.push(mostRecentOverviewPage) + }); + history.push(mostRecentOverviewPage); }) .catch((e) => { this.context.metricsEvent({ @@ -191,15 +191,15 @@ class ConnectHardwareForm extends Component { customVariables: { error: e.message, }, - }) - this.setState({ error: e.message }) - }) - } + }); + this.setState({ error: e.message }); + }); + }; onCancel = () => { - const { history, mostRecentOverviewPage } = this.props - history.push(mostRecentOverviewPage) - } + const { history, mostRecentOverviewPage } = this.props; + history.push(mostRecentOverviewPage); + }; renderError() { if (this.state.error === U2F_ERROR) { @@ -220,11 +220,11 @@ class ConnectHardwareForm extends Component { , ])}

    - ) + ); } return this.state.error ? ( {this.state.error} - ) : null + ) : null; } renderContent() { @@ -234,7 +234,7 @@ class ConnectHardwareForm extends Component { connectToHardwareWallet={this.connectToHardwareWallet} browserSupported={this.state.browserSupported} /> - ) + ); } return ( @@ -252,7 +252,7 @@ class ConnectHardwareForm extends Component { onCancel={this.onCancel} onAccountRestriction={this.onAccountRestriction} /> - ) + ); } render() { @@ -261,7 +261,7 @@ class ConnectHardwareForm extends Component { {this.renderError()} {this.renderContent()} - ) + ); } } @@ -279,16 +279,16 @@ ConnectHardwareForm.propTypes = { address: PropTypes.string, defaultHdPaths: PropTypes.object, mostRecentOverviewPage: PropTypes.string.isRequired, -} +}; const mapStateToProps = (state) => { const { metamask: { network, selectedAddress }, - } = state - const accounts = getMetaMaskAccounts(state) + } = state; + const accounts = getMetaMaskAccounts(state); const { appState: { defaultHdPaths }, - } = state + } = state; return { network, @@ -296,36 +296,39 @@ const mapStateToProps = (state) => { address: selectedAddress, defaultHdPaths, mostRecentOverviewPage: getMostRecentOverviewPage(state), - } -} + }; +}; const mapDispatchToProps = (dispatch) => { return { setHardwareWalletDefaultHdPath: ({ device, path }) => { - return dispatch(actions.setHardwareWalletDefaultHdPath({ device, path })) + return dispatch(actions.setHardwareWalletDefaultHdPath({ device, path })); }, connectHardware: (deviceName, page, hdPath) => { - return dispatch(actions.connectHardware(deviceName, page, hdPath)) + return dispatch(actions.connectHardware(deviceName, page, hdPath)); }, checkHardwareStatus: (deviceName, hdPath) => { - return dispatch(actions.checkHardwareStatus(deviceName, hdPath)) + return dispatch(actions.checkHardwareStatus(deviceName, hdPath)); }, forgetDevice: (deviceName) => { - return dispatch(actions.forgetDevice(deviceName)) + return dispatch(actions.forgetDevice(deviceName)); }, unlockHardwareWalletAccount: (index, deviceName, hdPath) => { return dispatch( actions.unlockHardwareWalletAccount(index, deviceName, hdPath), - ) + ); }, showAlert: (msg) => dispatch(actions.showAlert(msg)), hideAlert: () => dispatch(actions.hideAlert()), - } -} + }; +}; ConnectHardwareForm.contextTypes = { t: PropTypes.func, metricsEvent: PropTypes.func, -} +}; -export default connect(mapStateToProps, mapDispatchToProps)(ConnectHardwareForm) +export default connect( + mapStateToProps, + mapDispatchToProps, +)(ConnectHardwareForm); diff --git a/ui/app/pages/create-account/connect-hardware/select-hardware.js b/ui/app/pages/create-account/connect-hardware/select-hardware.js index 5ffb728a5..040245c57 100644 --- a/ui/app/pages/create-account/connect-hardware/select-hardware.js +++ b/ui/app/pages/create-account/connect-hardware/select-hardware.js @@ -1,28 +1,28 @@ -import classnames from 'classnames' -import PropTypes from 'prop-types' -import React, { Component } from 'react' -import Button from '../../../components/ui/button' +import classnames from 'classnames'; +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import Button from '../../../components/ui/button'; export default class SelectHardware extends Component { static contextTypes = { t: PropTypes.func, - } + }; static propTypes = { connectToHardwareWallet: PropTypes.func.isRequired, browserSupported: PropTypes.bool.isRequired, - } + }; state = { selectedDevice: null, - } + }; connect = () => { if (this.state.selectedDevice) { - this.props.connectToHardwareWallet(this.state.selectedDevice) + this.props.connectToHardwareWallet(this.state.selectedDevice); } - return null - } + return null; + }; renderConnectToTrezorButton() { return ( @@ -38,7 +38,7 @@ export default class SelectHardware extends Component { alt="Trezor" /> - ) + ); } renderConnectToLedgerButton() { @@ -55,7 +55,7 @@ export default class SelectHardware extends Component { alt="Ledger" /> - ) + ); } renderButtons() { @@ -75,7 +75,7 @@ export default class SelectHardware extends Component { {this.context.t('connect')} - ) + ); } renderUnsupportedBrowser() { @@ -101,7 +101,7 @@ export default class SelectHardware extends Component { {this.context.t('downloadGoogleChrome')} - ) + ); } renderHeader() { @@ -114,26 +114,26 @@ export default class SelectHardware extends Component { {this.context.t('hardwareWalletsMsg')}

    - ) + ); } getAffiliateLinks() { const links = { trezor: `Trezor`, ledger: `Ledger`, - } + }; - const text = this.context.t('orderOneHere') + const text = this.context.t('orderOneHere'); const response = text .replace('Trezor', links.trezor) - .replace('Ledger', links.ledger) + .replace('Ledger', links.ledger); return (
    - ) + ); } renderTrezorAffiliateLink() { @@ -144,14 +144,14 @@ export default class SelectHardware extends Component {

    {this.getAffiliateLinks()}
    - ) + ); } scrollToTutorial = () => { if (this.referenceNode) { - this.referenceNode.scrollIntoView({ behavior: 'smooth' }) + this.referenceNode.scrollIntoView({ behavior: 'smooth' }); } - } + }; renderLearnMore() { return ( @@ -163,7 +163,7 @@ export default class SelectHardware extends Component { alt="" />

    - ) + ); } renderTutorialSteps() { @@ -186,13 +186,13 @@ export default class SelectHardware extends Component { title: this.context.t('step3HardwareWallet'), message: this.context.t('step3HardwareWalletMsg'), }, - ] + ]; return (
    { - this.referenceNode = node + this.referenceNode = node; }} > {steps.map((step, index) => ( @@ -208,7 +208,7 @@ export default class SelectHardware extends Component {
    ))} - ) + ); } renderFooter() { @@ -230,7 +230,7 @@ export default class SelectHardware extends Component {

    - ) + ); } renderConnectScreen() { @@ -243,13 +243,13 @@ export default class SelectHardware extends Component { {this.renderTutorialSteps()} {this.renderFooter()} - ) + ); } render() { if (this.props.browserSupported) { - return this.renderConnectScreen() + return this.renderConnectScreen(); } - return this.renderUnsupportedBrowser() + return this.renderUnsupportedBrowser(); } } diff --git a/ui/app/pages/create-account/create-account.component.js b/ui/app/pages/create-account/create-account.component.js index 1ec2e5258..4eaefce52 100644 --- a/ui/app/pages/create-account/create-account.component.js +++ b/ui/app/pages/create-account/create-account.component.js @@ -1,29 +1,29 @@ -import React, { Component } from 'react' -import { Switch, Route, matchPath } from 'react-router-dom' -import PropTypes from 'prop-types' -import classnames from 'classnames' +import React, { Component } from 'react'; +import { Switch, Route, matchPath } from 'react-router-dom'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; import { NEW_ACCOUNT_ROUTE, IMPORT_ACCOUNT_ROUTE, CONNECT_HARDWARE_ROUTE, -} from '../../helpers/constants/routes' -import NewAccountCreateForm from './new-account.container' -import NewAccountImportForm from './import-account' -import ConnectHardwareForm from './connect-hardware' +} from '../../helpers/constants/routes'; +import NewAccountCreateForm from './new-account.container'; +import NewAccountImportForm from './import-account'; +import ConnectHardwareForm from './connect-hardware'; export default class CreateAccountPage extends Component { renderTabs() { const { history, location: { pathname }, - } = this.props + } = this.props; const getClassNames = (path) => classnames('new-account__tabs__tab', { 'new-account__tabs__selected': matchPath(pathname, { path, exact: true, }), - }) + }); return (
    @@ -46,7 +46,7 @@ export default class CreateAccountPage extends Component { {this.context.t('hardware')}
    - ) + ); } render() { @@ -79,15 +79,15 @@ export default class CreateAccountPage extends Component { - ) + ); } } CreateAccountPage.propTypes = { location: PropTypes.object, history: PropTypes.object, -} +}; CreateAccountPage.contextTypes = { t: PropTypes.func, -} +}; diff --git a/ui/app/pages/create-account/import-account/index.js b/ui/app/pages/create-account/import-account/index.js index 0b7e45cf9..8068773c3 100644 --- a/ui/app/pages/create-account/import-account/index.js +++ b/ui/app/pages/create-account/import-account/index.js @@ -1,40 +1,40 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import Select from 'react-select' +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import Select from 'react-select'; // Subviews -import JsonImportView from './json' -import PrivateKeyImportView from './private-key' +import JsonImportView from './json'; +import PrivateKeyImportView from './private-key'; export default class AccountImportSubview extends Component { static contextTypes = { t: PropTypes.func, - } + }; - state = {} + state = {}; getMenuItemTexts() { - return [this.context.t('privateKey'), this.context.t('jsonFile')] + return [this.context.t('privateKey'), this.context.t('jsonFile')]; } renderImportView() { - const { type } = this.state - const menuItems = this.getMenuItemTexts() - const current = type || menuItems[0] + const { type } = this.state; + const menuItems = this.getMenuItemTexts(); + const current = type || menuItems[0]; switch (current) { case this.context.t('privateKey'): - return + return ; case this.context.t('jsonFile'): - return + return ; default: - return + return ; } } render() { - const menuItems = this.getMenuItemTexts() - const { type } = this.state + const menuItems = this.getMenuItemTexts(); + const { type } = this.state; return (
    @@ -49,7 +49,7 @@ export default class AccountImportSubview extends Component { global.platform.openTab({ url: 'https://metamask.zendesk.com/hc/en-us/articles/360015289932', - }) + }); }} > {this.context.t('here')} @@ -68,15 +68,15 @@ export default class AccountImportSubview extends Component { return { value: text, label: text, - } + }; })} onChange={(opt) => { - this.setState({ type: opt.value }) + this.setState({ type: opt.value }); }} />
    {this.renderImportView()} - ) + ); } } diff --git a/ui/app/pages/create-account/import-account/json.js b/ui/app/pages/create-account/import-account/json.js index 34eadaf84..afaeb7751 100644 --- a/ui/app/pages/create-account/import-account/json.js +++ b/ui/app/pages/create-account/import-account/json.js @@ -1,28 +1,28 @@ -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 FileInput from 'react-simple-file-input' -import * as actions from '../../../store/actions' -import { getMetaMaskAccounts } from '../../../selectors' -import Button from '../../../components/ui/button' -import { getMostRecentOverviewPage } from '../../../ducks/history/history' +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 FileInput from 'react-simple-file-input'; +import * as actions from '../../../store/actions'; +import { getMetaMaskAccounts } from '../../../selectors'; +import Button from '../../../components/ui/button'; +import { getMostRecentOverviewPage } from '../../../ducks/history/history'; const HELP_LINK = - 'https://metamask.zendesk.com/hc/en-us/articles/360015489331-Importing-an-Account' + 'https://metamask.zendesk.com/hc/en-us/articles/360015489331-Importing-an-Account'; class JsonImportSubview extends Component { state = { fileContents: '', isEmpty: true, - } + }; - inputRef = React.createRef() + inputRef = React.createRef(); render() { - const { error, history, mostRecentOverviewPage } = this.props - const enabled = !this.state.isEmpty && this.state.fileContents !== '' + const { error, history, mostRecentOverviewPage } = this.props; + const enabled = !this.state.isEmpty && this.state.fileContents !== ''; return (
    @@ -76,19 +76,19 @@ class JsonImportSubview extends Component {
    {error ? {error} : null} - ) + ); } onLoad(event) { this.setState({ fileContents: event.target.result, - }) + }); } createKeyringOnEnter(event) { if (event.key === 'Enter') { - event.preventDefault() - this.createNewKeychain() + event.preventDefault(); + this.createNewKeychain(); } } @@ -100,51 +100,51 @@ class JsonImportSubview extends Component { importNewJsonAccount, mostRecentOverviewPage, setSelectedAddress, - } = this.props - const { fileContents } = this.state + } = this.props; + const { fileContents } = this.state; if (!fileContents) { - const message = this.context.t('needImportFile') - displayWarning(message) - return + const message = this.context.t('needImportFile'); + displayWarning(message); + return; } - const password = this.inputRef.current.value + const password = this.inputRef.current.value; importNewJsonAccount([fileContents, password]) .then(({ selectedAddress }) => { if (selectedAddress) { - history.push(mostRecentOverviewPage) + history.push(mostRecentOverviewPage); this.context.metricsEvent({ eventOpts: { category: 'Accounts', action: 'Import Account', name: 'Imported Account with JSON', }, - }) - displayWarning(null) + }); + displayWarning(null); } else { - displayWarning('Error importing account.') + displayWarning('Error importing account.'); this.context.metricsEvent({ eventOpts: { category: 'Accounts', action: 'Import Account', name: 'Error importing JSON', }, - }) - setSelectedAddress(firstAddress) + }); + setSelectedAddress(firstAddress); } }) - .catch((err) => err && displayWarning(err.message || err)) + .catch((err) => err && displayWarning(err.message || err)); } checkInputEmpty() { - const password = this.inputRef.current.value - let isEmpty = true + const password = this.inputRef.current.value; + let isEmpty = true; if (password !== '') { - isEmpty = false + isEmpty = false; } - this.setState({ isEmpty }) + this.setState({ isEmpty }); } } @@ -156,15 +156,15 @@ JsonImportSubview.propTypes = { 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 { @@ -173,15 +173,15 @@ const mapDispatchToProps = (dispatch) => { dispatch(actions.importNewAccount('JSON File', options)), setSelectedAddress: (address) => dispatch(actions.setSelectedAddress(address)), - } -} + }; +}; JsonImportSubview.contextTypes = { t: PropTypes.func, metricsEvent: PropTypes.func, -} +}; export default compose( withRouter, connect(mapStateToProps, mapDispatchToProps), -)(JsonImportSubview) +)(JsonImportSubview); diff --git a/ui/app/pages/create-account/import-account/private-key.js b/ui/app/pages/create-account/import-account/private-key.js index e2f78ada4..c360424be 100644 --- a/ui/app/pages/create-account/import-account/private-key.js +++ b/ui/app/pages/create-account/import-account/private-key.js @@ -1,18 +1,18 @@ -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 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'; class PrivateKeyImportView extends Component { static contextTypes = { t: PropTypes.func, metricsEvent: PropTypes.func, - } + }; static propTypes = { importNewAccount: PropTypes.func.isRequired, @@ -22,14 +22,14 @@ class PrivateKeyImportView extends Component { firstAddress: PropTypes.string.isRequired, error: PropTypes.node, mostRecentOverviewPage: PropTypes.string.isRequired, - } + }; - inputRef = React.createRef() + inputRef = React.createRef(); - state = { isEmpty: true } + state = { isEmpty: true }; createNewKeychain() { - const privateKey = this.inputRef.current.value + const privateKey = this.inputRef.current.value; const { importNewAccount, history, @@ -37,7 +37,7 @@ class PrivateKeyImportView extends Component { mostRecentOverviewPage, setSelectedAddress, firstAddress, - } = this.props + } = this.props; importNewAccount('Private Key', [privateKey]) .then(({ selectedAddress }) => { @@ -48,42 +48,42 @@ class PrivateKeyImportView extends Component { action: 'Import Account', name: 'Imported Account with Private Key', }, - }) - history.push(mostRecentOverviewPage) - displayWarning(null) + }); + history.push(mostRecentOverviewPage); + displayWarning(null); } else { - displayWarning('Error importing account.') + displayWarning('Error importing account.'); this.context.metricsEvent({ eventOpts: { category: 'Accounts', action: 'Import Account', name: 'Error importing with Private Key', }, - }) - setSelectedAddress(firstAddress) + }); + setSelectedAddress(firstAddress); } }) - .catch((err) => err && displayWarning(err.message || err)) + .catch((err) => err && displayWarning(err.message || err)); } createKeyringOnEnter = (event) => { if (event.key === 'Enter') { - event.preventDefault() - this.createNewKeychain() + event.preventDefault(); + this.createNewKeychain(); } - } + }; checkInputEmpty() { - const privateKey = this.inputRef.current.value - let isEmpty = true + const privateKey = this.inputRef.current.value; + let isEmpty = true; if (privateKey !== '') { - isEmpty = false + isEmpty = false; } - this.setState({ isEmpty }) + this.setState({ isEmpty }); } render() { - const { error, displayWarning } = this.props + const { error, displayWarning } = this.props; return (
    @@ -107,9 +107,9 @@ class PrivateKeyImportView extends Component { large className="new-account-create-form__button" onClick={() => { - const { history, mostRecentOverviewPage } = this.props - displayWarning(null) - history.push(mostRecentOverviewPage) + const { history, mostRecentOverviewPage } = this.props; + displayWarning(null); + history.push(mostRecentOverviewPage); }} > {this.context.t('cancel')} @@ -126,31 +126,31 @@ class PrivateKeyImportView extends Component {
    {error ? {error} : null} - ) + ); } } export default compose( withRouter, connect(mapStateToProps, mapDispatchToProps), -)(PrivateKeyImportView) +)(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])) + return dispatch(actions.importNewAccount(strategy, [privateKey])); }, displayWarning: (message) => dispatch(actions.displayWarning(message || null)), setSelectedAddress: (address) => dispatch(actions.setSelectedAddress(address)), - } + }; } diff --git a/ui/app/pages/create-account/index.js b/ui/app/pages/create-account/index.js index a736bfff7..ebf30f7c7 100644 --- a/ui/app/pages/create-account/index.js +++ b/ui/app/pages/create-account/index.js @@ -1 +1 @@ -export { default } from './create-account.component' +export { default } from './create-account.component'; diff --git a/ui/app/pages/create-account/new-account.component.js b/ui/app/pages/create-account/new-account.component.js index 92f832a23..252eb2821 100644 --- a/ui/app/pages/create-account/new-account.component.js +++ b/ui/app/pages/create-account/new-account.component.js @@ -1,22 +1,22 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import Button from '../../components/ui/button' +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import Button from '../../components/ui/button'; export default class NewAccountCreateForm extends Component { static defaultProps = { newAccountNumber: 0, - } + }; state = { newAccountName: '', defaultAccountName: this.context.t('newAccountNumberName', [ this.props.newAccountNumber, ]), - } + }; render() { - const { newAccountName, defaultAccountName } = this.state - const { history, createAccount, mostRecentOverviewPage } = this.props + const { newAccountName, defaultAccountName } = this.state; + const { history, createAccount, mostRecentOverviewPage } = this.props; const createClick = (_) => { createAccount(newAccountName || defaultAccountName) .then(() => { @@ -26,8 +26,8 @@ export default class NewAccountCreateForm extends Component { action: 'Add New Account', name: 'Added New Account', }, - }) - history.push(mostRecentOverviewPage) + }); + history.push(mostRecentOverviewPage); }) .catch((e) => { this.context.metricsEvent({ @@ -39,9 +39,9 @@ export default class NewAccountCreateForm extends Component { customVariables: { errorMessage: e.message, }, - }) - }) - } + }); + }); + }; return (
    @@ -78,7 +78,7 @@ export default class NewAccountCreateForm extends Component {
    - ) + ); } } @@ -87,9 +87,9 @@ NewAccountCreateForm.propTypes = { newAccountNumber: PropTypes.number, history: PropTypes.object, mostRecentOverviewPage: PropTypes.string.isRequired, -} +}; NewAccountCreateForm.contextTypes = { t: PropTypes.func, metricsEvent: PropTypes.func, -} +}; diff --git a/ui/app/pages/create-account/new-account.container.js b/ui/app/pages/create-account/new-account.container.js index 833d7143c..d37c8f30c 100644 --- a/ui/app/pages/create-account/new-account.container.js +++ b/ui/app/pages/create-account/new-account.container.js @@ -1,34 +1,34 @@ -import { connect } from 'react-redux' -import * as actions from '../../store/actions' -import { getMostRecentOverviewPage } from '../../ducks/history/history' -import NewAccountCreateForm from './new-account.component' +import { connect } from 'react-redux'; +import * as actions from '../../store/actions'; +import { getMostRecentOverviewPage } from '../../ducks/history/history'; +import NewAccountCreateForm from './new-account.component'; const mapStateToProps = (state) => { const { metamask: { identities = {} }, - } = state - const numberOfExistingAccounts = Object.keys(identities).length - const newAccountNumber = numberOfExistingAccounts + 1 + } = state; + const numberOfExistingAccounts = Object.keys(identities).length; + const newAccountNumber = numberOfExistingAccounts + 1; return { newAccountNumber, mostRecentOverviewPage: getMostRecentOverviewPage(state), - } -} + }; +}; const mapDispatchToProps = (dispatch) => { return { createAccount: (newAccountName) => { return dispatch(actions.addNewAccount()).then((newAccountAddress) => { if (newAccountName) { - dispatch(actions.setAccountLabel(newAccountAddress, newAccountName)) + dispatch(actions.setAccountLabel(newAccountAddress, newAccountName)); } - }) + }); }, - } -} + }; +}; export default connect( mapStateToProps, mapDispatchToProps, -)(NewAccountCreateForm) +)(NewAccountCreateForm); diff --git a/ui/app/pages/create-account/tests/create-account.test.js b/ui/app/pages/create-account/tests/create-account.test.js index 335d3c5ba..0c564a64b 100644 --- a/ui/app/pages/create-account/tests/create-account.test.js +++ b/ui/app/pages/create-account/tests/create-account.test.js @@ -1,11 +1,11 @@ -import assert from 'assert' -import React from 'react' -import sinon from 'sinon' -import { mountWithRouter } from '../../../../../test/lib/render-helpers' -import CreateAccountPage from '..' +import assert from 'assert'; +import React from 'react'; +import sinon from 'sinon'; +import { mountWithRouter } from '../../../../../test/lib/render-helpers'; +import CreateAccountPage from '..'; describe('Create Account Page', function () { - let wrapper + let wrapper; const props = { history: { @@ -14,37 +14,37 @@ describe('Create Account Page', function () { location: { pathname: '/new-account', }, - } + }; before(function () { - wrapper = mountWithRouter() - }) + wrapper = mountWithRouter(); + }); afterEach(function () { - props.history.push.resetHistory() - }) + props.history.push.resetHistory(); + }); it('clicks create account and routes to new-account path', function () { - const createAccount = wrapper.find('.new-account__tabs__tab').at(0) - createAccount.simulate('click') - assert.strictEqual(props.history.push.getCall(0).args[0], '/new-account') - }) + const createAccount = wrapper.find('.new-account__tabs__tab').at(0); + createAccount.simulate('click'); + assert.strictEqual(props.history.push.getCall(0).args[0], '/new-account'); + }); it('clicks import account and routes to import new account path', function () { - const importAccount = wrapper.find('.new-account__tabs__tab').at(1) - importAccount.simulate('click') + const importAccount = wrapper.find('.new-account__tabs__tab').at(1); + importAccount.simulate('click'); assert.strictEqual( props.history.push.getCall(0).args[0], '/new-account/import', - ) - }) + ); + }); it('clicks connect HD Wallet and routes to connect new account path', function () { - const connectHdWallet = wrapper.find('.new-account__tabs__tab').at(2) - connectHdWallet.simulate('click') + const connectHdWallet = wrapper.find('.new-account__tabs__tab').at(2); + connectHdWallet.simulate('click'); assert.strictEqual( props.history.push.getCall(0).args[0], '/new-account/connect', - ) - }) -}) + ); + }); +}); diff --git a/ui/app/pages/error/error.component.js b/ui/app/pages/error/error.component.js index e7e9ff6ed..22d7f5229 100644 --- a/ui/app/pages/error/error.component.js +++ b/ui/app/pages/error/error.component.js @@ -1,23 +1,23 @@ -import React, { PureComponent } from 'react' -import PropTypes from 'prop-types' -import { getEnvironmentType } from '../../../../app/scripts/lib/util' -import { ENVIRONMENT_TYPE_POPUP } from '../../../../shared/constants/app' +import React, { PureComponent } from 'react'; +import PropTypes from 'prop-types'; +import { getEnvironmentType } from '../../../../app/scripts/lib/util'; +import { ENVIRONMENT_TYPE_POPUP } from '../../../../shared/constants/app'; class ErrorPage extends PureComponent { static contextTypes = { t: PropTypes.func.isRequired, - } + }; static propTypes = { error: PropTypes.object.isRequired, - } + }; renderErrorDetail(content) { return (
  • {content}

  • - ) + ); } renderErrorStack(title, stack) { @@ -26,14 +26,14 @@ class ErrorPage extends PureComponent { {title}
    {stack}
    - ) + ); } render() { - const { error } = this.props - const { t } = this.context + const { error } = this.props; + const { t } = this.context; - const isPopup = getEnvironmentType() === ENVIRONMENT_TYPE_POPUP + const isPopup = getEnvironmentType() === ENVIRONMENT_TYPE_POPUP; return (
    @@ -61,8 +61,8 @@ class ErrorPage extends PureComponent {
    - ) + ); } } -export default ErrorPage +export default ErrorPage; diff --git a/ui/app/pages/error/index.js b/ui/app/pages/error/index.js index c2a9f62d9..386b79786 100644 --- a/ui/app/pages/error/index.js +++ b/ui/app/pages/error/index.js @@ -1 +1 @@ -export { default } from './error.component' +export { default } from './error.component'; diff --git a/ui/app/pages/first-time-flow/create-password/create-password.component.js b/ui/app/pages/first-time-flow/create-password/create-password.component.js index b249c3aba..6913c10fa 100644 --- a/ui/app/pages/first-time-flow/create-password/create-password.component.js +++ b/ui/app/pages/first-time-flow/create-password/create-password.component.js @@ -1,14 +1,14 @@ -import React, { PureComponent } from 'react' -import PropTypes from 'prop-types' -import { Switch, Route } from 'react-router-dom' -import MetaFoxLogo from '../../../components/ui/metafox-logo' +import React, { PureComponent } from 'react'; +import PropTypes from 'prop-types'; +import { Switch, Route } from 'react-router-dom'; +import MetaFoxLogo from '../../../components/ui/metafox-logo'; import { INITIALIZE_CREATE_PASSWORD_ROUTE, INITIALIZE_IMPORT_WITH_SEED_PHRASE_ROUTE, INITIALIZE_SEED_PHRASE_ROUTE, -} from '../../../helpers/constants/routes' -import NewAccount from './new-account' -import ImportWithSeedPhrase from './import-with-seed-phrase' +} from '../../../helpers/constants/routes'; +import NewAccount from './new-account'; +import ImportWithSeedPhrase from './import-with-seed-phrase'; export default class CreatePassword extends PureComponent { static propTypes = { @@ -16,18 +16,18 @@ export default class CreatePassword extends PureComponent { isInitialized: PropTypes.bool, onCreateNewAccount: PropTypes.func, onCreateNewAccountFromSeed: PropTypes.func, - } + }; componentDidMount() { - const { isInitialized, history } = this.props + const { isInitialized, history } = this.props; if (isInitialized) { - history.push(INITIALIZE_SEED_PHRASE_ROUTE) + history.push(INITIALIZE_SEED_PHRASE_ROUTE); } } render() { - const { onCreateNewAccount, onCreateNewAccountFromSeed } = this.props + const { onCreateNewAccount, onCreateNewAccountFromSeed } = this.props; return (
    @@ -52,6 +52,6 @@ export default class CreatePassword extends PureComponent { />
    - ) + ); } } diff --git a/ui/app/pages/first-time-flow/create-password/create-password.container.js b/ui/app/pages/first-time-flow/create-password/create-password.container.js index 9e8d12870..ccb35af75 100644 --- a/ui/app/pages/first-time-flow/create-password/create-password.container.js +++ b/ui/app/pages/first-time-flow/create-password/create-password.container.js @@ -1,14 +1,14 @@ -import { connect } from 'react-redux' -import CreatePassword from './create-password.component' +import { connect } from 'react-redux'; +import CreatePassword from './create-password.component'; const mapStateToProps = (state) => { const { metamask: { isInitialized }, - } = state + } = state; return { isInitialized, - } -} + }; +}; -export default connect(mapStateToProps)(CreatePassword) +export default connect(mapStateToProps)(CreatePassword); diff --git a/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/import-with-seed-phrase.component.js b/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/import-with-seed-phrase.component.js index b9de02575..5bb58fd66 100644 --- a/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/import-with-seed-phrase.component.js +++ b/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/import-with-seed-phrase.component.js @@ -1,27 +1,27 @@ -import { ethers } from 'ethers' -import React, { PureComponent } from 'react' -import PropTypes from 'prop-types' -import TextField from '../../../../components/ui/text-field' -import Button from '../../../../components/ui/button' +import { ethers } from 'ethers'; +import React, { PureComponent } from 'react'; +import PropTypes from 'prop-types'; +import TextField from '../../../../components/ui/text-field'; +import Button from '../../../../components/ui/button'; import { INITIALIZE_SELECT_ACTION_ROUTE, INITIALIZE_END_OF_FLOW_ROUTE, -} from '../../../../helpers/constants/routes' +} from '../../../../helpers/constants/routes'; -const { isValidMnemonic } = ethers.utils +const { isValidMnemonic } = ethers.utils; export default class ImportWithSeedPhrase extends PureComponent { static contextTypes = { t: PropTypes.func, metricsEvent: PropTypes.func, - } + }; static propTypes = { history: PropTypes.object, onSubmit: PropTypes.func.isRequired, setSeedPhraseBackedUp: PropTypes.func, initializeThreeBox: PropTypes.func, - } + }; state = { seedPhrase: '', @@ -32,10 +32,10 @@ export default class ImportWithSeedPhrase extends PureComponent { passwordError: '', confirmPasswordError: '', termsChecked: false, - } + }; parseSeedPhrase = (seedPhrase) => - (seedPhrase || '').trim().toLowerCase().match(/\w+/gu)?.join(' ') || '' + (seedPhrase || '').trim().toLowerCase().match(/\w+/gu)?.join(' ') || ''; UNSAFE_componentWillMount() { this._onBeforeUnload = () => @@ -49,105 +49,105 @@ export default class ImportWithSeedPhrase extends PureComponent { errorLabel: 'Seed Phrase Error', errorMessage: this.state.seedPhraseError, }, - }) - window.addEventListener('beforeunload', this._onBeforeUnload) + }); + window.addEventListener('beforeunload', this._onBeforeUnload); } componentWillUnmount() { - window.removeEventListener('beforeunload', this._onBeforeUnload) + window.removeEventListener('beforeunload', this._onBeforeUnload); } handleSeedPhraseChange(seedPhrase) { - let seedPhraseError = '' + let seedPhraseError = ''; if (seedPhrase) { - const parsedSeedPhrase = this.parseSeedPhrase(seedPhrase) - const wordCount = parsedSeedPhrase.split(/\s/u).length + const parsedSeedPhrase = this.parseSeedPhrase(seedPhrase); + const wordCount = parsedSeedPhrase.split(/\s/u).length; if (wordCount % 3 !== 0 || wordCount > 24 || wordCount < 12) { - seedPhraseError = this.context.t('seedPhraseReq') + seedPhraseError = this.context.t('seedPhraseReq'); } else if (!isValidMnemonic(parsedSeedPhrase)) { - seedPhraseError = this.context.t('invalidSeedPhrase') + seedPhraseError = this.context.t('invalidSeedPhrase'); } } - this.setState({ seedPhrase, seedPhraseError }) + this.setState({ seedPhrase, seedPhraseError }); } handlePasswordChange(password) { - const { t } = this.context + const { t } = this.context; this.setState((state) => { - const { confirmPassword } = state - let confirmPasswordError = '' - let passwordError = '' + const { confirmPassword } = state; + let confirmPasswordError = ''; + let passwordError = ''; if (password && password.length < 8) { - passwordError = t('passwordNotLongEnough') + passwordError = t('passwordNotLongEnough'); } if (confirmPassword && password !== confirmPassword) { - confirmPasswordError = t('passwordsDontMatch') + confirmPasswordError = t('passwordsDontMatch'); } return { password, passwordError, confirmPasswordError, - } - }) + }; + }); } handleConfirmPasswordChange(confirmPassword) { - const { t } = this.context + const { t } = this.context; this.setState((state) => { - const { password } = state - let confirmPasswordError = '' + const { password } = state; + let confirmPasswordError = ''; if (password !== confirmPassword) { - confirmPasswordError = t('passwordsDontMatch') + confirmPasswordError = t('passwordsDontMatch'); } return { confirmPassword, confirmPasswordError, - } - }) + }; + }); } handleImport = async (event) => { - event.preventDefault() + event.preventDefault(); if (!this.isValid()) { - return + return; } - const { password, seedPhrase } = this.state + const { password, seedPhrase } = this.state; const { history, onSubmit, setSeedPhraseBackedUp, initializeThreeBox, - } = this.props + } = this.props; try { - await onSubmit(password, this.parseSeedPhrase(seedPhrase)) + await onSubmit(password, this.parseSeedPhrase(seedPhrase)); this.context.metricsEvent({ eventOpts: { category: 'Onboarding', action: 'Import Seed Phrase', name: 'Import Complete', }, - }) + }); setSeedPhraseBackedUp(true).then(async () => { - initializeThreeBox() - history.push(INITIALIZE_END_OF_FLOW_ROUTE) - }) + initializeThreeBox(); + history.push(INITIALIZE_END_OF_FLOW_ROUTE); + }); } catch (error) { - this.setState({ seedPhraseError: error.message }) + this.setState({ seedPhraseError: error.message }); } - } + }; isValid() { const { @@ -157,7 +157,7 @@ export default class ImportWithSeedPhrase extends PureComponent { passwordError, confirmPasswordError, seedPhraseError, - } = this.state + } = this.state; if ( !password || @@ -165,21 +165,21 @@ export default class ImportWithSeedPhrase extends PureComponent { !seedPhrase || password !== confirmPassword ) { - return false + return false; } if (password.length < 8) { - return false + return false; } - return !passwordError && !confirmPasswordError && !seedPhraseError + return !passwordError && !confirmPasswordError && !seedPhraseError; } onTermsKeyPress = ({ key }) => { if (key === ' ' || key === 'Enter') { - this.toggleTermsCheck() + this.toggleTermsCheck(); } - } + }; toggleTermsCheck = () => { this.context.metricsEvent({ @@ -188,34 +188,34 @@ export default class ImportWithSeedPhrase extends PureComponent { action: 'Import Seed Phrase', name: 'Check ToS', }, - }) + }); this.setState((prevState) => ({ termsChecked: !prevState.termsChecked, - })) - } + })); + }; toggleShowSeedPhrase = () => { this.setState(({ showSeedPhrase }) => ({ showSeedPhrase: !showSeedPhrase, - })) - } + })); + }; render() { - const { t } = this.context + const { t } = this.context; const { seedPhraseError, showSeedPhrase, passwordError, confirmPasswordError, termsChecked, - } = this.state + } = this.state; return (
    { - e.preventDefault() + e.preventDefault(); this.context.metricsEvent({ eventOpts: { category: 'Onboarding', @@ -226,8 +226,8 @@ export default class ImportWithSeedPhrase extends PureComponent { errorLabel: 'Seed Phrase Error', errorMessage: seedPhraseError, }, - }) - this.props.history.push(INITIALIZE_SELECT_ACTION_ROUTE) + }); + this.props.history.push(INITIALIZE_SELECT_ACTION_ROUTE); }} href="#" > @@ -342,6 +342,6 @@ export default class ImportWithSeedPhrase extends PureComponent { {t('import')} - ) + ); } } diff --git a/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/import-with-seed-phrase.container.js b/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/import-with-seed-phrase.container.js index 7da5af5a1..7d2fef50f 100644 --- a/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/import-with-seed-phrase.container.js +++ b/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/import-with-seed-phrase.container.js @@ -1,16 +1,16 @@ -import { connect } from 'react-redux' +import { connect } from 'react-redux'; import { setSeedPhraseBackedUp, initializeThreeBox, -} from '../../../../store/actions' -import ImportWithSeedPhrase from './import-with-seed-phrase.component' +} from '../../../../store/actions'; +import ImportWithSeedPhrase from './import-with-seed-phrase.component'; const mapDispatchToProps = (dispatch) => { return { setSeedPhraseBackedUp: (seedPhraseBackupState) => dispatch(setSeedPhraseBackedUp(seedPhraseBackupState)), initializeThreeBox: () => dispatch(initializeThreeBox()), - } -} + }; +}; -export default connect(null, mapDispatchToProps)(ImportWithSeedPhrase) +export default connect(null, mapDispatchToProps)(ImportWithSeedPhrase); diff --git a/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/index.js b/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/index.js index 9d4ad7d0f..3e192d728 100644 --- a/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/index.js +++ b/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/index.js @@ -1 +1 @@ -export { default } from './import-with-seed-phrase.container' +export { default } from './import-with-seed-phrase.container'; diff --git a/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/tests/import-with-seed-phrase.component.test.js b/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/tests/import-with-seed-phrase.component.test.js index 7aea35494..57e8ddcee 100644 --- a/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/tests/import-with-seed-phrase.component.test.js +++ b/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/tests/import-with-seed-phrase.component.test.js @@ -1,8 +1,8 @@ -import assert from 'assert' -import React from 'react' -import { shallow } from 'enzyme' -import sinon from 'sinon' -import ImportWithSeedPhrase from '../import-with-seed-phrase.component' +import assert from 'assert'; +import React from 'react'; +import { shallow } from 'enzyme'; +import sinon from 'sinon'; +import ImportWithSeedPhrase from '../import-with-seed-phrase.component'; function shallowRender(props = {}, context = {}) { return shallow(, { @@ -11,91 +11,91 @@ function shallowRender(props = {}, context = {}) { metricsEvent: sinon.spy(), ...context, }, - }) + }); } describe('ImportWithSeedPhrase Component', function () { it('should render without error', function () { const root = shallowRender({ onSubmit: sinon.spy(), - }) - const textareaCount = root.find('.first-time-flow__textarea').length - assert.strictEqual(textareaCount, 1, 'should render 12 seed phrases') - }) + }); + const textareaCount = root.find('.first-time-flow__textarea').length; + assert.strictEqual(textareaCount, 1, 'should render 12 seed phrases'); + }); describe('parseSeedPhrase', function () { it('should handle a regular seed phrase', function () { const root = shallowRender({ onSubmit: sinon.spy(), - }) + }); - const { parseSeedPhrase } = root.instance() + const { parseSeedPhrase } = root.instance(); - assert.deepStrictEqual(parseSeedPhrase('foo bar baz'), 'foo bar baz') - }) + assert.deepStrictEqual(parseSeedPhrase('foo bar baz'), 'foo bar baz'); + }); it('should handle a mixed-case seed phrase', function () { const root = shallowRender({ onSubmit: sinon.spy(), - }) + }); - const { parseSeedPhrase } = root.instance() + const { parseSeedPhrase } = root.instance(); - assert.deepStrictEqual(parseSeedPhrase('FOO bAr baZ'), 'foo bar baz') - }) + assert.deepStrictEqual(parseSeedPhrase('FOO bAr baZ'), 'foo bar baz'); + }); it('should handle an upper-case seed phrase', function () { const root = shallowRender({ onSubmit: sinon.spy(), - }) + }); - const { parseSeedPhrase } = root.instance() + const { parseSeedPhrase } = root.instance(); - assert.deepStrictEqual(parseSeedPhrase('FOO BAR BAZ'), 'foo bar baz') - }) + assert.deepStrictEqual(parseSeedPhrase('FOO BAR BAZ'), 'foo bar baz'); + }); it('should trim extraneous whitespace from the given seed phrase', function () { const root = shallowRender({ onSubmit: sinon.spy(), - }) + }); - const { parseSeedPhrase } = root.instance() + const { parseSeedPhrase } = root.instance(); assert.deepStrictEqual( parseSeedPhrase(' foo bar baz '), 'foo bar baz', - ) - }) + ); + }); it('should return an empty string when given a whitespace-only string', function () { const root = shallowRender({ onSubmit: sinon.spy(), - }) + }); - const { parseSeedPhrase } = root.instance() + const { parseSeedPhrase } = root.instance(); - assert.deepStrictEqual(parseSeedPhrase(' '), '') - }) + assert.deepStrictEqual(parseSeedPhrase(' '), ''); + }); it('should return an empty string when given a string with only symbols', function () { const root = shallowRender({ onSubmit: sinon.spy(), - }) + }); - const { parseSeedPhrase } = root.instance() + const { parseSeedPhrase } = root.instance(); - assert.deepStrictEqual(parseSeedPhrase('$'), '') - }) + assert.deepStrictEqual(parseSeedPhrase('$'), ''); + }); it('should return an empty string for both null and undefined', function () { const root = shallowRender({ onSubmit: sinon.spy(), - }) + }); - const { parseSeedPhrase } = root.instance() + const { parseSeedPhrase } = root.instance(); - assert.deepStrictEqual(parseSeedPhrase(undefined), '') - assert.deepStrictEqual(parseSeedPhrase(null), '') - }) - }) -}) + assert.deepStrictEqual(parseSeedPhrase(undefined), ''); + assert.deepStrictEqual(parseSeedPhrase(null), ''); + }); + }); +}); diff --git a/ui/app/pages/first-time-flow/create-password/index.js b/ui/app/pages/first-time-flow/create-password/index.js index 42e7436f9..d4baaac71 100644 --- a/ui/app/pages/first-time-flow/create-password/index.js +++ b/ui/app/pages/first-time-flow/create-password/index.js @@ -1 +1 @@ -export { default } from './create-password.container' +export { default } from './create-password.container'; diff --git a/ui/app/pages/first-time-flow/create-password/new-account/index.js b/ui/app/pages/first-time-flow/create-password/new-account/index.js index 97db39cc3..f12222878 100644 --- a/ui/app/pages/first-time-flow/create-password/new-account/index.js +++ b/ui/app/pages/first-time-flow/create-password/new-account/index.js @@ -1 +1 @@ -export { default } from './new-account.component' +export { default } from './new-account.component'; diff --git a/ui/app/pages/first-time-flow/create-password/new-account/new-account.component.js b/ui/app/pages/first-time-flow/create-password/new-account/new-account.component.js index 0f86a5d7b..b74cce8a9 100644 --- a/ui/app/pages/first-time-flow/create-password/new-account/new-account.component.js +++ b/ui/app/pages/first-time-flow/create-password/new-account/new-account.component.js @@ -1,22 +1,22 @@ -import React, { PureComponent } from 'react' -import PropTypes from 'prop-types' -import Button from '../../../../components/ui/button' +import React, { PureComponent } from 'react'; +import PropTypes from 'prop-types'; +import Button from '../../../../components/ui/button'; import { INITIALIZE_SEED_PHRASE_ROUTE, INITIALIZE_SELECT_ACTION_ROUTE, -} from '../../../../helpers/constants/routes' -import TextField from '../../../../components/ui/text-field' +} from '../../../../helpers/constants/routes'; +import TextField from '../../../../components/ui/text-field'; export default class NewAccount extends PureComponent { static contextTypes = { metricsEvent: PropTypes.func, t: PropTypes.func, - } + }; static propTypes = { onSubmit: PropTypes.func.isRequired, history: PropTypes.object.isRequired, - } + }; state = { password: '', @@ -24,7 +24,7 @@ export default class NewAccount extends PureComponent { passwordError: '', confirmPasswordError: '', termsChecked: false, - } + }; isValid() { const { @@ -32,73 +32,73 @@ export default class NewAccount extends PureComponent { confirmPassword, passwordError, confirmPasswordError, - } = this.state + } = this.state; if (!password || !confirmPassword || password !== confirmPassword) { - return false + return false; } if (password.length < 8) { - return false + return false; } - return !passwordError && !confirmPasswordError + return !passwordError && !confirmPasswordError; } handlePasswordChange(password) { - const { t } = this.context + const { t } = this.context; this.setState((state) => { - const { confirmPassword } = state - let passwordError = '' - let confirmPasswordError = '' + const { confirmPassword } = state; + let passwordError = ''; + let confirmPasswordError = ''; if (password && password.length < 8) { - passwordError = t('passwordNotLongEnough') + passwordError = t('passwordNotLongEnough'); } if (confirmPassword && password !== confirmPassword) { - confirmPasswordError = t('passwordsDontMatch') + confirmPasswordError = t('passwordsDontMatch'); } return { password, passwordError, confirmPasswordError, - } - }) + }; + }); } handleConfirmPasswordChange(confirmPassword) { - const { t } = this.context + const { t } = this.context; this.setState((state) => { - const { password } = state - let confirmPasswordError = '' + const { password } = state; + let confirmPasswordError = ''; if (password !== confirmPassword) { - confirmPasswordError = t('passwordsDontMatch') + confirmPasswordError = t('passwordsDontMatch'); } return { confirmPassword, confirmPasswordError, - } - }) + }; + }); } handleCreate = async (event) => { - event.preventDefault() + event.preventDefault(); if (!this.isValid()) { - return + return; } - const { password } = this.state - const { onSubmit, history } = this.props + const { password } = this.state; + const { onSubmit, history } = this.props; try { - await onSubmit(password) + await onSubmit(password); this.context.metricsEvent({ eventOpts: { @@ -106,13 +106,13 @@ export default class NewAccount extends PureComponent { action: 'Create Password', name: 'Submit Password', }, - }) + }); - history.push(INITIALIZE_SEED_PHRASE_ROUTE) + history.push(INITIALIZE_SEED_PHRASE_ROUTE); } catch (error) { - this.setState({ passwordError: error.message }) + this.setState({ passwordError: error.message }); } - } + }; toggleTermsCheck = () => { this.context.metricsEvent({ @@ -121,43 +121,43 @@ export default class NewAccount extends PureComponent { action: 'Create Password', name: 'Check ToS', }, - }) + }); this.setState((prevState) => ({ termsChecked: !prevState.termsChecked, - })) - } + })); + }; onTermsKeyPress = ({ key }) => { if (key === ' ' || key === 'Enter') { - this.toggleTermsCheck() + this.toggleTermsCheck(); } - } + }; render() { - const { t } = this.context + const { t } = this.context; const { password, confirmPassword, passwordError, confirmPasswordError, termsChecked, - } = this.state + } = this.state; return (
    - ) + ); } } diff --git a/ui/app/pages/first-time-flow/create-password/unique-image/index.js b/ui/app/pages/first-time-flow/create-password/unique-image/index.js index 0e97bf755..8a16dbcce 100644 --- a/ui/app/pages/first-time-flow/create-password/unique-image/index.js +++ b/ui/app/pages/first-time-flow/create-password/unique-image/index.js @@ -1 +1 @@ -export { default } from './unique-image.container' +export { default } from './unique-image.container'; diff --git a/ui/app/pages/first-time-flow/create-password/unique-image/unique-image.component.js b/ui/app/pages/first-time-flow/create-password/unique-image/unique-image.component.js index ad30c2066..3533b8b2d 100644 --- a/ui/app/pages/first-time-flow/create-password/unique-image/unique-image.component.js +++ b/ui/app/pages/first-time-flow/create-password/unique-image/unique-image.component.js @@ -1,21 +1,21 @@ -import React, { PureComponent } from 'react' -import PropTypes from 'prop-types' -import Button from '../../../../components/ui/button' -import { INITIALIZE_END_OF_FLOW_ROUTE } from '../../../../helpers/constants/routes' +import React, { PureComponent } from 'react'; +import PropTypes from 'prop-types'; +import Button from '../../../../components/ui/button'; +import { INITIALIZE_END_OF_FLOW_ROUTE } from '../../../../helpers/constants/routes'; export default class UniqueImageScreen extends PureComponent { static contextTypes = { t: PropTypes.func, metricsEvent: PropTypes.func, - } + }; static propTypes = { history: PropTypes.object, - } + }; render() { - const { t } = this.context - const { history } = this.props + const { t } = this.context; + const { history } = this.props; return (
    @@ -37,13 +37,13 @@ export default class UniqueImageScreen extends PureComponent { action: 'Agree to Phishing Warning', name: 'Agree to Phishing Warning', }, - }) - history.push(INITIALIZE_END_OF_FLOW_ROUTE) + }); + history.push(INITIALIZE_END_OF_FLOW_ROUTE); }} > {t('next')}
    - ) + ); } } diff --git a/ui/app/pages/first-time-flow/create-password/unique-image/unique-image.container.js b/ui/app/pages/first-time-flow/create-password/unique-image/unique-image.container.js index 34874aaec..fd3e5953f 100644 --- a/ui/app/pages/first-time-flow/create-password/unique-image/unique-image.container.js +++ b/ui/app/pages/first-time-flow/create-password/unique-image/unique-image.container.js @@ -1,12 +1,12 @@ -import { connect } from 'react-redux' -import UniqueImage from './unique-image.component' +import { connect } from 'react-redux'; +import UniqueImage from './unique-image.component'; const mapStateToProps = ({ metamask }) => { - const { selectedAddress } = metamask + const { selectedAddress } = metamask; return { address: selectedAddress, - } -} + }; +}; -export default connect(mapStateToProps)(UniqueImage) +export default connect(mapStateToProps)(UniqueImage); diff --git a/ui/app/pages/first-time-flow/end-of-flow/end-of-flow.component.js b/ui/app/pages/first-time-flow/end-of-flow/end-of-flow.component.js index 34a52a027..c461fa637 100644 --- a/ui/app/pages/first-time-flow/end-of-flow/end-of-flow.component.js +++ b/ui/app/pages/first-time-flow/end-of-flow/end-of-flow.component.js @@ -1,16 +1,16 @@ -import React, { PureComponent } from 'react' -import PropTypes from 'prop-types' -import Button from '../../../components/ui/button' -import Snackbar from '../../../components/ui/snackbar' -import MetaFoxLogo from '../../../components/ui/metafox-logo' -import { DEFAULT_ROUTE } from '../../../helpers/constants/routes' -import { returnToOnboardingInitiator } from '../onboarding-initiator-util' +import React, { PureComponent } from 'react'; +import PropTypes from 'prop-types'; +import Button from '../../../components/ui/button'; +import Snackbar from '../../../components/ui/snackbar'; +import MetaFoxLogo from '../../../components/ui/metafox-logo'; +import { DEFAULT_ROUTE } from '../../../helpers/constants/routes'; +import { returnToOnboardingInitiator } from '../onboarding-initiator-util'; export default class EndOfFlowScreen extends PureComponent { static contextTypes = { t: PropTypes.func, metricsEvent: PropTypes.func, - } + }; static propTypes = { history: PropTypes.object, @@ -20,50 +20,50 @@ export default class EndOfFlowScreen extends PureComponent { location: PropTypes.string, tabId: PropTypes.number, }), - } + }; async _beforeUnload() { - await this._onOnboardingComplete() + await this._onOnboardingComplete(); } _removeBeforeUnload() { - window.removeEventListener('beforeunload', this._beforeUnload) + window.removeEventListener('beforeunload', this._beforeUnload); } async _onOnboardingComplete() { - const { setCompletedOnboarding, completionMetaMetricsName } = this.props - await setCompletedOnboarding() + const { setCompletedOnboarding, completionMetaMetricsName } = this.props; + await setCompletedOnboarding(); this.context.metricsEvent({ eventOpts: { category: 'Onboarding', action: 'Onboarding Complete', name: completionMetaMetricsName, }, - }) + }); } onComplete = async () => { - const { history, onboardingInitiator } = this.props + const { history, onboardingInitiator } = this.props; - this._removeBeforeUnload() - await this._onOnboardingComplete() + this._removeBeforeUnload(); + await this._onOnboardingComplete(); if (onboardingInitiator) { - await returnToOnboardingInitiator(onboardingInitiator) + await returnToOnboardingInitiator(onboardingInitiator); } - history.push(DEFAULT_ROUTE) - } + history.push(DEFAULT_ROUTE); + }; componentDidMount() { - window.addEventListener('beforeunload', this._beforeUnload.bind(this)) + window.addEventListener('beforeunload', this._beforeUnload.bind(this)); } componentWillUnmount = () => { - this._removeBeforeUnload() - } + this._removeBeforeUnload(); + }; render() { - const { t } = this.context - const { onboardingInitiator } = this.props + const { t } = this.context; + const { onboardingInitiator } = this.props; return (
    @@ -119,6 +119,6 @@ export default class EndOfFlowScreen extends PureComponent { /> ) : null}
    - ) + ); } } diff --git a/ui/app/pages/first-time-flow/end-of-flow/end-of-flow.container.js b/ui/app/pages/first-time-flow/end-of-flow/end-of-flow.container.js index 5b0d00c17..fa3bcec2d 100644 --- a/ui/app/pages/first-time-flow/end-of-flow/end-of-flow.container.js +++ b/ui/app/pages/first-time-flow/end-of-flow/end-of-flow.container.js @@ -1,28 +1,28 @@ -import { connect } from 'react-redux' -import { getOnboardingInitiator } from '../../../selectors' -import { setCompletedOnboarding } from '../../../store/actions' -import EndOfFlow from './end-of-flow.component' +import { connect } from 'react-redux'; +import { getOnboardingInitiator } from '../../../selectors'; +import { setCompletedOnboarding } from '../../../store/actions'; +import EndOfFlow from './end-of-flow.component'; const firstTimeFlowTypeNameMap = { create: 'New Wallet Created', import: 'New Wallet Imported', -} +}; const mapStateToProps = (state) => { const { metamask: { firstTimeFlowType }, - } = state + } = state; return { completionMetaMetricsName: firstTimeFlowTypeNameMap[firstTimeFlowType], onboardingInitiator: getOnboardingInitiator(state), - } -} + }; +}; const mapDispatchToProps = (dispatch) => { return { setCompletedOnboarding: () => dispatch(setCompletedOnboarding()), - } -} + }; +}; -export default connect(mapStateToProps, mapDispatchToProps)(EndOfFlow) +export default connect(mapStateToProps, mapDispatchToProps)(EndOfFlow); diff --git a/ui/app/pages/first-time-flow/end-of-flow/index.js b/ui/app/pages/first-time-flow/end-of-flow/index.js index b0643d155..4b34ccefd 100644 --- a/ui/app/pages/first-time-flow/end-of-flow/index.js +++ b/ui/app/pages/first-time-flow/end-of-flow/index.js @@ -1 +1 @@ -export { default } from './end-of-flow.container' +export { default } from './end-of-flow.container'; diff --git a/ui/app/pages/first-time-flow/end-of-flow/tests/end-of-flow.test.js b/ui/app/pages/first-time-flow/end-of-flow/tests/end-of-flow.test.js index aef4ef6a1..2e25aa6b9 100644 --- a/ui/app/pages/first-time-flow/end-of-flow/tests/end-of-flow.test.js +++ b/ui/app/pages/first-time-flow/end-of-flow/tests/end-of-flow.test.js @@ -1,35 +1,37 @@ -import assert from 'assert' -import React from 'react' -import sinon from 'sinon' -import { mountWithRouter } from '../../../../../../test/lib/render-helpers' -import { DEFAULT_ROUTE } from '../../../../helpers/constants/routes' -import EndOfFlowScreen from '..' +import assert from 'assert'; +import React from 'react'; +import sinon from 'sinon'; +import { mountWithRouter } from '../../../../../../test/lib/render-helpers'; +import { DEFAULT_ROUTE } from '../../../../helpers/constants/routes'; +import EndOfFlowScreen from '..'; describe('End of Flow Screen', function () { - let wrapper + let wrapper; const props = { history: { push: sinon.spy(), }, setCompletedOnboarding: sinon.spy(), - } + }; beforeEach(function () { - wrapper = mountWithRouter() - }) + wrapper = mountWithRouter(); + }); it('renders', function () { - assert.strictEqual(wrapper.length, 1) - }) + assert.strictEqual(wrapper.length, 1); + }); it('should navigate to the default route on click', function (done) { - const endOfFlowButton = wrapper.find('.btn-primary.first-time-flow__button') - endOfFlowButton.simulate('click') + const endOfFlowButton = wrapper.find( + '.btn-primary.first-time-flow__button', + ); + endOfFlowButton.simulate('click'); setImmediate(() => { - assert(props.history.push.calledOnceWithExactly(DEFAULT_ROUTE)) - done() - }) - }) -}) + assert(props.history.push.calledOnceWithExactly(DEFAULT_ROUTE)); + done(); + }); + }); +}); diff --git a/ui/app/pages/first-time-flow/first-time-flow-switch/first-time-flow-switch.component.js b/ui/app/pages/first-time-flow/first-time-flow-switch/first-time-flow-switch.component.js index 6caad3c00..be27ee7cf 100644 --- a/ui/app/pages/first-time-flow/first-time-flow-switch/first-time-flow-switch.component.js +++ b/ui/app/pages/first-time-flow/first-time-flow-switch/first-time-flow-switch.component.js @@ -1,13 +1,13 @@ -import React, { PureComponent } from 'react' -import PropTypes from 'prop-types' -import { Redirect } from 'react-router-dom' +import React, { PureComponent } from 'react'; +import PropTypes from 'prop-types'; +import { Redirect } from 'react-router-dom'; import { DEFAULT_ROUTE, LOCK_ROUTE, INITIALIZE_END_OF_FLOW_ROUTE, INITIALIZE_WELCOME_ROUTE, INITIALIZE_UNLOCK_ROUTE, -} from '../../../helpers/constants/routes' +} from '../../../helpers/constants/routes'; export default class FirstTimeFlowSwitch extends PureComponent { static propTypes = { @@ -15,7 +15,7 @@ export default class FirstTimeFlowSwitch extends PureComponent { isInitialized: PropTypes.bool, isUnlocked: PropTypes.bool, seedPhraseBackedUp: PropTypes.bool, - } + }; render() { const { @@ -23,24 +23,24 @@ export default class FirstTimeFlowSwitch extends PureComponent { isInitialized, isUnlocked, seedPhraseBackedUp, - } = this.props + } = this.props; if (completedOnboarding) { - return + return ; } if (seedPhraseBackedUp !== null) { - return + return ; } if (isUnlocked) { - return + return ; } if (!isInitialized) { - return + return ; } - return + return ; } } diff --git a/ui/app/pages/first-time-flow/first-time-flow-switch/first-time-flow-switch.container.js b/ui/app/pages/first-time-flow/first-time-flow-switch/first-time-flow-switch.container.js index 92423f3dc..265c51ff0 100644 --- a/ui/app/pages/first-time-flow/first-time-flow-switch/first-time-flow-switch.container.js +++ b/ui/app/pages/first-time-flow/first-time-flow-switch/first-time-flow-switch.container.js @@ -1,5 +1,5 @@ -import { connect } from 'react-redux' -import FirstTimeFlowSwitch from './first-time-flow-switch.component' +import { connect } from 'react-redux'; +import FirstTimeFlowSwitch from './first-time-flow-switch.component'; const mapStateToProps = ({ metamask }) => { const { @@ -7,14 +7,14 @@ const mapStateToProps = ({ metamask }) => { isInitialized, isUnlocked, seedPhraseBackedUp, - } = metamask + } = metamask; return { completedOnboarding, isInitialized, isUnlocked, seedPhraseBackedUp, - } -} + }; +}; -export default connect(mapStateToProps)(FirstTimeFlowSwitch) +export default connect(mapStateToProps)(FirstTimeFlowSwitch); diff --git a/ui/app/pages/first-time-flow/first-time-flow-switch/index.js b/ui/app/pages/first-time-flow/first-time-flow-switch/index.js index 3647756ef..c7280e9b1 100644 --- a/ui/app/pages/first-time-flow/first-time-flow-switch/index.js +++ b/ui/app/pages/first-time-flow/first-time-flow-switch/index.js @@ -1 +1 @@ -export { default } from './first-time-flow-switch.container' +export { default } from './first-time-flow-switch.container'; diff --git a/ui/app/pages/first-time-flow/first-time-flow-switch/tests/first-time-flow-switch.test.js b/ui/app/pages/first-time-flow/first-time-flow-switch/tests/first-time-flow-switch.test.js index fa3b9788f..16270b2bd 100644 --- a/ui/app/pages/first-time-flow/first-time-flow-switch/tests/first-time-flow-switch.test.js +++ b/ui/app/pages/first-time-flow/first-time-flow-switch/tests/first-time-flow-switch.test.js @@ -1,14 +1,14 @@ -import assert from 'assert' -import React from 'react' -import { mountWithRouter } from '../../../../../../test/lib/render-helpers' +import assert from 'assert'; +import React from 'react'; +import { mountWithRouter } from '../../../../../../test/lib/render-helpers'; import { DEFAULT_ROUTE, LOCK_ROUTE, INITIALIZE_WELCOME_ROUTE, INITIALIZE_UNLOCK_ROUTE, INITIALIZE_END_OF_FLOW_ROUTE, -} from '../../../../helpers/constants/routes' -import FirstTimeFlowSwitch from '..' +} from '../../../../helpers/constants/routes'; +import FirstTimeFlowSwitch from '..'; describe('FirstTimeFlowSwitch', function () { it('redirects to /welcome route with null props', function () { @@ -17,83 +17,83 @@ describe('FirstTimeFlowSwitch', function () { isInitialized: null, isUnlocked: null, seedPhraseBackedUp: null, - } + }; const wrapper = mountWithRouter( , - ) + ); assert.strictEqual( wrapper .find('Lifecycle') .find({ to: { pathname: INITIALIZE_WELCOME_ROUTE } }).length, 1, - ) - }) + ); + }); it('redirects to / route when completedOnboarding is true', function () { const props = { completedOnboarding: true, - } + }; const wrapper = mountWithRouter( , - ) + ); assert.strictEqual( wrapper.find('Lifecycle').find({ to: { pathname: DEFAULT_ROUTE } }) .length, 1, - ) - }) + ); + }); it('redirects to end of flow route when seedPhraseBackedUp is true', function () { const props = { completedOnboarding: false, seedPhraseBackedUp: true, - } + }; const wrapper = mountWithRouter( , - ) + ); assert.strictEqual( wrapper .find('Lifecycle') .find({ to: { pathname: INITIALIZE_END_OF_FLOW_ROUTE } }).length, 1, - ) - }) + ); + }); it('redirects to end of flow route when seedPhraseBackedUp is false', function () { const props = { completedOnboarding: false, seedPhraseBackedUp: false, - } + }; const wrapper = mountWithRouter( , - ) + ); assert.strictEqual( wrapper .find('Lifecycle') .find({ to: { pathname: INITIALIZE_END_OF_FLOW_ROUTE } }).length, 1, - ) - }) + ); + }); it('redirects to /lock route when isUnlocked is true ', function () { const props = { completedOnboarding: false, isUnlocked: true, seedPhraseBackedUp: null, - } + }; const wrapper = mountWithRouter( , - ) + ); assert.strictEqual( wrapper.find('Lifecycle').find({ to: { pathname: LOCK_ROUTE } }).length, 1, - ) - }) + ); + }); it('redirects to /welcome route when isInitialized is false', function () { const props = { @@ -101,19 +101,19 @@ describe('FirstTimeFlowSwitch', function () { isUnlocked: false, isInitialized: false, seedPhraseBackedUp: null, - } + }; const wrapper = mountWithRouter( , - ) + ); assert.strictEqual( wrapper .find('Lifecycle') .find({ to: { pathname: INITIALIZE_WELCOME_ROUTE } }).length, 1, - ) - }) + ); + }); it('redirects to /unlock route when isInitialized is true', function () { const props = { @@ -121,17 +121,17 @@ describe('FirstTimeFlowSwitch', function () { isUnlocked: false, isInitialized: true, seedPhraseBackedUp: null, - } + }; const wrapper = mountWithRouter( , - ) + ); assert.strictEqual( wrapper .find('Lifecycle') .find({ to: { pathname: INITIALIZE_UNLOCK_ROUTE } }).length, 1, - ) - }) -}) + ); + }); +}); diff --git a/ui/app/pages/first-time-flow/first-time-flow.component.js b/ui/app/pages/first-time-flow/first-time-flow.component.js index 0a96a8ceb..5094fb2ba 100644 --- a/ui/app/pages/first-time-flow/first-time-flow.component.js +++ b/ui/app/pages/first-time-flow/first-time-flow.component.js @@ -1,7 +1,7 @@ -import React, { PureComponent } from 'react' -import PropTypes from 'prop-types' -import { Switch, Route } from 'react-router-dom' -import Unlock from '../unlock-page' +import React, { PureComponent } from 'react'; +import PropTypes from 'prop-types'; +import { Switch, Route } from 'react-router-dom'; +import Unlock from '../unlock-page'; import { DEFAULT_ROUTE, INITIALIZE_WELCOME_ROUTE, @@ -12,14 +12,14 @@ import { INITIALIZE_END_OF_FLOW_ROUTE, INITIALIZE_METAMETRICS_OPT_IN_ROUTE, INITIALIZE_BACKUP_SEED_PHRASE_ROUTE, -} from '../../helpers/constants/routes' -import FirstTimeFlowSwitch from './first-time-flow-switch' -import Welcome from './welcome' -import SelectAction from './select-action' -import EndOfFlow from './end-of-flow' -import CreatePassword from './create-password' -import SeedPhrase from './seed-phrase' -import MetaMetricsOptInScreen from './metametrics-opt-in' +} from '../../helpers/constants/routes'; +import FirstTimeFlowSwitch from './first-time-flow-switch'; +import Welcome from './welcome'; +import SelectAction from './select-action'; +import EndOfFlow from './end-of-flow'; +import CreatePassword from './create-password'; +import SeedPhrase from './seed-phrase'; +import MetaMetricsOptInScreen from './metametrics-opt-in'; export default class FirstTimeFlow extends PureComponent { static propTypes = { @@ -34,11 +34,11 @@ export default class FirstTimeFlow extends PureComponent { showingSeedPhraseBackupAfterOnboarding: PropTypes.bool, seedPhraseBackedUp: PropTypes.bool, verifySeedPhrase: PropTypes.func, - } + }; state = { seedPhrase: '', - } + }; componentDidMount() { const { @@ -48,59 +48,59 @@ export default class FirstTimeFlow extends PureComponent { isUnlocked, showingSeedPhraseBackupAfterOnboarding, seedPhraseBackedUp, - } = this.props + } = this.props; if ( completedOnboarding && (!showingSeedPhraseBackupAfterOnboarding || seedPhraseBackedUp) ) { - history.push(DEFAULT_ROUTE) - return + history.push(DEFAULT_ROUTE); + return; } if (isInitialized && !isUnlocked) { - history.push(INITIALIZE_UNLOCK_ROUTE) + history.push(INITIALIZE_UNLOCK_ROUTE); } } handleCreateNewAccount = async (password) => { - const { createNewAccount } = this.props + const { createNewAccount } = this.props; try { - const seedPhrase = await createNewAccount(password) - this.setState({ seedPhrase }) + const seedPhrase = await createNewAccount(password); + this.setState({ seedPhrase }); } catch (error) { - throw new Error(error.message) + throw new Error(error.message); } - } + }; handleImportWithSeedPhrase = async (password, seedPhrase) => { - const { createNewAccountFromSeed } = this.props + const { createNewAccountFromSeed } = this.props; try { - const vault = await createNewAccountFromSeed(password, seedPhrase) - return vault + const vault = await createNewAccountFromSeed(password, seedPhrase); + return vault; } catch (error) { - throw new Error(error.message) + throw new Error(error.message); } - } + }; handleUnlock = async (password) => { - const { unlockAccount, history, nextRoute } = this.props + const { unlockAccount, history, nextRoute } = this.props; try { - const seedPhrase = await unlockAccount(password) + const seedPhrase = await unlockAccount(password); this.setState({ seedPhrase }, () => { - history.push(nextRoute) - }) + history.push(nextRoute); + }); } catch (error) { - throw new Error(error.message) + throw new Error(error.message); } - } + }; render() { - const { seedPhrase } = this.state - const { verifySeedPhrase } = this.props + const { seedPhrase } = this.state; + const { verifySeedPhrase } = this.props; return (
    @@ -159,6 +159,6 @@ export default class FirstTimeFlow extends PureComponent {
    - ) + ); } } diff --git a/ui/app/pages/first-time-flow/first-time-flow.container.js b/ui/app/pages/first-time-flow/first-time-flow.container.js index 4e358a6f8..8c0abaf5f 100644 --- a/ui/app/pages/first-time-flow/first-time-flow.container.js +++ b/ui/app/pages/first-time-flow/first-time-flow.container.js @@ -1,13 +1,13 @@ -import { connect } from 'react-redux' -import { getFirstTimeFlowTypeRoute } from '../../selectors' +import { connect } from 'react-redux'; +import { getFirstTimeFlowTypeRoute } from '../../selectors'; import { createNewVaultAndGetSeedPhrase, createNewVaultAndRestore, unlockAndGetSeedPhrase, verifySeedPhrase, -} from '../../store/actions' -import { INITIALIZE_BACKUP_SEED_PHRASE_ROUTE } from '../../helpers/constants/routes' -import FirstTimeFlow from './first-time-flow.component' +} from '../../store/actions'; +import { INITIALIZE_BACKUP_SEED_PHRASE_ROUTE } from '../../helpers/constants/routes'; +import FirstTimeFlow from './first-time-flow.component'; const mapStateToProps = (state, ownProps) => { const { @@ -17,10 +17,10 @@ const mapStateToProps = (state, ownProps) => { isUnlocked, seedPhraseBackedUp, }, - } = state + } = state; const showingSeedPhraseBackupAfterOnboarding = Boolean( ownProps.location.pathname.match(INITIALIZE_BACKUP_SEED_PHRASE_ROUTE), - ) + ); return { completedOnboarding, @@ -29,19 +29,19 @@ const mapStateToProps = (state, ownProps) => { nextRoute: getFirstTimeFlowTypeRoute(state), showingSeedPhraseBackupAfterOnboarding, seedPhraseBackedUp, - } -} + }; +}; const mapDispatchToProps = (dispatch) => { return { createNewAccount: (password) => dispatch(createNewVaultAndGetSeedPhrase(password)), createNewAccountFromSeed: (password, seedPhrase) => { - return dispatch(createNewVaultAndRestore(password, seedPhrase)) + return dispatch(createNewVaultAndRestore(password, seedPhrase)); }, unlockAccount: (password) => dispatch(unlockAndGetSeedPhrase(password)), verifySeedPhrase: () => verifySeedPhrase(), - } -} + }; +}; -export default connect(mapStateToProps, mapDispatchToProps)(FirstTimeFlow) +export default connect(mapStateToProps, mapDispatchToProps)(FirstTimeFlow); diff --git a/ui/app/pages/first-time-flow/index.js b/ui/app/pages/first-time-flow/index.js index 5db42437c..1e045f2ef 100644 --- a/ui/app/pages/first-time-flow/index.js +++ b/ui/app/pages/first-time-flow/index.js @@ -1 +1 @@ -export { default } from './first-time-flow.container' +export { default } from './first-time-flow.container'; diff --git a/ui/app/pages/first-time-flow/metametrics-opt-in/index.js b/ui/app/pages/first-time-flow/metametrics-opt-in/index.js index 4bc2fc3a7..285dbd9de 100644 --- a/ui/app/pages/first-time-flow/metametrics-opt-in/index.js +++ b/ui/app/pages/first-time-flow/metametrics-opt-in/index.js @@ -1 +1 @@ -export { default } from './metametrics-opt-in.container' +export { default } from './metametrics-opt-in.container'; diff --git a/ui/app/pages/first-time-flow/metametrics-opt-in/metametrics-opt-in.component.js b/ui/app/pages/first-time-flow/metametrics-opt-in/metametrics-opt-in.component.js index 0bafcf01a..5e3be989b 100644 --- a/ui/app/pages/first-time-flow/metametrics-opt-in/metametrics-opt-in.component.js +++ b/ui/app/pages/first-time-flow/metametrics-opt-in/metametrics-opt-in.component.js @@ -1,7 +1,7 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import MetaFoxLogo from '../../../components/ui/metafox-logo' -import PageContainerFooter from '../../../components/ui/page-container/page-container-footer' +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import MetaFoxLogo from '../../../components/ui/metafox-logo'; +import PageContainerFooter from '../../../components/ui/page-container/page-container-footer'; export default class MetaMetricsOptIn extends Component { static propTypes = { @@ -10,22 +10,22 @@ export default class MetaMetricsOptIn extends Component { nextRoute: PropTypes.string, firstTimeSelectionMetaMetricsName: PropTypes.string, participateInMetaMetrics: PropTypes.bool, - } + }; static contextTypes = { metricsEvent: PropTypes.func, t: PropTypes.func, - } + }; render() { - const { metricsEvent, t } = this.context + const { metricsEvent, t } = this.context; const { nextRoute, history, setParticipateInMetaMetrics, firstTimeSelectionMetaMetricsName, participateInMetaMetrics, - } = this.props + } = this.props; return (
    @@ -102,7 +102,7 @@ export default class MetaMetricsOptIn extends Component {
    { - await setParticipateInMetaMetrics(false) + await setParticipateInMetaMetrics(false); try { if ( @@ -117,10 +117,10 @@ export default class MetaMetricsOptIn extends Component { }, isOptIn: true, flushImmediately: true, - }) + }); } } finally { - history.push(nextRoute) + history.push(nextRoute); } }} cancelText={t('noThanks')} @@ -128,9 +128,9 @@ export default class MetaMetricsOptIn extends Component { onSubmit={async () => { const [, metaMetricsId] = await setParticipateInMetaMetrics( true, - ) + ); try { - const metrics = [] + const metrics = []; if ( participateInMetaMetrics === null || participateInMetaMetrics === false @@ -145,7 +145,7 @@ export default class MetaMetricsOptIn extends Component { isOptIn: true, flushImmediately: true, }), - ) + ); } metrics.push( metricsEvent({ @@ -158,10 +158,10 @@ export default class MetaMetricsOptIn extends Component { metaMetricsId, flushImmediately: true, }), - ) - await Promise.all(metrics) + ); + await Promise.all(metrics); } finally { - history.push(nextRoute) + history.push(nextRoute); } }} submitText={t('affirmAgree')} @@ -183,6 +183,6 @@ export default class MetaMetricsOptIn extends Component {
    - ) + ); } } diff --git a/ui/app/pages/first-time-flow/metametrics-opt-in/metametrics-opt-in.container.js b/ui/app/pages/first-time-flow/metametrics-opt-in/metametrics-opt-in.container.js index 4fd76b5f9..e336a9dd2 100644 --- a/ui/app/pages/first-time-flow/metametrics-opt-in/metametrics-opt-in.container.js +++ b/ui/app/pages/first-time-flow/metametrics-opt-in/metametrics-opt-in.container.js @@ -1,29 +1,29 @@ -import { connect } from 'react-redux' -import { setParticipateInMetaMetrics } from '../../../store/actions' -import { getFirstTimeFlowTypeRoute } from '../../../selectors' -import MetaMetricsOptIn from './metametrics-opt-in.component' +import { connect } from 'react-redux'; +import { setParticipateInMetaMetrics } from '../../../store/actions'; +import { getFirstTimeFlowTypeRoute } from '../../../selectors'; +import MetaMetricsOptIn from './metametrics-opt-in.component'; const firstTimeFlowTypeNameMap = { create: 'Selected Create New Wallet', import: 'Selected Import Wallet', -} +}; const mapStateToProps = (state) => { - const { firstTimeFlowType, participateInMetaMetrics } = state.metamask + const { firstTimeFlowType, participateInMetaMetrics } = state.metamask; return { nextRoute: getFirstTimeFlowTypeRoute(state), firstTimeSelectionMetaMetricsName: firstTimeFlowTypeNameMap[firstTimeFlowType], participateInMetaMetrics, - } -} + }; +}; const mapDispatchToProps = (dispatch) => { return { setParticipateInMetaMetrics: (val) => dispatch(setParticipateInMetaMetrics(val)), - } -} + }; +}; -export default connect(mapStateToProps, mapDispatchToProps)(MetaMetricsOptIn) +export default connect(mapStateToProps, mapDispatchToProps)(MetaMetricsOptIn); diff --git a/ui/app/pages/first-time-flow/metametrics-opt-in/tests/metametrics-opt-in.test.js b/ui/app/pages/first-time-flow/metametrics-opt-in/tests/metametrics-opt-in.test.js index 33d9ebb30..7aee30951 100644 --- a/ui/app/pages/first-time-flow/metametrics-opt-in/tests/metametrics-opt-in.test.js +++ b/ui/app/pages/first-time-flow/metametrics-opt-in/tests/metametrics-opt-in.test.js @@ -1,9 +1,9 @@ -import assert from 'assert' -import React from 'react' -import sinon from 'sinon' -import configureMockStore from 'redux-mock-store' -import { mountWithRouter } from '../../../../../../test/lib/render-helpers' -import MetaMetricsOptIn from '..' +import assert from 'assert'; +import React from 'react'; +import sinon from 'sinon'; +import configureMockStore from 'redux-mock-store'; +import { mountWithRouter } from '../../../../../../test/lib/render-helpers'; +import MetaMetricsOptIn from '..'; describe('MetaMetricsOptIn', function () { it('opt out of MetaMetrics', function () { @@ -13,20 +13,20 @@ describe('MetaMetricsOptIn', function () { }, setParticipateInMetaMetrics: sinon.stub().resolves(), participateInMetaMetrics: false, - } + }; const store = configureMockStore()({ metamask: {}, - }) + }); const wrapper = mountWithRouter( , store, - ) + ); const noThanksButton = wrapper.find( '.btn-default.page-container__footer-button', - ) - noThanksButton.simulate('click') + ); + noThanksButton.simulate('click'); - assert.ok(props.setParticipateInMetaMetrics.calledOnceWithExactly(false)) - props.setParticipateInMetaMetrics.resetHistory() - }) -}) + assert.ok(props.setParticipateInMetaMetrics.calledOnceWithExactly(false)); + props.setParticipateInMetaMetrics.resetHistory(); + }); +}); diff --git a/ui/app/pages/first-time-flow/onboarding-initiator-util.js b/ui/app/pages/first-time-flow/onboarding-initiator-util.js index 87427903a..abfa424d7 100644 --- a/ui/app/pages/first-time-flow/onboarding-initiator-util.js +++ b/ui/app/pages/first-time-flow/onboarding-initiator-util.js @@ -1,5 +1,5 @@ -import extension from 'extensionizer' -import log from 'loglevel' +import extension from 'extensionizer'; +import log from 'loglevel'; const returnToOnboardingInitiatorTab = async (onboardingInitiator) => { const tab = await new Promise((resolve) => { @@ -9,48 +9,48 @@ const returnToOnboardingInitiatorTab = async (onboardingInitiator) => { // eslint-disable-next-line no-shadow (tab) => { if (tab) { - resolve(tab) + resolve(tab); } else { // silence console message about unchecked error if (extension.runtime.lastError) { - log.debug(extension.runtime.lastError) + log.debug(extension.runtime.lastError); } - resolve() + resolve(); } }, - ) - }) + ); + }); if (tab) { - window.close() + window.close(); } else { // this case can happen if the tab was closed since being checked with `extension.tabs.get` log.warn( `Setting current tab to onboarding initiator has failed; falling back to redirect`, - ) - window.location.assign(onboardingInitiator.location) + ); + window.location.assign(onboardingInitiator.location); } -} +}; export const returnToOnboardingInitiator = async (onboardingInitiator) => { const tab = await new Promise((resolve) => { // eslint-disable-next-line no-shadow extension.tabs.get(onboardingInitiator.tabId, (tab) => { if (tab) { - resolve(tab) + resolve(tab); } else { // silence console message about unchecked error if (extension.runtime.lastError) { - log.debug(extension.runtime.lastError) + log.debug(extension.runtime.lastError); } - resolve() + resolve(); } - }) - }) + }); + }); if (tab) { - await returnToOnboardingInitiatorTab(onboardingInitiator) + await returnToOnboardingInitiatorTab(onboardingInitiator); } else { - window.location.assign(onboardingInitiator.location) + window.location.assign(onboardingInitiator.location); } -} +}; diff --git a/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.component.js b/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.component.js index 3494e5f0a..6c7420ef2 100644 --- a/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.component.js +++ b/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.component.js @@ -1,32 +1,32 @@ -import React, { PureComponent } from 'react' -import PropTypes from 'prop-types' -import classnames from 'classnames' -import Button from '../../../../components/ui/button' +import React, { PureComponent } from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; +import Button from '../../../../components/ui/button'; import { INITIALIZE_END_OF_FLOW_ROUTE, INITIALIZE_SEED_PHRASE_ROUTE, -} from '../../../../helpers/constants/routes' -import { exportAsFile } from '../../../../helpers/utils/util' -import DraggableSeed from './draggable-seed.component' +} from '../../../../helpers/constants/routes'; +import { exportAsFile } from '../../../../helpers/utils/util'; +import DraggableSeed from './draggable-seed.component'; -const EMPTY_SEEDS = Array(12).fill(null) +const EMPTY_SEEDS = Array(12).fill(null); export default class ConfirmSeedPhrase extends PureComponent { static contextTypes = { metricsEvent: PropTypes.func, t: PropTypes.func, - } + }; static defaultProps = { seedPhrase: '', - } + }; static propTypes = { history: PropTypes.object, seedPhrase: PropTypes.string, initializeThreeBox: PropTypes.func, setSeedPhraseBackedUp: PropTypes.func, - } + }; state = { selectedSeedIndices: [], @@ -34,46 +34,46 @@ export default class ConfirmSeedPhrase extends PureComponent { pendingSeedIndices: [], draggingSeedIndex: -1, hoveringIndex: -1, - } + }; componentDidMount() { - const { seedPhrase = '' } = this.props - const sortedSeedWords = (seedPhrase.split(' ') || []).sort() - this.setState({ sortedSeedWords }) + const { seedPhrase = '' } = this.props; + const sortedSeedWords = (seedPhrase.split(' ') || []).sort(); + this.setState({ sortedSeedWords }); } setDraggingSeedIndex = (draggingSeedIndex) => - this.setState({ draggingSeedIndex }) + this.setState({ draggingSeedIndex }); - setHoveringIndex = (hoveringIndex) => this.setState({ hoveringIndex }) + setHoveringIndex = (hoveringIndex) => this.setState({ hoveringIndex }); onDrop = (targetIndex) => { - const { selectedSeedIndices, draggingSeedIndex } = this.state + const { selectedSeedIndices, draggingSeedIndex } = this.state; const indices = insert( selectedSeedIndices, draggingSeedIndex, targetIndex, true, - ) + ); this.setState({ selectedSeedIndices: indices, pendingSeedIndices: indices, draggingSeedIndex: -1, hoveringIndex: -1, - }) - } + }); + }; handleExport = () => { - exportAsFile('', this.props.seedPhrase, 'text/plain') - } + exportAsFile('', this.props.seedPhrase, 'text/plain'); + }; handleSubmit = async () => { - const { history, setSeedPhraseBackedUp, initializeThreeBox } = this.props + const { history, setSeedPhraseBackedUp, initializeThreeBox } = this.props; if (!this.isValid()) { - return + return; } try { @@ -83,23 +83,23 @@ export default class ConfirmSeedPhrase extends PureComponent { action: 'Seed Phrase Setup', name: 'Verify Complete', }, - }) + }); setSeedPhraseBackedUp(true).then(async () => { - initializeThreeBox() - history.push(INITIALIZE_END_OF_FLOW_ROUTE) - }) + initializeThreeBox(); + history.push(INITIALIZE_END_OF_FLOW_ROUTE); + }); } catch (error) { - console.error(error.message) + console.error(error.message); } - } + }; handleSelectSeedWord = (index) => { this.setState({ selectedSeedIndices: [...this.state.selectedSeedIndices, index], pendingSeedIndices: [...this.state.pendingSeedIndices, index], - }) - } + }); + }; handleDeselectSeedWord = (index) => { this.setState({ @@ -109,32 +109,34 @@ export default class ConfirmSeedPhrase extends PureComponent { pendingSeedIndices: this.state.pendingSeedIndices.filter( (i) => index !== i, ), - }) - } + }); + }; isValid() { - const { seedPhrase } = this.props - const { selectedSeedIndices, sortedSeedWords } = this.state - const selectedSeedWords = selectedSeedIndices.map((i) => sortedSeedWords[i]) - return seedPhrase === selectedSeedWords.join(' ') + const { seedPhrase } = this.props; + const { selectedSeedIndices, sortedSeedWords } = this.state; + const selectedSeedWords = selectedSeedIndices.map( + (i) => sortedSeedWords[i], + ); + return seedPhrase === selectedSeedWords.join(' '); } render() { - const { t } = this.context - const { history } = this.props + const { t } = this.context; + const { history } = this.props; const { selectedSeedIndices, sortedSeedWords, draggingSeedIndex, - } = this.state + } = this.state; return ( - ) + ); } renderSelectedSeeds() { @@ -201,10 +203,10 @@ export default class ConfirmSeedPhrase extends PureComponent { sortedSeedWords, selectedSeedIndices, draggingSeedIndex, - } = this.state + } = this.state; return EMPTY_SEEDS.map((_, index) => { - const seedIndex = selectedSeedIndices[index] - const word = sortedSeedWords[seedIndex] + const seedIndex = selectedSeedIndices[index]; + const word = sortedSeedWords[seedIndex]; return ( - ) - }) + ); + }); } renderPendingSeeds() { @@ -229,13 +231,17 @@ export default class ConfirmSeedPhrase extends PureComponent { sortedSeedWords, draggingSeedIndex, hoveringIndex, - } = this.state + } = this.state; - const indices = insert(pendingSeedIndices, draggingSeedIndex, hoveringIndex) + const indices = insert( + pendingSeedIndices, + draggingSeedIndex, + hoveringIndex, + ); return EMPTY_SEEDS.map((_, index) => { - const seedIndex = indices[index] - const word = sortedSeedWords[seedIndex] + const seedIndex = indices[index]; + const word = sortedSeedWords[seedIndex]; return ( - ) - }) + ); + }); } } function insert(list, value, target, removeOld) { - let nextList = [...list] + let nextList = [...list]; if (typeof list[target] === 'number') { - nextList = [...list.slice(0, target), value, ...list.slice(target)] + nextList = [...list.slice(0, target), value, ...list.slice(target)]; } if (removeOld) { nextList = nextList.filter((seed, i) => { - return seed !== value || i === target - }) + return seed !== value || i === target; + }); } - return nextList + return nextList; } diff --git a/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.container.js b/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.container.js index 646314ecd..339bb3513 100644 --- a/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.container.js +++ b/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.container.js @@ -1,16 +1,16 @@ -import { connect } from 'react-redux' +import { connect } from 'react-redux'; import { setSeedPhraseBackedUp, initializeThreeBox, -} from '../../../../store/actions' -import ConfirmSeedPhrase from './confirm-seed-phrase.component' +} from '../../../../store/actions'; +import ConfirmSeedPhrase from './confirm-seed-phrase.component'; const mapDispatchToProps = (dispatch) => { return { setSeedPhraseBackedUp: (seedPhraseBackupState) => dispatch(setSeedPhraseBackedUp(seedPhraseBackupState)), initializeThreeBox: () => dispatch(initializeThreeBox()), - } -} + }; +}; -export default connect(null, mapDispatchToProps)(ConfirmSeedPhrase) +export default connect(null, mapDispatchToProps)(ConfirmSeedPhrase); diff --git a/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/draggable-seed.component.js b/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/draggable-seed.component.js index 291cc8016..eab193293 100644 --- a/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/draggable-seed.component.js +++ b/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/draggable-seed.component.js @@ -1,7 +1,7 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import classnames from 'classnames' -import { DragSource, DropTarget } from 'react-dnd' +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; +import { DragSource, DropTarget } from 'react-dnd'; class DraggableSeed extends Component { static propTypes = { @@ -18,17 +18,17 @@ class DraggableSeed extends Component { word: PropTypes.string, className: PropTypes.string, selected: PropTypes.bool, - } + }; static defaultProps = { className: '', onClick: undefined, - } + }; UNSAFE_componentWillReceiveProps(nextProps) { - const { isOver, setHoveringIndex } = this.props + const { isOver, setHoveringIndex } = this.props; if (isOver && !nextProps.isOver) { - setHoveringIndex(-1) + setHoveringIndex(-1); } } @@ -44,7 +44,7 @@ class DraggableSeed extends Component { onClick, isOver, canDrop, - } = this.props + } = this.props; return connectDropTarget( connectDragSource( @@ -67,66 +67,66 @@ class DraggableSeed extends Component { {word}
    , ), - ) + ); } } -const SEEDWORD = 'SEEDWORD' +const SEEDWORD = 'SEEDWORD'; const seedSource = { beginDrag(props) { - setTimeout(() => props.setDraggingSeedIndex(props.seedIndex), 0) + setTimeout(() => props.setDraggingSeedIndex(props.seedIndex), 0); return { seedIndex: props.seedIndex, word: props.word, - } + }; }, canDrag(props) { - return props.draggable + return props.draggable; }, endDrag(props, monitor) { - const dropTarget = monitor.getDropResult() + const dropTarget = monitor.getDropResult(); if (!dropTarget) { - setTimeout(() => props.setDraggingSeedIndex(-1), 0) - return + setTimeout(() => props.setDraggingSeedIndex(-1), 0); + return; } - props.onDrop(dropTarget.targetIndex) + props.onDrop(dropTarget.targetIndex); }, -} +}; const seedTarget = { drop(props) { return { targetIndex: props.index, - } + }; }, canDrop(props) { - return props.droppable + return props.droppable; }, hover(props) { - props.setHoveringIndex(props.index) + props.setHoveringIndex(props.index); }, -} +}; const collectDrag = (connect, monitor) => { return { connectDragSource: connect.dragSource(), isDragging: monitor.isDragging(), - } -} + }; +}; const collectDrop = (connect, monitor) => { return { connectDropTarget: connect.dropTarget(), isOver: monitor.isOver(), canDrop: monitor.canDrop(), - } -} + }; +}; export default DropTarget( SEEDWORD, seedTarget, collectDrop, -)(DragSource(SEEDWORD, seedSource, collectDrag)(DraggableSeed)) +)(DragSource(SEEDWORD, seedSource, collectDrag)(DraggableSeed)); diff --git a/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/index.js b/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/index.js index beb53b383..724a0a3ba 100644 --- a/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/index.js +++ b/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/index.js @@ -1 +1 @@ -export { default } from './confirm-seed-phrase.container' +export { default } from './confirm-seed-phrase.container'; diff --git a/ui/app/pages/first-time-flow/seed-phrase/index.js b/ui/app/pages/first-time-flow/seed-phrase/index.js index 185b3f089..01bd7431b 100644 --- a/ui/app/pages/first-time-flow/seed-phrase/index.js +++ b/ui/app/pages/first-time-flow/seed-phrase/index.js @@ -1 +1 @@ -export { default } from './seed-phrase.component' +export { default } from './seed-phrase.component'; diff --git a/ui/app/pages/first-time-flow/seed-phrase/reveal-seed-phrase/index.js b/ui/app/pages/first-time-flow/seed-phrase/reveal-seed-phrase/index.js index a528f95a2..e1fd81f91 100644 --- a/ui/app/pages/first-time-flow/seed-phrase/reveal-seed-phrase/index.js +++ b/ui/app/pages/first-time-flow/seed-phrase/reveal-seed-phrase/index.js @@ -1 +1 @@ -export { default } from './reveal-seed-phrase.container' +export { default } from './reveal-seed-phrase.container'; diff --git a/ui/app/pages/first-time-flow/seed-phrase/reveal-seed-phrase/reveal-seed-phrase.component.js b/ui/app/pages/first-time-flow/seed-phrase/reveal-seed-phrase/reveal-seed-phrase.component.js index bbc438c93..1236817a7 100644 --- a/ui/app/pages/first-time-flow/seed-phrase/reveal-seed-phrase/reveal-seed-phrase.component.js +++ b/ui/app/pages/first-time-flow/seed-phrase/reveal-seed-phrase/reveal-seed-phrase.component.js @@ -1,21 +1,21 @@ -import React, { PureComponent } from 'react' -import PropTypes from 'prop-types' -import classnames from 'classnames' -import LockIcon from '../../../../components/ui/lock-icon' -import Button from '../../../../components/ui/button' -import Snackbar from '../../../../components/ui/snackbar' +import React, { PureComponent } from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; +import LockIcon from '../../../../components/ui/lock-icon'; +import Button from '../../../../components/ui/button'; +import Snackbar from '../../../../components/ui/snackbar'; import { INITIALIZE_CONFIRM_SEED_PHRASE_ROUTE, DEFAULT_ROUTE, -} from '../../../../helpers/constants/routes' -import { exportAsFile } from '../../../../helpers/utils/util' -import { returnToOnboardingInitiator } from '../../onboarding-initiator-util' +} from '../../../../helpers/constants/routes'; +import { exportAsFile } from '../../../../helpers/utils/util'; +import { returnToOnboardingInitiator } from '../../onboarding-initiator-util'; export default class RevealSeedPhrase extends PureComponent { static contextTypes = { t: PropTypes.func, metricsEvent: PropTypes.func, - } + }; static propTypes = { history: PropTypes.object, @@ -26,19 +26,19 @@ export default class RevealSeedPhrase extends PureComponent { location: PropTypes.string, tabId: PropTypes.number, }), - } + }; state = { isShowingSeedPhrase: false, - } + }; handleExport = () => { - exportAsFile('', this.props.seedPhrase, 'text/plain') - } + exportAsFile('', this.props.seedPhrase, 'text/plain'); + }; handleNext = () => { - const { isShowingSeedPhrase } = this.state - const { history } = this.props + const { isShowingSeedPhrase } = this.state; + const { history } = this.props; this.context.metricsEvent({ eventOpts: { @@ -46,14 +46,14 @@ export default class RevealSeedPhrase extends PureComponent { action: 'Seed Phrase Setup', name: 'Advance to Verify', }, - }) + }); if (!isShowingSeedPhrase) { - return + return; } - history.push(INITIALIZE_CONFIRM_SEED_PHRASE_ROUTE) - } + history.push(INITIALIZE_CONFIRM_SEED_PHRASE_ROUTE); + }; handleSkip = async () => { const { @@ -61,7 +61,7 @@ export default class RevealSeedPhrase extends PureComponent { setSeedPhraseBackedUp, setCompletedOnboarding, onboardingInitiator, - } = this.props + } = this.props; this.context.metricsEvent({ eventOpts: { @@ -69,20 +69,20 @@ export default class RevealSeedPhrase extends PureComponent { action: 'Seed Phrase Setup', name: 'Remind me later', }, - }) + }); - await Promise.all([setCompletedOnboarding(), setSeedPhraseBackedUp(false)]) + await Promise.all([setCompletedOnboarding(), setSeedPhraseBackedUp(false)]); if (onboardingInitiator) { - await returnToOnboardingInitiator(onboardingInitiator) + await returnToOnboardingInitiator(onboardingInitiator); } - history.push(DEFAULT_ROUTE) - } + history.push(DEFAULT_ROUTE); + }; renderSecretWordsContainer() { - const { t } = this.context - const { seedPhrase } = this.props - const { isShowingSeedPhrase } = this.state + const { t } = this.context; + const { seedPhrase } = this.props; + const { isShowingSeedPhrase } = this.state; return (
    @@ -106,8 +106,8 @@ export default class RevealSeedPhrase extends PureComponent { action: 'Seed Phrase Setup', name: 'Revealed Words', }, - }) - this.setState({ isShowingSeedPhrase: true }) + }); + this.setState({ isShowingSeedPhrase: true }); }} > @@ -117,13 +117,13 @@ export default class RevealSeedPhrase extends PureComponent {
    )} - ) + ); } render() { - const { t } = this.context - const { isShowingSeedPhrase } = this.state - const { onboardingInitiator } = this.props + const { t } = this.context; + const { isShowingSeedPhrase } = this.state; + const { onboardingInitiator } = this.props; return (
    @@ -187,6 +187,6 @@ export default class RevealSeedPhrase extends PureComponent { /> ) : null}
    - ) + ); } } diff --git a/ui/app/pages/first-time-flow/seed-phrase/reveal-seed-phrase/reveal-seed-phrase.container.js b/ui/app/pages/first-time-flow/seed-phrase/reveal-seed-phrase/reveal-seed-phrase.container.js index 30b4f9a23..a9a3cb2ef 100644 --- a/ui/app/pages/first-time-flow/seed-phrase/reveal-seed-phrase/reveal-seed-phrase.container.js +++ b/ui/app/pages/first-time-flow/seed-phrase/reveal-seed-phrase/reveal-seed-phrase.container.js @@ -1,23 +1,23 @@ -import { connect } from 'react-redux' +import { connect } from 'react-redux'; import { setCompletedOnboarding, setSeedPhraseBackedUp, -} from '../../../../store/actions' -import { getOnboardingInitiator } from '../../../../selectors' -import RevealSeedPhrase from './reveal-seed-phrase.component' +} from '../../../../store/actions'; +import { getOnboardingInitiator } from '../../../../selectors'; +import RevealSeedPhrase from './reveal-seed-phrase.component'; const mapStateToProps = (state) => { return { onboardingInitiator: getOnboardingInitiator(state), - } -} + }; +}; const mapDispatchToProps = (dispatch) => { return { setSeedPhraseBackedUp: (seedPhraseBackupState) => dispatch(setSeedPhraseBackedUp(seedPhraseBackupState)), setCompletedOnboarding: () => dispatch(setCompletedOnboarding()), - } -} + }; +}; -export default connect(mapStateToProps, mapDispatchToProps)(RevealSeedPhrase) +export default connect(mapStateToProps, mapDispatchToProps)(RevealSeedPhrase); diff --git a/ui/app/pages/first-time-flow/seed-phrase/reveal-seed-phrase/tests/reveal-seed-phrase.test.js b/ui/app/pages/first-time-flow/seed-phrase/reveal-seed-phrase/tests/reveal-seed-phrase.test.js index f0e561a4b..29f1d6968 100644 --- a/ui/app/pages/first-time-flow/seed-phrase/reveal-seed-phrase/tests/reveal-seed-phrase.test.js +++ b/ui/app/pages/first-time-flow/seed-phrase/reveal-seed-phrase/tests/reveal-seed-phrase.test.js @@ -1,14 +1,14 @@ -import assert from 'assert' -import React from 'react' -import sinon from 'sinon' -import { mount } from 'enzyme' -import RevealSeedPhrase from '..' +import assert from 'assert'; +import React from 'react'; +import sinon from 'sinon'; +import { mount } from 'enzyme'; +import RevealSeedPhrase from '..'; describe('Reveal Seed Phrase', function () { - let wrapper + let wrapper; const TEST_SEED = - 'debris dizzy just program just float decrease vacant alarm reduce speak stadium' + 'debris dizzy just program just float decrease vacant alarm reduce speak stadium'; const props = { history: { @@ -17,7 +17,7 @@ describe('Reveal Seed Phrase', function () { seedPhrase: TEST_SEED, setSeedPhraseBackedUp: sinon.spy(), setCompletedOnboarding: sinon.spy(), - } + }; beforeEach(function () { wrapper = mount(, { @@ -25,23 +25,25 @@ describe('Reveal Seed Phrase', function () { t: (str) => str, metricsEvent: () => undefined, }, - }) - }) + }); + }); it('seed phrase', function () { - const seedPhrase = wrapper.find('.reveal-seed-phrase__secret-words--hidden') - assert.strictEqual(seedPhrase.length, 1) - assert.strictEqual(seedPhrase.text(), TEST_SEED) - }) + const seedPhrase = wrapper.find( + '.reveal-seed-phrase__secret-words--hidden', + ); + assert.strictEqual(seedPhrase.length, 1); + assert.strictEqual(seedPhrase.text(), TEST_SEED); + }); it('clicks to reveal', function () { - const reveal = wrapper.find('.reveal-seed-phrase__secret-blocker') + const reveal = wrapper.find('.reveal-seed-phrase__secret-blocker'); - assert.strictEqual(wrapper.state().isShowingSeedPhrase, false) - reveal.simulate('click') - assert.strictEqual(wrapper.state().isShowingSeedPhrase, true) + assert.strictEqual(wrapper.state().isShowingSeedPhrase, false); + reveal.simulate('click'); + assert.strictEqual(wrapper.state().isShowingSeedPhrase, true); - const showSeed = wrapper.find('.reveal-seed-phrase__secret-words') - assert.strictEqual(showSeed.length, 1) - }) -}) + const showSeed = wrapper.find('.reveal-seed-phrase__secret-words'); + assert.strictEqual(showSeed.length, 1); + }); +}); diff --git a/ui/app/pages/first-time-flow/seed-phrase/seed-phrase.component.js b/ui/app/pages/first-time-flow/seed-phrase/seed-phrase.component.js index a953df36d..97d27998a 100644 --- a/ui/app/pages/first-time-flow/seed-phrase/seed-phrase.component.js +++ b/ui/app/pages/first-time-flow/seed-phrase/seed-phrase.component.js @@ -1,46 +1,46 @@ -import React, { PureComponent } from 'react' -import PropTypes from 'prop-types' -import { Switch, Route } from 'react-router-dom' -import HTML5Backend from 'react-dnd-html5-backend' -import { DragDropContextProvider } from 'react-dnd' +import React, { PureComponent } from 'react'; +import PropTypes from 'prop-types'; +import { Switch, Route } from 'react-router-dom'; +import HTML5Backend from 'react-dnd-html5-backend'; +import { DragDropContextProvider } from 'react-dnd'; import { INITIALIZE_SEED_PHRASE_ROUTE, INITIALIZE_CONFIRM_SEED_PHRASE_ROUTE, INITIALIZE_BACKUP_SEED_PHRASE_ROUTE, DEFAULT_ROUTE, -} from '../../../helpers/constants/routes' -import MetaFoxLogo from '../../../components/ui/metafox-logo' -import ConfirmSeedPhrase from './confirm-seed-phrase' -import RevealSeedPhrase from './reveal-seed-phrase' +} from '../../../helpers/constants/routes'; +import MetaFoxLogo from '../../../components/ui/metafox-logo'; +import ConfirmSeedPhrase from './confirm-seed-phrase'; +import RevealSeedPhrase from './reveal-seed-phrase'; export default class SeedPhrase extends PureComponent { static propTypes = { history: PropTypes.object, seedPhrase: PropTypes.string, verifySeedPhrase: PropTypes.func, - } + }; state = { verifiedSeedPhrase: '', - } + }; componentDidMount() { - const { seedPhrase, history, verifySeedPhrase } = this.props + const { seedPhrase, history, verifySeedPhrase } = this.props; if (!seedPhrase) { verifySeedPhrase().then((verifiedSeedPhrase) => { if (verifiedSeedPhrase) { - this.setState({ verifiedSeedPhrase }) + this.setState({ verifiedSeedPhrase }); } else { - history.push(DEFAULT_ROUTE) + history.push(DEFAULT_ROUTE); } - }) + }); } } render() { - const { seedPhrase } = this.props - const { verifiedSeedPhrase } = this.state + const { seedPhrase } = this.props; + const { verifiedSeedPhrase } = this.state; return ( @@ -80,6 +80,6 @@ export default class SeedPhrase extends PureComponent { - ) + ); } } diff --git a/ui/app/pages/first-time-flow/seed-phrase/tests/confirm-seed-phrase-component.test.js b/ui/app/pages/first-time-flow/seed-phrase/tests/confirm-seed-phrase-component.test.js index 1be3b70d7..5add90bd9 100644 --- a/ui/app/pages/first-time-flow/seed-phrase/tests/confirm-seed-phrase-component.test.js +++ b/ui/app/pages/first-time-flow/seed-phrase/tests/confirm-seed-phrase-component.test.js @@ -1,8 +1,8 @@ -import assert from 'assert' -import React from 'react' -import { shallow } from 'enzyme' -import sinon from 'sinon' -import ConfirmSeedPhrase from '../confirm-seed-phrase/confirm-seed-phrase.component' +import assert from 'assert'; +import React from 'react'; +import { shallow } from 'enzyme'; +import sinon from 'sinon'; +import ConfirmSeedPhrase from '../confirm-seed-phrase/confirm-seed-phrase.component'; function shallowRender(props = {}, context = {}) { return shallow(, { @@ -10,25 +10,25 @@ function shallowRender(props = {}, context = {}) { t: (str) => `${str}_t`, ...context, }, - }) + }); } describe('ConfirmSeedPhrase Component', function () { it('should render correctly', function () { const root = shallowRender({ seedPhrase: '鼠 牛 虎 兔 龍 蛇 馬 羊 猴 雞 狗 豬', - }) + }); assert.strictEqual( root.find('.confirm-seed-phrase__seed-word--sorted').length, 12, 'should render 12 seed phrases', - ) - }) + ); + }); it('should add/remove selected on click', function () { - const metricsEventSpy = sinon.spy() - const pushSpy = sinon.spy() + const metricsEventSpy = sinon.spy(); + const pushSpy = sinon.spy(); const root = shallowRender( { seedPhrase: '鼠 牛 虎 兔 龍 蛇 馬 羊 猴 雞 狗 豬', @@ -37,36 +37,39 @@ describe('ConfirmSeedPhrase Component', function () { { metricsEvent: metricsEventSpy, }, - ) + ); - const seeds = root.find('.confirm-seed-phrase__seed-word--sorted') + const seeds = root.find('.confirm-seed-phrase__seed-word--sorted'); // Click on 3 seeds to add to selected - seeds.at(0).simulate('click') - seeds.at(1).simulate('click') - seeds.at(2).simulate('click') + seeds.at(0).simulate('click'); + seeds.at(1).simulate('click'); + seeds.at(2).simulate('click'); assert.deepStrictEqual( root.state().selectedSeedIndices, [0, 1, 2], 'should add seed phrase to selected on click', - ) + ); // Click on a selected seed to remove - root.state() - root.update() - root.state() - root.find('.confirm-seed-phrase__seed-word--sorted').at(1).simulate('click') + root.state(); + root.update(); + root.state(); + root + .find('.confirm-seed-phrase__seed-word--sorted') + .at(1) + .simulate('click'); assert.deepStrictEqual( root.state().selectedSeedIndices, [0, 2], 'should remove seed phrase from selected when click again', - ) - }) + ); + }); it('should render correctly on hover', function () { - const metricsEventSpy = sinon.spy() - const pushSpy = sinon.spy() + const metricsEventSpy = sinon.spy(); + const pushSpy = sinon.spy(); const root = shallowRender( { seedPhrase: '鼠 牛 虎 兔 龍 蛇 馬 羊 猴 雞 狗 豬', @@ -75,33 +78,33 @@ describe('ConfirmSeedPhrase Component', function () { { metricsEvent: metricsEventSpy, }, - ) + ); - const seeds = root.find('.confirm-seed-phrase__seed-word--sorted') + const seeds = root.find('.confirm-seed-phrase__seed-word--sorted'); // Click on 3 seeds to add to selected - seeds.at(0).simulate('click') - seeds.at(1).simulate('click') - seeds.at(2).simulate('click') + seeds.at(0).simulate('click'); + seeds.at(1).simulate('click'); + seeds.at(2).simulate('click'); // Dragging Seed # 2 to 0 placeth - root.instance().setDraggingSeedIndex(2) - root.instance().setHoveringIndex(0) + root.instance().setDraggingSeedIndex(2); + root.instance().setHoveringIndex(0); - root.update() + root.update(); const pendingSeeds = root.find( '.confirm-seed-phrase__selected-seed-words__pending-seed', - ) + ); - assert.strictEqual(pendingSeeds.at(0).props().seedIndex, 2) - assert.strictEqual(pendingSeeds.at(1).props().seedIndex, 0) - assert.strictEqual(pendingSeeds.at(2).props().seedIndex, 1) - }) + assert.strictEqual(pendingSeeds.at(0).props().seedIndex, 2); + assert.strictEqual(pendingSeeds.at(1).props().seedIndex, 0); + assert.strictEqual(pendingSeeds.at(2).props().seedIndex, 1); + }); it('should insert seed in place on drop', function () { - const metricsEventSpy = sinon.spy() - const pushSpy = sinon.spy() + const metricsEventSpy = sinon.spy(); + const pushSpy = sinon.spy(); const root = shallowRender( { seedPhrase: '鼠 牛 虎 兔 龍 蛇 馬 羊 猴 雞 狗 豬', @@ -110,25 +113,25 @@ describe('ConfirmSeedPhrase Component', function () { { metricsEvent: metricsEventSpy, }, - ) + ); - const seeds = root.find('.confirm-seed-phrase__seed-word--sorted') + const seeds = root.find('.confirm-seed-phrase__seed-word--sorted'); // Click on 3 seeds to add to selected - seeds.at(0).simulate('click') - seeds.at(1).simulate('click') - seeds.at(2).simulate('click') + seeds.at(0).simulate('click'); + seeds.at(1).simulate('click'); + seeds.at(2).simulate('click'); // Drop Seed # 2 to 0 placeth - root.instance().setDraggingSeedIndex(2) - root.instance().setHoveringIndex(0) - root.instance().onDrop(0) + root.instance().setDraggingSeedIndex(2); + root.instance().setHoveringIndex(0); + root.instance().onDrop(0); - root.update() + root.update(); - assert.deepStrictEqual(root.state().selectedSeedIndices, [2, 0, 1]) - assert.deepStrictEqual(root.state().pendingSeedIndices, [2, 0, 1]) - }) + assert.deepStrictEqual(root.state().selectedSeedIndices, [2, 0, 1]); + assert.deepStrictEqual(root.state().pendingSeedIndices, [2, 0, 1]); + }); it('should submit correctly', async function () { const originalSeed = [ @@ -144,10 +147,10 @@ describe('ConfirmSeedPhrase Component', function () { '雞', '狗', '豬', - ] - const metricsEventSpy = sinon.spy() - const pushSpy = sinon.spy() - const initialize3BoxSpy = sinon.spy() + ]; + const metricsEventSpy = sinon.spy(); + const pushSpy = sinon.spy(); + const initialize3BoxSpy = sinon.spy(); const root = shallowRender( { seedPhrase: '鼠 牛 虎 兔 龍 蛇 馬 羊 猴 雞 狗 豬', @@ -158,21 +161,21 @@ describe('ConfirmSeedPhrase Component', function () { { metricsEvent: metricsEventSpy, }, - ) + ); - const sorted = root.state().sortedSeedWords - const seeds = root.find('.confirm-seed-phrase__seed-word--sorted') + const sorted = root.state().sortedSeedWords; + const seeds = root.find('.confirm-seed-phrase__seed-word--sorted'); originalSeed.forEach((seed) => { - const seedIndex = sorted.findIndex((s) => s === seed) - seeds.at(seedIndex).simulate('click') - }) + const seedIndex = sorted.findIndex((s) => s === seed); + seeds.at(seedIndex).simulate('click'); + }); - root.update() + root.update(); - root.find('.first-time-flow__button').simulate('click') + root.find('.first-time-flow__button').simulate('click'); - await new Promise((resolve) => setTimeout(resolve, 100)) + await new Promise((resolve) => setTimeout(resolve, 100)); assert.deepStrictEqual(metricsEventSpy.args[0][0], { eventOpts: { @@ -180,8 +183,8 @@ describe('ConfirmSeedPhrase Component', function () { action: 'Seed Phrase Setup', name: 'Verify Complete', }, - }) - assert(initialize3BoxSpy.calledOnce) - assert.strictEqual(pushSpy.args[0][0], '/initialize/end-of-flow') - }) -}) + }); + assert(initialize3BoxSpy.calledOnce); + assert.strictEqual(pushSpy.args[0][0], '/initialize/end-of-flow'); + }); +}); diff --git a/ui/app/pages/first-time-flow/select-action/index.js b/ui/app/pages/first-time-flow/select-action/index.js index 4fbe1823b..ca98b401d 100644 --- a/ui/app/pages/first-time-flow/select-action/index.js +++ b/ui/app/pages/first-time-flow/select-action/index.js @@ -1 +1 @@ -export { default } from './select-action.container' +export { default } from './select-action.container'; diff --git a/ui/app/pages/first-time-flow/select-action/select-action.component.js b/ui/app/pages/first-time-flow/select-action/select-action.component.js index 993c0b16e..2f02df189 100644 --- a/ui/app/pages/first-time-flow/select-action/select-action.component.js +++ b/ui/app/pages/first-time-flow/select-action/select-action.component.js @@ -1,8 +1,8 @@ -import React, { PureComponent } from 'react' -import PropTypes from 'prop-types' -import Button from '../../../components/ui/button' -import MetaFoxLogo from '../../../components/ui/metafox-logo' -import { INITIALIZE_METAMETRICS_OPT_IN_ROUTE } from '../../../helpers/constants/routes' +import React, { PureComponent } from 'react'; +import PropTypes from 'prop-types'; +import Button from '../../../components/ui/button'; +import MetaFoxLogo from '../../../components/ui/metafox-logo'; +import { INITIALIZE_METAMETRICS_OPT_IN_ROUTE } from '../../../helpers/constants/routes'; export default class SelectAction extends PureComponent { static propTypes = { @@ -10,32 +10,32 @@ export default class SelectAction extends PureComponent { isInitialized: PropTypes.bool, setFirstTimeFlowType: PropTypes.func, nextRoute: PropTypes.string, - } + }; static contextTypes = { t: PropTypes.func, - } + }; componentDidMount() { - const { history, isInitialized, nextRoute } = this.props + const { history, isInitialized, nextRoute } = this.props; if (isInitialized) { - history.push(nextRoute) + history.push(nextRoute); } } handleCreate = () => { - this.props.setFirstTimeFlowType('create') - this.props.history.push(INITIALIZE_METAMETRICS_OPT_IN_ROUTE) - } + this.props.setFirstTimeFlowType('create'); + this.props.history.push(INITIALIZE_METAMETRICS_OPT_IN_ROUTE); + }; handleImport = () => { - this.props.setFirstTimeFlowType('import') - this.props.history.push(INITIALIZE_METAMETRICS_OPT_IN_ROUTE) - } + this.props.setFirstTimeFlowType('import'); + this.props.history.push(INITIALIZE_METAMETRICS_OPT_IN_ROUTE); + }; render() { - const { t } = this.context + const { t } = this.context; return (
    @@ -91,6 +91,6 @@ export default class SelectAction extends PureComponent {
    - ) + ); } } diff --git a/ui/app/pages/first-time-flow/select-action/select-action.container.js b/ui/app/pages/first-time-flow/select-action/select-action.container.js index 7b13c1269..77030f070 100644 --- a/ui/app/pages/first-time-flow/select-action/select-action.container.js +++ b/ui/app/pages/first-time-flow/select-action/select-action.container.js @@ -1,23 +1,23 @@ -import { connect } from 'react-redux' -import { withRouter } from 'react-router-dom' -import { compose } from 'redux' -import { setFirstTimeFlowType } from '../../../store/actions' -import { getFirstTimeFlowTypeRoute } from '../../../selectors' -import Welcome from './select-action.component' +import { connect } from 'react-redux'; +import { withRouter } from 'react-router-dom'; +import { compose } from 'redux'; +import { setFirstTimeFlowType } from '../../../store/actions'; +import { getFirstTimeFlowTypeRoute } from '../../../selectors'; +import Welcome from './select-action.component'; const mapStateToProps = (state) => { return { nextRoute: getFirstTimeFlowTypeRoute(state), - } -} + }; +}; const mapDispatchToProps = (dispatch) => { return { setFirstTimeFlowType: (type) => dispatch(setFirstTimeFlowType(type)), - } -} + }; +}; export default compose( withRouter, connect(mapStateToProps, mapDispatchToProps), -)(Welcome) +)(Welcome); diff --git a/ui/app/pages/first-time-flow/select-action/tests/select-action.test.js b/ui/app/pages/first-time-flow/select-action/tests/select-action.test.js index 447c20602..9f5b66fc6 100644 --- a/ui/app/pages/first-time-flow/select-action/tests/select-action.test.js +++ b/ui/app/pages/first-time-flow/select-action/tests/select-action.test.js @@ -1,11 +1,11 @@ -import assert from 'assert' -import React from 'react' -import sinon from 'sinon' -import { mountWithRouter } from '../../../../../../test/lib/render-helpers' -import SelectAction from '..' +import assert from 'assert'; +import React from 'react'; +import sinon from 'sinon'; +import { mountWithRouter } from '../../../../../../test/lib/render-helpers'; +import SelectAction from '..'; describe('Selection Action', function () { - let wrapper + let wrapper; const props = { isInitialized: false, @@ -13,36 +13,36 @@ describe('Selection Action', function () { history: { push: sinon.spy(), }, - } + }; beforeEach(function () { - wrapper = mountWithRouter() - }) + wrapper = mountWithRouter(); + }); afterEach(function () { - props.setFirstTimeFlowType.resetHistory() - props.history.push.resetHistory() - }) + props.setFirstTimeFlowType.resetHistory(); + props.history.push.resetHistory(); + }); it('clicks import wallet to route to import FTF', function () { const importWalletButton = wrapper .find('.btn-primary.first-time-flow__button') - .at(0) - importWalletButton.simulate('click') + .at(0); + importWalletButton.simulate('click'); - assert(props.setFirstTimeFlowType.calledOnce) - assert.strictEqual(props.setFirstTimeFlowType.getCall(0).args[0], 'import') - assert(props.history.push.calledOnce) - }) + assert(props.setFirstTimeFlowType.calledOnce); + assert.strictEqual(props.setFirstTimeFlowType.getCall(0).args[0], 'import'); + assert(props.history.push.calledOnce); + }); it('clicks create wallet to route to create FTF ', function () { const createWalletButton = wrapper .find('.btn-primary.first-time-flow__button') - .at(1) - createWalletButton.simulate('click') + .at(1); + createWalletButton.simulate('click'); - assert(props.setFirstTimeFlowType.calledOnce) - assert.strictEqual(props.setFirstTimeFlowType.getCall(0).args[0], 'create') - assert(props.history.push.calledOnce) - }) -}) + assert(props.setFirstTimeFlowType.calledOnce); + assert.strictEqual(props.setFirstTimeFlowType.getCall(0).args[0], 'create'); + assert(props.history.push.calledOnce); + }); +}); diff --git a/ui/app/pages/first-time-flow/welcome/index.js b/ui/app/pages/first-time-flow/welcome/index.js index 8abeddaa1..85e9f94a4 100644 --- a/ui/app/pages/first-time-flow/welcome/index.js +++ b/ui/app/pages/first-time-flow/welcome/index.js @@ -1 +1 @@ -export { default } from './welcome.container' +export { default } from './welcome.container'; diff --git a/ui/app/pages/first-time-flow/welcome/tests/welcome.test.js b/ui/app/pages/first-time-flow/welcome/tests/welcome.test.js index 4c35d8c0d..cc8dbab08 100644 --- a/ui/app/pages/first-time-flow/welcome/tests/welcome.test.js +++ b/ui/app/pages/first-time-flow/welcome/tests/welcome.test.js @@ -1,42 +1,42 @@ -import assert from 'assert' -import React from 'react' -import sinon from 'sinon' -import configureMockStore from 'redux-mock-store' -import { mountWithRouter } from '../../../../../../test/lib/render-helpers' -import Welcome from '..' +import assert from 'assert'; +import React from 'react'; +import sinon from 'sinon'; +import configureMockStore from 'redux-mock-store'; +import { mountWithRouter } from '../../../../../../test/lib/render-helpers'; +import Welcome from '..'; describe('Welcome', function () { const mockStore = { metamask: {}, - } + }; - const store = configureMockStore()(mockStore) + const store = configureMockStore()(mockStore); after(function () { - sinon.restore() - }) + sinon.restore(); + }); it('routes to select action when participateInMetaMetrics is not initialized', function () { const props = { history: { push: sinon.spy(), }, - } + }; const wrapper = mountWithRouter( , store, - ) + ); const getStartedButton = wrapper.find( '.btn-primary.first-time-flow__button', - ) - getStartedButton.simulate('click') + ); + getStartedButton.simulate('click'); assert.strictEqual( props.history.push.getCall(0).args[0], '/initialize/select-action', - ) - }) + ); + }); it('routes to correct password when participateInMetaMetrics is initialized', function () { const props = { @@ -45,20 +45,20 @@ describe('Welcome', function () { history: { push: sinon.spy(), }, - } + }; const wrapper = mountWithRouter( , store, - ) + ); const getStartedButton = wrapper.find( '.btn-primary.first-time-flow__button', - ) - getStartedButton.simulate('click') + ); + getStartedButton.simulate('click'); assert.strictEqual( props.history.push.getCall(0).args[0], '/initialize/create-password', - ) - }) -}) + ); + }); +}); diff --git a/ui/app/pages/first-time-flow/welcome/welcome.component.js b/ui/app/pages/first-time-flow/welcome/welcome.component.js index 9b62419c9..43d81b4fa 100644 --- a/ui/app/pages/first-time-flow/welcome/welcome.component.js +++ b/ui/app/pages/first-time-flow/welcome/welcome.component.js @@ -1,46 +1,46 @@ -import EventEmitter from 'events' -import React, { PureComponent } from 'react' -import PropTypes from 'prop-types' -import Mascot from '../../../components/ui/mascot' -import Button from '../../../components/ui/button' +import EventEmitter from 'events'; +import React, { PureComponent } from 'react'; +import PropTypes from 'prop-types'; +import Mascot from '../../../components/ui/mascot'; +import Button from '../../../components/ui/button'; import { INITIALIZE_CREATE_PASSWORD_ROUTE, INITIALIZE_SELECT_ACTION_ROUTE, -} from '../../../helpers/constants/routes' +} from '../../../helpers/constants/routes'; export default class Welcome extends PureComponent { static propTypes = { history: PropTypes.object, participateInMetaMetrics: PropTypes.bool, welcomeScreenSeen: PropTypes.bool, - } + }; static contextTypes = { t: PropTypes.func, - } + }; constructor(props) { - super(props) + super(props); - this.animationEventEmitter = new EventEmitter() + this.animationEventEmitter = new EventEmitter(); } componentDidMount() { - const { history, participateInMetaMetrics, welcomeScreenSeen } = this.props + const { history, participateInMetaMetrics, welcomeScreenSeen } = this.props; if (welcomeScreenSeen && participateInMetaMetrics !== null) { - history.push(INITIALIZE_CREATE_PASSWORD_ROUTE) + history.push(INITIALIZE_CREATE_PASSWORD_ROUTE); } else if (welcomeScreenSeen) { - history.push(INITIALIZE_SELECT_ACTION_ROUTE) + history.push(INITIALIZE_SELECT_ACTION_ROUTE); } } handleContinue = () => { - this.props.history.push(INITIALIZE_SELECT_ACTION_ROUTE) - } + this.props.history.push(INITIALIZE_SELECT_ACTION_ROUTE); + }; render() { - const { t } = this.context + const { t } = this.context; return (
    @@ -64,6 +64,6 @@ export default class Welcome extends PureComponent {
    - ) + ); } } diff --git a/ui/app/pages/first-time-flow/welcome/welcome.container.js b/ui/app/pages/first-time-flow/welcome/welcome.container.js index 9e8aff339..77909d25b 100644 --- a/ui/app/pages/first-time-flow/welcome/welcome.container.js +++ b/ui/app/pages/first-time-flow/welcome/welcome.container.js @@ -1,25 +1,25 @@ -import { connect } from 'react-redux' -import { withRouter } from 'react-router-dom' -import { compose } from 'redux' -import { closeWelcomeScreen } from '../../../store/actions' -import Welcome from './welcome.component' +import { connect } from 'react-redux'; +import { withRouter } from 'react-router-dom'; +import { compose } from 'redux'; +import { closeWelcomeScreen } from '../../../store/actions'; +import Welcome from './welcome.component'; const mapStateToProps = ({ metamask }) => { - const { welcomeScreenSeen, participateInMetaMetrics } = metamask + const { welcomeScreenSeen, participateInMetaMetrics } = metamask; return { welcomeScreenSeen, participateInMetaMetrics, - } -} + }; +}; const mapDispatchToProps = (dispatch) => { return { closeWelcomeScreen: () => dispatch(closeWelcomeScreen()), - } -} + }; +}; export default compose( withRouter, connect(mapStateToProps, mapDispatchToProps), -)(Welcome) +)(Welcome); diff --git a/ui/app/pages/home/home.component.js b/ui/app/pages/home/home.component.js index 92c8d685d..d5b5f75d7 100644 --- a/ui/app/pages/home/home.component.js +++ b/ui/app/pages/home/home.component.js @@ -1,19 +1,19 @@ -import React, { PureComponent } from 'react' -import PropTypes from 'prop-types' -import { Redirect, Route } from 'react-router-dom' -import { formatDate } from '../../helpers/utils/util' -import AssetList from '../../components/app/asset-list' -import HomeNotification from '../../components/app/home-notification' -import MultipleNotifications from '../../components/app/multiple-notifications' -import TransactionList from '../../components/app/transaction-list' -import MenuBar from '../../components/app/menu-bar' -import Popover from '../../components/ui/popover' -import Button from '../../components/ui/button' -import ConnectedSites from '../connected-sites' -import ConnectedAccounts from '../connected-accounts' -import { Tabs, Tab } from '../../components/ui/tabs' -import { EthOverview } from '../../components/app/wallet-overview' -import SwapsIntroPopup from '../swaps/intro-popup' +import React, { PureComponent } from 'react'; +import PropTypes from 'prop-types'; +import { Redirect, Route } from 'react-router-dom'; +import { formatDate } from '../../helpers/utils/util'; +import AssetList from '../../components/app/asset-list'; +import HomeNotification from '../../components/app/home-notification'; +import MultipleNotifications from '../../components/app/multiple-notifications'; +import TransactionList from '../../components/app/transaction-list'; +import MenuBar from '../../components/app/menu-bar'; +import Popover from '../../components/ui/popover'; +import Button from '../../components/ui/button'; +import ConnectedSites from '../connected-sites'; +import ConnectedAccounts from '../connected-accounts'; +import { Tabs, Tab } from '../../components/ui/tabs'; +import { EthOverview } from '../../components/app/wallet-overview'; +import SwapsIntroPopup from '../swaps/intro-popup'; import { ASSET_ROUTE, @@ -27,17 +27,17 @@ import { AWAITING_SWAP_ROUTE, BUILD_QUOTE_ROUTE, VIEW_QUOTE_ROUTE, -} from '../../helpers/constants/routes' +} from '../../helpers/constants/routes'; const LEARN_MORE_URL = - 'https://metamask.zendesk.com/hc/en-us/articles/360045129011-Intro-to-MetaMask-v8-extension' + 'https://metamask.zendesk.com/hc/en-us/articles/360045129011-Intro-to-MetaMask-v8-extension'; const LEGACY_WEB3_URL = - 'https://metamask.zendesk.com/hc/en-us/articles/360053147012' + 'https://metamask.zendesk.com/hc/en-us/articles/360053147012'; export default class Home extends PureComponent { static contextTypes = { t: PropTypes.func, - } + }; static propTypes = { history: PropTypes.object, @@ -72,11 +72,11 @@ export default class Home extends PureComponent { setWeb3ShimUsageAlertDismissed: PropTypes.func.isRequired, originOfCurrentTab: PropTypes.string, disableWeb3ShimUsageAlert: PropTypes.func.isRequired, - } + }; state = { mounted: false, - } + }; componentDidMount() { const { @@ -89,23 +89,23 @@ export default class Home extends PureComponent { haveSwapsQuotes, showAwaitingSwapScreen, swapsFetchParams, - } = this.props + } = this.props; - this.setState({ mounted: true }) + this.setState({ mounted: true }); if (isNotification && totalUnapprovedCount === 0) { - global.platform.closeCurrentWindow() + global.platform.closeCurrentWindow(); } else if (!isNotification && showAwaitingSwapScreen) { - history.push(AWAITING_SWAP_ROUTE) + history.push(AWAITING_SWAP_ROUTE); } else if (!isNotification && haveSwapsQuotes) { - history.push(VIEW_QUOTE_ROUTE) + history.push(VIEW_QUOTE_ROUTE); } else if (!isNotification && swapsFetchParams) { - history.push(BUILD_QUOTE_ROUTE) + history.push(BUILD_QUOTE_ROUTE); } else if (firstPermissionsRequestId) { - history.push(`${CONNECT_ROUTE}/${firstPermissionsRequestId}`) + history.push(`${CONNECT_ROUTE}/${firstPermissionsRequestId}`); } else if (unconfirmedTransactionsCount > 0) { - history.push(CONFIRM_TRANSACTION_ROUTE) + history.push(CONFIRM_TRANSACTION_ROUTE); } else if (Object.keys(suggestedTokens).length > 0) { - history.push(CONFIRM_ADD_SUGGESTED_TOKEN_ROUTE) + history.push(CONFIRM_ADD_SUGGESTED_TOKEN_ROUTE); } } @@ -124,7 +124,7 @@ export default class Home extends PureComponent { ) { if (!mounted) { if (isNotification && totalUnapprovedCount === 0) { - return { closing: true } + return { closing: true }; } else if ( firstPermissionsRequestId || unconfirmedTransactionsCount > 0 || @@ -132,10 +132,10 @@ export default class Home extends PureComponent { (!isNotification && (showAwaitingSwapScreen || haveSwapsQuotes || swapsFetchParams)) ) { - return { redirecting: true } + return { redirecting: true }; } } - return null + return null; } componentDidUpdate(_, prevState) { @@ -144,19 +144,19 @@ export default class Home extends PureComponent { showRestorePrompt, threeBoxLastUpdated, threeBoxSynced, - } = this.props + } = this.props; if (!prevState.closing && this.state.closing) { - global.platform.closeCurrentWindow() + global.platform.closeCurrentWindow(); } if (threeBoxSynced && showRestorePrompt && threeBoxLastUpdated === null) { - setupThreeBox() + setupThreeBox(); } } renderNotifications() { - const { t } = this.context + const { t } = this.context; const { history, shouldShowSeedPhraseReminder, @@ -171,7 +171,7 @@ export default class Home extends PureComponent { setWeb3ShimUsageAlertDismissed, originOfCurrentTab, disableWeb3ShimUsageAlert, - } = this.props + } = this.props; return ( @@ -190,9 +190,9 @@ export default class Home extends PureComponent { ])} ignoreText={t('dismiss')} onIgnore={(disable) => { - setWeb3ShimUsageAlertDismissed(originOfCurrentTab) + setWeb3ShimUsageAlertDismissed(originOfCurrentTab); if (disable) { - disableWeb3ShimUsageAlert() + disableWeb3ShimUsageAlert(); } }} checkboxText={t('dontShowThisAgain')} @@ -208,9 +208,9 @@ export default class Home extends PureComponent { if (isPopup) { global.platform.openExtensionInBrowser( INITIALIZE_BACKUP_SEED_PHRASE_ROUTE, - ) + ); } else { - history.push(INITIALIZE_BACKUP_SEED_PHRASE_ROUTE) + history.push(INITIALIZE_BACKUP_SEED_PHRASE_ROUTE); } }} infoText={t('backupApprovalInfo')} @@ -227,22 +227,22 @@ export default class Home extends PureComponent { infoText={t('dataBackupFoundInfo')} onAccept={() => { restoreFromThreeBox(selectedAddress).then(() => { - turnThreeBoxSyncingOn() - }) + turnThreeBoxSyncingOn(); + }); }} onIgnore={() => { - setShowRestorePromptToFalse() + setShowRestorePromptToFalse(); }} key="home-privacyModeDefault" /> ) : null} - ) + ); } renderPopover = () => { - const { setConnectedStatusPopoverHasBeenShown } = this.props - const { t } = this.context + const { setConnectedStatusPopoverHasBeenShown } = this.props; + const { t } = this.context; return (
    - ) + ); }} footer={ <> @@ -279,11 +279,11 @@ export default class Home extends PureComponent {
    {t('metaMaskConnectStatusParagraphThree')}
    - ) - } + ); + }; render() { - const { t } = this.context + const { t } = this.context; const { defaultHomeActiveTabName, onTabClick, @@ -295,12 +295,12 @@ export default class Home extends PureComponent { setSwapsWelcomeMessageHasBeenShown, swapsEnabled, isMainnet, - } = this.props + } = this.props; if (forgottenPassword) { - return + return ; } else if (this.state.closing || this.state.redirecting) { - return null + return null; } return ( @@ -353,6 +353,6 @@ export default class Home extends PureComponent { {this.renderNotifications()} - ) + ); } } diff --git a/ui/app/pages/home/home.container.js b/ui/app/pages/home/home.container.js index ba4b9e6d4..b53a5a96d 100644 --- a/ui/app/pages/home/home.container.js +++ b/ui/app/pages/home/home.container.js @@ -1,6 +1,6 @@ -import { compose } from 'redux' -import { connect } from 'react-redux' -import { withRouter } from 'react-router-dom' +import { compose } from 'redux'; +import { connect } from 'react-redux'; +import { withRouter } from 'react-router-dom'; import { activeTabHasPermissions, getCurrentEthBalance, @@ -10,7 +10,7 @@ import { getTotalUnapprovedCount, getWeb3ShimUsageStateForOrigin, unconfirmedTransactionsCountSelector, -} from '../../selectors' +} from '../../selectors'; import { restoreFromThreeBox, @@ -22,26 +22,26 @@ import { setSwapsWelcomeMessageHasBeenShown, setWeb3ShimUsageAlertDismissed, setAlertEnabledness, -} from '../../store/actions' -import { setThreeBoxLastUpdated } from '../../ducks/app/app' -import { getWeb3ShimUsageAlertEnabledness } from '../../ducks/metamask/metamask' +} from '../../store/actions'; +import { setThreeBoxLastUpdated } from '../../ducks/app/app'; +import { getWeb3ShimUsageAlertEnabledness } from '../../ducks/metamask/metamask'; import { getSwapsWelcomeMessageSeenStatus, getSwapsFeatureLiveness, -} from '../../ducks/swaps/swaps' -import { getEnvironmentType } from '../../../../app/scripts/lib/util' +} from '../../ducks/swaps/swaps'; +import { getEnvironmentType } from '../../../../app/scripts/lib/util'; import { ENVIRONMENT_TYPE_NOTIFICATION, ENVIRONMENT_TYPE_POPUP, -} from '../../../../shared/constants/app' +} from '../../../../shared/constants/app'; import { ALERT_TYPES, WEB3_SHIM_USAGE_ALERT_STATES, -} from '../../../../shared/constants/alerts' -import Home from './home.component' +} from '../../../../shared/constants/alerts'; +import Home from './home.component'; const mapStateToProps = (state) => { - const { metamask, appState } = state + const { metamask, appState } = state; const { suggestedTokens, seedPhraseBackedUp, @@ -52,29 +52,29 @@ const mapStateToProps = (state) => { connectedStatusPopoverHasBeenShown, defaultHomeActiveTabName, swapsState, - } = metamask - const accountBalance = getCurrentEthBalance(state) - const { forgottenPassword, threeBoxLastUpdated } = appState - const totalUnapprovedCount = getTotalUnapprovedCount(state) - const swapsEnabled = getSwapsFeatureLiveness(state) + } = metamask; + const accountBalance = getCurrentEthBalance(state); + const { forgottenPassword, threeBoxLastUpdated } = appState; + const totalUnapprovedCount = getTotalUnapprovedCount(state); + const swapsEnabled = getSwapsFeatureLiveness(state); - const envType = getEnvironmentType() - const isPopup = envType === ENVIRONMENT_TYPE_POPUP - const isNotification = envType === ENVIRONMENT_TYPE_NOTIFICATION + const envType = getEnvironmentType(); + const isPopup = envType === ENVIRONMENT_TYPE_POPUP; + const isNotification = envType === ENVIRONMENT_TYPE_NOTIFICATION; - const firstPermissionsRequest = getFirstPermissionRequest(state) + const firstPermissionsRequest = getFirstPermissionRequest(state); const firstPermissionsRequestId = firstPermissionsRequest && firstPermissionsRequest.metadata ? firstPermissionsRequest.metadata.id - : null + : null; - const originOfCurrentTab = getOriginOfCurrentTab(state) + const originOfCurrentTab = getOriginOfCurrentTab(state); const shouldShowWeb3ShimUsageNotification = isPopup && getWeb3ShimUsageAlertEnabledness(state) && activeTabHasPermissions(state) && getWeb3ShimUsageStateForOrigin(state, originOfCurrentTab) === - WEB3_SHIM_USAGE_ALERT_STATES.RECORDED + WEB3_SHIM_USAGE_ALERT_STATES.RECORDED; return { forgottenPassword, @@ -101,20 +101,20 @@ const mapStateToProps = (state) => { isMainnet: getIsMainnet(state), originOfCurrentTab, shouldShowWeb3ShimUsageNotification, - } -} + }; +}; const mapDispatchToProps = (dispatch) => ({ turnThreeBoxSyncingOn: () => dispatch(turnThreeBoxSyncingOn()), setupThreeBox: () => { dispatch(getThreeBoxLastUpdated()).then((lastUpdated) => { if (lastUpdated) { - dispatch(setThreeBoxLastUpdated(lastUpdated)) + dispatch(setThreeBoxLastUpdated(lastUpdated)); } else { - dispatch(setShowRestorePromptToFalse()) - dispatch(turnThreeBoxSyncingOn()) + dispatch(setShowRestorePromptToFalse()); + dispatch(turnThreeBoxSyncingOn()); } - }) + }); }, restoreFromThreeBox: (address) => dispatch(restoreFromThreeBox(address)), setShowRestorePromptToFalse: () => dispatch(setShowRestorePromptToFalse()), @@ -127,9 +127,9 @@ const mapDispatchToProps = (dispatch) => ({ setWeb3ShimUsageAlertDismissed(origin), disableWeb3ShimUsageAlert: () => setAlertEnabledness(ALERT_TYPES.web3ShimUsage, false), -}) +}); export default compose( withRouter, connect(mapStateToProps, mapDispatchToProps), -)(Home) +)(Home); diff --git a/ui/app/pages/home/index.js b/ui/app/pages/home/index.js index 4474ba5b8..b306d2090 100644 --- a/ui/app/pages/home/index.js +++ b/ui/app/pages/home/index.js @@ -1 +1 @@ -export { default } from './home.container' +export { default } from './home.container'; diff --git a/ui/app/pages/index.js b/ui/app/pages/index.js index e64ea3f22..3033e2946 100644 --- a/ui/app/pages/index.js +++ b/ui/app/pages/index.js @@ -1,34 +1,34 @@ -import React, { PureComponent } from 'react' -import PropTypes from 'prop-types' -import { Provider } from 'react-redux' -import { HashRouter } from 'react-router-dom' -import * as Sentry from '@sentry/browser' -import { I18nProvider, LegacyI18nProvider } from '../contexts/i18n' +import React, { PureComponent } from 'react'; +import PropTypes from 'prop-types'; +import { Provider } from 'react-redux'; +import { HashRouter } from 'react-router-dom'; +import * as Sentry from '@sentry/browser'; +import { I18nProvider, LegacyI18nProvider } from '../contexts/i18n'; import { MetaMetricsProvider, LegacyMetaMetricsProvider, -} from '../contexts/metametrics' +} from '../contexts/metametrics'; import { MetaMetricsProvider as NewMetaMetricsProvider, LegacyMetaMetricsProvider as NewLegacyMetaMetricsProvider, -} from '../contexts/metametrics.new' -import ErrorPage from './error' -import Routes from './routes' +} from '../contexts/metametrics.new'; +import ErrorPage from './error'; +import Routes from './routes'; class Index extends PureComponent { - state = {} + state = {}; static getDerivedStateFromError(error) { - return { error } + return { error }; } componentDidCatch(error) { - Sentry.captureException(error) + Sentry.captureException(error); } render() { - const { error, errorId } = this.state - const { store } = this.props + const { error, errorId } = this.state; + const { store } = this.props; if (error) { return ( @@ -39,7 +39,7 @@ class Index extends PureComponent { - ) + ); } return ( @@ -60,12 +60,12 @@ class Index extends PureComponent { - ) + ); } } Index.propTypes = { store: PropTypes.object, -} +}; -export default Index +export default Index; diff --git a/ui/app/pages/keychains/restore-vault.js b/ui/app/pages/keychains/restore-vault.js index b8dab7ba5..fc1121c7b 100644 --- a/ui/app/pages/keychains/restore-vault.js +++ b/ui/app/pages/keychains/restore-vault.js @@ -1,20 +1,20 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import { connect } from 'react-redux' +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import { connect } from 'react-redux'; import { createNewVaultAndRestore, unMarkPasswordForgotten, initializeThreeBox, -} from '../../store/actions' -import { DEFAULT_ROUTE } from '../../helpers/constants/routes' -import TextField from '../../components/ui/text-field' -import Button from '../../components/ui/button' +} from '../../store/actions'; +import { DEFAULT_ROUTE } from '../../helpers/constants/routes'; +import TextField from '../../components/ui/text-field'; +import Button from '../../components/ui/button'; class RestoreVaultPage extends Component { static contextTypes = { t: PropTypes.func, metricsEvent: PropTypes.func, - } + }; static propTypes = { createNewVaultAndRestore: PropTypes.func.isRequired, @@ -22,7 +22,7 @@ class RestoreVaultPage extends Component { history: PropTypes.object, isLoading: PropTypes.bool, initializeThreeBox: PropTypes.func, - } + }; state = { seedPhrase: '', @@ -32,54 +32,54 @@ class RestoreVaultPage extends Component { seedPhraseError: null, passwordError: null, confirmPasswordError: null, - } + }; parseSeedPhrase = (seedPhrase) => - (seedPhrase || '').trim().toLowerCase().match(/\w+/gu)?.join(' ') || '' + (seedPhrase || '').trim().toLowerCase().match(/\w+/gu)?.join(' ') || ''; handleSeedPhraseChange(seedPhrase) { - let seedPhraseError = null + let seedPhraseError = null; - const wordCount = this.parseSeedPhrase(seedPhrase).split(/\s/u).length + const wordCount = this.parseSeedPhrase(seedPhrase).split(/\s/u).length; if ( seedPhrase && (wordCount % 3 !== 0 || wordCount < 12 || wordCount > 24) ) { - seedPhraseError = this.context.t('seedPhraseReq') + seedPhraseError = this.context.t('seedPhraseReq'); } - this.setState({ seedPhrase, seedPhraseError }) + this.setState({ seedPhrase, seedPhraseError }); } handlePasswordChange(password) { - const { confirmPassword } = this.state - let confirmPasswordError = null - let passwordError = null + const { confirmPassword } = this.state; + let confirmPasswordError = null; + let passwordError = null; if (password && password.length < 8) { - passwordError = this.context.t('passwordNotLongEnough') + passwordError = this.context.t('passwordNotLongEnough'); } if (confirmPassword && password !== confirmPassword) { - confirmPasswordError = this.context.t('passwordsDontMatch') + confirmPasswordError = this.context.t('passwordsDontMatch'); } - this.setState({ password, passwordError, confirmPasswordError }) + this.setState({ password, passwordError, confirmPasswordError }); } handleConfirmPasswordChange(confirmPassword) { - const { password } = this.state - let confirmPasswordError = null + const { password } = this.state; + let confirmPasswordError = null; if (password !== confirmPassword) { - confirmPasswordError = this.context.t('passwordsDontMatch') + confirmPasswordError = this.context.t('passwordsDontMatch'); } - this.setState({ confirmPassword, confirmPasswordError }) + this.setState({ confirmPassword, confirmPasswordError }); } onClick = () => { - const { password, seedPhrase } = this.state + const { password, seedPhrase } = this.state; const { // eslint-disable-next-line no-shadow createNewVaultAndRestore, @@ -87,9 +87,9 @@ class RestoreVaultPage extends Component { history, // eslint-disable-next-line no-shadow initializeThreeBox, - } = this.props + } = this.props; - leaveImportSeedScreenState() + leaveImportSeedScreenState(); createNewVaultAndRestore(password, this.parseSeedPhrase(seedPhrase)).then( () => { this.context.metricsEvent({ @@ -98,23 +98,23 @@ class RestoreVaultPage extends Component { action: 'userEntersSeedPhrase', name: 'onboardingRestoredVault', }, - }) - initializeThreeBox() - history.push(DEFAULT_ROUTE) + }); + initializeThreeBox(); + history.push(DEFAULT_ROUTE); }, - ) - } + ); + }; hasError() { - const { passwordError, confirmPasswordError, seedPhraseError } = this.state - return passwordError || confirmPasswordError || seedPhraseError + const { passwordError, confirmPasswordError, seedPhraseError } = this.state; + return passwordError || confirmPasswordError || seedPhraseError; } toggleShowSeedPhrase = () => { this.setState(({ showSeedPhrase }) => ({ showSeedPhrase: !showSeedPhrase, - })) - } + })); + }; render() { const { @@ -125,15 +125,15 @@ class RestoreVaultPage extends Component { seedPhraseError, passwordError, confirmPasswordError, - } = this.state - const { t } = this.context - const { isLoading } = this.props + } = this.state; + const { t } = this.context; + const { isLoading } = this.props; const disabled = !seedPhrase || !password || !confirmPassword || isLoading || - this.hasError() + this.hasError(); return (
    - ) + ); } } @@ -248,10 +248,10 @@ export default connect( ({ appState: { isLoading } }) => ({ isLoading }), (dispatch) => ({ leaveImportSeedScreenState: () => { - dispatch(unMarkPasswordForgotten()) + dispatch(unMarkPasswordForgotten()); }, createNewVaultAndRestore: (pw, seed) => dispatch(createNewVaultAndRestore(pw, seed)), initializeThreeBox: () => dispatch(initializeThreeBox()), }), -)(RestoreVaultPage) +)(RestoreVaultPage); diff --git a/ui/app/pages/keychains/reveal-seed.js b/ui/app/pages/keychains/reveal-seed.js index 94f940617..f9ac0c105 100644 --- a/ui/app/pages/keychains/reveal-seed.js +++ b/ui/app/pages/keychains/reveal-seed.js @@ -1,15 +1,15 @@ -import React, { Component } from 'react' -import { connect } from 'react-redux' -import PropTypes from 'prop-types' -import classnames from 'classnames' -import { requestRevealSeedWords } from '../../store/actions' -import ExportTextContainer from '../../components/ui/export-text-container' -import { getMostRecentOverviewPage } from '../../ducks/history/history' +import React, { Component } from 'react'; +import { connect } from 'react-redux'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; +import { requestRevealSeedWords } from '../../store/actions'; +import ExportTextContainer from '../../components/ui/export-text-container'; +import { getMostRecentOverviewPage } from '../../ducks/history/history'; -import Button from '../../components/ui/button' +import Button from '../../components/ui/button'; -const PASSWORD_PROMPT_SCREEN = 'PASSWORD_PROMPT_SCREEN' -const REVEAL_SEED_SCREEN = 'REVEAL_SEED_SCREEN' +const PASSWORD_PROMPT_SCREEN = 'PASSWORD_PROMPT_SCREEN'; +const REVEAL_SEED_SCREEN = 'REVEAL_SEED_SCREEN'; class RevealSeedPage extends Component { state = { @@ -17,24 +17,24 @@ class RevealSeedPage extends Component { password: '', seedWords: null, error: null, - } + }; componentDidMount() { - const passwordBox = document.getElementById('password-box') + const passwordBox = document.getElementById('password-box'); if (passwordBox) { - passwordBox.focus() + passwordBox.focus(); } } handleSubmit(event) { - event.preventDefault() - this.setState({ seedWords: null, error: null }) + event.preventDefault(); + this.setState({ seedWords: null, error: null }); this.props .requestRevealSeedWords(this.state.password) .then((seedWords) => this.setState({ seedWords, screen: REVEAL_SEED_SCREEN }), ) - .catch((error) => this.setState({ error: error.message })) + .catch((error) => this.setState({ error: error.message })); } renderWarning() { @@ -52,17 +52,17 @@ class RevealSeedPage extends Component {
    {this.context.t('revealSeedWordsWarning')}
    - ) + ); } renderContent() { return this.state.screen === PASSWORD_PROMPT_SCREEN ? this.renderPasswordPromptContent() - : this.renderRevealSeedContent() + : this.renderRevealSeedContent(); } renderPasswordPromptContent() { - const { t } = this.context + const { t } = this.context; return (
    this.handleSubmit(event)}> @@ -87,11 +87,11 @@ class RevealSeedPage extends Component {
    {this.state.error}
    )}
    - ) + ); } renderRevealSeedContent() { - const { t } = this.context + const { t } = this.context; return (
    @@ -100,13 +100,13 @@ class RevealSeedPage extends Component {
    - ) + ); } renderFooter() { return this.state.screen === PASSWORD_PROMPT_SCREEN ? this.renderPasswordPromptFooter() - : this.renderRevealSeedFooter() + : this.renderRevealSeedFooter(); } renderPasswordPromptFooter() { @@ -134,7 +134,7 @@ class RevealSeedPage extends Component { - ) + ); } renderRevealSeedFooter() { @@ -151,7 +151,7 @@ class RevealSeedPage extends Component { {this.context.t('close')} - ) + ); } render() { @@ -171,7 +171,7 @@ class RevealSeedPage extends Component { {this.renderFooter()} - ) + ); } } @@ -179,23 +179,23 @@ RevealSeedPage.propTypes = { requestRevealSeedWords: PropTypes.func, history: PropTypes.object, mostRecentOverviewPage: PropTypes.string.isRequired, -} +}; RevealSeedPage.contextTypes = { t: PropTypes.func, -} +}; const mapStateToProps = (state) => { return { mostRecentOverviewPage: getMostRecentOverviewPage(state), - } -} + }; +}; const mapDispatchToProps = (dispatch) => { return { requestRevealSeedWords: (password) => dispatch(requestRevealSeedWords(password)), - } -} + }; +}; -export default connect(mapStateToProps, mapDispatchToProps)(RevealSeedPage) +export default connect(mapStateToProps, mapDispatchToProps)(RevealSeedPage); diff --git a/ui/app/pages/keychains/tests/reveal-seed.test.js b/ui/app/pages/keychains/tests/reveal-seed.test.js index 7cb867588..8eeda0ae0 100644 --- a/ui/app/pages/keychains/tests/reveal-seed.test.js +++ b/ui/app/pages/keychains/tests/reveal-seed.test.js @@ -1,8 +1,8 @@ -import assert from 'assert' -import React from 'react' -import sinon from 'sinon' -import { mount } from 'enzyme' -import RevealSeedPage from '../reveal-seed' +import assert from 'assert'; +import React from 'react'; +import sinon from 'sinon'; +import { mount } from 'enzyme'; +import RevealSeedPage from '../reveal-seed'; describe('Reveal Seed Page', function () { it('form submit', function () { @@ -11,14 +11,14 @@ describe('Reveal Seed Page', function () { push: sinon.spy(), }, requestRevealSeedWords: sinon.stub().resolves(), - } + }; const wrapper = mount(, { context: { t: (str) => str, }, - }) + }); - wrapper.find('form').simulate('submit') - assert(props.requestRevealSeedWords.calledOnce) - }) -}) + wrapper.find('form').simulate('submit'); + assert(props.requestRevealSeedWords.calledOnce); + }); +}); diff --git a/ui/app/pages/lock/index.js b/ui/app/pages/lock/index.js index 7bfe2a61f..793e47c23 100644 --- a/ui/app/pages/lock/index.js +++ b/ui/app/pages/lock/index.js @@ -1 +1 @@ -export { default } from './lock.container' +export { default } from './lock.container'; diff --git a/ui/app/pages/lock/lock.component.js b/ui/app/pages/lock/lock.component.js index a415f5b55..4b801f540 100644 --- a/ui/app/pages/lock/lock.component.js +++ b/ui/app/pages/lock/lock.component.js @@ -1,26 +1,26 @@ -import React, { PureComponent } from 'react' -import PropTypes from 'prop-types' -import Loading from '../../components/ui/loading-screen' -import { DEFAULT_ROUTE } from '../../helpers/constants/routes' +import React, { PureComponent } from 'react'; +import PropTypes from 'prop-types'; +import Loading from '../../components/ui/loading-screen'; +import { DEFAULT_ROUTE } from '../../helpers/constants/routes'; export default class Lock extends PureComponent { static propTypes = { history: PropTypes.object, isUnlocked: PropTypes.bool, lockMetamask: PropTypes.func, - } + }; componentDidMount() { - const { lockMetamask, isUnlocked, history } = this.props + const { lockMetamask, isUnlocked, history } = this.props; if (isUnlocked) { - lockMetamask().then(() => history.push(DEFAULT_ROUTE)) + lockMetamask().then(() => history.push(DEFAULT_ROUTE)); } else { - history.replace(DEFAULT_ROUTE) + history.replace(DEFAULT_ROUTE); } } render() { - return + return ; } } diff --git a/ui/app/pages/lock/lock.container.js b/ui/app/pages/lock/lock.container.js index b1da86f67..c029d8ddc 100644 --- a/ui/app/pages/lock/lock.container.js +++ b/ui/app/pages/lock/lock.container.js @@ -1,26 +1,26 @@ -import { compose } from 'redux' -import { connect } from 'react-redux' -import { withRouter } from 'react-router-dom' -import { lockMetamask } from '../../store/actions' -import Lock from './lock.component' +import { compose } from 'redux'; +import { connect } from 'react-redux'; +import { withRouter } from 'react-router-dom'; +import { lockMetamask } from '../../store/actions'; +import Lock from './lock.component'; const mapStateToProps = (state) => { const { metamask: { isUnlocked }, - } = state + } = state; return { isUnlocked, - } -} + }; +}; const mapDispatchToProps = (dispatch) => { return { lockMetamask: () => dispatch(lockMetamask()), - } -} + }; +}; export default compose( withRouter, connect(mapStateToProps, mapDispatchToProps), -)(Lock) +)(Lock); diff --git a/ui/app/pages/lock/tests/lock.test.js b/ui/app/pages/lock/tests/lock.test.js index 688fe062a..529fe0176 100644 --- a/ui/app/pages/lock/tests/lock.test.js +++ b/ui/app/pages/lock/tests/lock.test.js @@ -1,8 +1,8 @@ -import assert from 'assert' -import React from 'react' -import sinon from 'sinon' -import { mountWithRouter } from '../../../../../test/lib/render-helpers' -import Lock from '..' +import assert from 'assert'; +import React from 'react'; +import sinon from 'sinon'; +import { mountWithRouter } from '../../../../../test/lib/render-helpers'; +import Lock from '..'; describe('Lock', function () { it('replaces history with default route when isUnlocked false', function () { @@ -11,12 +11,12 @@ describe('Lock', function () { history: { replace: sinon.spy(), }, - } + }; - mountWithRouter() + mountWithRouter(); - assert.strictEqual(props.history.replace.getCall(0).args[0], '/') - }) + assert.strictEqual(props.history.replace.getCall(0).args[0], '/'); + }); it('locks and pushes history with default route when isUnlocked true', function (done) { const props = { @@ -25,16 +25,16 @@ describe('Lock', function () { history: { push: sinon.spy(), }, - } + }; - props.lockMetamask.resolves() + props.lockMetamask.resolves(); - mountWithRouter() + mountWithRouter(); - assert(props.lockMetamask.calledOnce) + assert(props.lockMetamask.calledOnce); setImmediate(() => { - assert.strictEqual(props.history.push.getCall(0).args[0], '/') - done() - }) - }) -}) + assert.strictEqual(props.history.push.getCall(0).args[0], '/'); + done(); + }); + }); +}); diff --git a/ui/app/pages/mobile-sync/index.js b/ui/app/pages/mobile-sync/index.js index c7df5ede5..be41d814c 100644 --- a/ui/app/pages/mobile-sync/index.js +++ b/ui/app/pages/mobile-sync/index.js @@ -1 +1 @@ -export { default } from './mobile-sync.container' +export { default } from './mobile-sync.container'; diff --git a/ui/app/pages/mobile-sync/mobile-sync.component.js b/ui/app/pages/mobile-sync/mobile-sync.component.js index e7efc2364..339bfa130 100644 --- a/ui/app/pages/mobile-sync/mobile-sync.component.js +++ b/ui/app/pages/mobile-sync/mobile-sync.component.js @@ -1,22 +1,22 @@ -import React, { Component } from 'react' +import React, { Component } from 'react'; -import PropTypes from 'prop-types' -import classnames from 'classnames' -import PubNub from 'pubnub' -import qrCode from 'qrcode-generator' +import PropTypes from 'prop-types'; +import classnames from 'classnames'; +import PubNub from 'pubnub'; +import qrCode from 'qrcode-generator'; -import Button from '../../components/ui/button' -import LoadingScreen from '../../components/ui/loading-screen' +import Button from '../../components/ui/button'; +import LoadingScreen from '../../components/ui/loading-screen'; -const PASSWORD_PROMPT_SCREEN = 'PASSWORD_PROMPT_SCREEN' -const REVEAL_SEED_SCREEN = 'REVEAL_SEED_SCREEN' -const KEYS_GENERATION_TIME = 30000 -const IDLE_TIME = KEYS_GENERATION_TIME * 4 +const PASSWORD_PROMPT_SCREEN = 'PASSWORD_PROMPT_SCREEN'; +const REVEAL_SEED_SCREEN = 'REVEAL_SEED_SCREEN'; +const KEYS_GENERATION_TIME = 30000; +const IDLE_TIME = KEYS_GENERATION_TIME * 4; export default class MobileSyncPage extends Component { static contextTypes = { t: PropTypes.func, - } + }; static propTypes = { history: PropTypes.object.isRequired, @@ -27,7 +27,7 @@ export default class MobileSyncPage extends Component { requestRevealSeedWords: PropTypes.func.isRequired, exportAccounts: PropTypes.func.isRequired, keyrings: PropTypes.array, - } + }; state = { screen: PASSWORD_PROMPT_SCREEN, @@ -39,151 +39,152 @@ export default class MobileSyncPage extends Component { completed: false, channelName: undefined, cipherKey: undefined, - } + }; - syncing = false + syncing = false; componentDidMount() { - const passwordBox = document.getElementById('password-box') + const passwordBox = document.getElementById('password-box'); if (passwordBox) { - passwordBox.focus() + passwordBox.focus(); } } startIdleTimeout() { this.idleTimeout = setTimeout(() => { - this.clearTimeouts() - this.goBack() - }, IDLE_TIME) + this.clearTimeouts(); + this.goBack(); + }, IDLE_TIME); } handleSubmit(event) { - event.preventDefault() - this.setState({ seedWords: null, error: null }) + event.preventDefault(); + this.setState({ seedWords: null, error: null }); this.props .requestRevealSeedWords(this.state.password) .then((seedWords) => { - this.startKeysGeneration() - this.startIdleTimeout() + this.startKeysGeneration(); + this.startIdleTimeout(); this.exportAccounts().then((importedAccounts) => { this.setState({ seedWords, importedAccounts, screen: REVEAL_SEED_SCREEN, - }) - }) + }); + }); }) - .catch((error) => this.setState({ error: error.message })) + .catch((error) => this.setState({ error: error.message })); } async exportAccounts() { - const addresses = [] + const addresses = []; this.props.keyrings.forEach((keyring) => { if (keyring.type === 'Simple Key Pair') { - addresses.push(keyring.accounts[0]) + addresses.push(keyring.accounts[0]); } - }) + }); const importedAccounts = await this.props.exportAccounts( this.state.password, addresses, - ) - return importedAccounts + ); + return importedAccounts; } startKeysGeneration() { - this.keysGenerationTimeout && clearTimeout(this.keysGenerationTimeout) - this.disconnectWebsockets() - this.generateCipherKeyAndChannelName() - this.initWebsockets() + this.keysGenerationTimeout && clearTimeout(this.keysGenerationTimeout); + this.disconnectWebsockets(); + this.generateCipherKeyAndChannelName(); + this.initWebsockets(); this.keysGenerationTimeout = setTimeout(() => { - this.startKeysGeneration() - }, KEYS_GENERATION_TIME) + this.startKeysGeneration(); + }, KEYS_GENERATION_TIME); } goBack() { - const { history, mostRecentOverviewPage } = this.props - history.push(mostRecentOverviewPage) + const { history, mostRecentOverviewPage } = this.props; + history.push(mostRecentOverviewPage); } clearTimeouts() { - this.keysGenerationTimeout && clearTimeout(this.keysGenerationTimeout) - this.idleTimeout && clearTimeout(this.idleTimeout) + this.keysGenerationTimeout && clearTimeout(this.keysGenerationTimeout); + this.idleTimeout && clearTimeout(this.idleTimeout); } generateCipherKeyAndChannelName() { this.cipherKey = `${this.props.selectedAddress.substr( -4, - )}-${PubNub.generateUUID()}` - this.channelName = `mm-${PubNub.generateUUID()}` - this.setState({ cipherKey: this.cipherKey, channelName: this.channelName }) + )}-${PubNub.generateUUID()}`; + this.channelName = `mm-${PubNub.generateUUID()}`; + this.setState({ cipherKey: this.cipherKey, channelName: this.channelName }); } initWithCipherKeyAndChannelName(cipherKey, channelName) { - this.cipherKey = cipherKey - this.channelName = channelName + this.cipherKey = cipherKey; + this.channelName = channelName; } initWebsockets() { // Make sure there are no existing listeners - this.disconnectWebsockets() + this.disconnectWebsockets(); this.pubnub = new PubNub({ subscribeKey: process.env.PUBNUB_SUB_KEY, publishKey: process.env.PUBNUB_PUB_KEY, cipherKey: this.cipherKey, ssl: true, - }) + }); this.pubnubListener = { message: (data) => { - const { channel, message } = data + const { channel, message } = data; // handle message if (channel !== this.channelName || !message) { - return + return; } if (message.event === 'start-sync') { - this.startSyncing() + this.startSyncing(); } else if (message.event === 'connection-info') { - this.keysGenerationTimeout && clearTimeout(this.keysGenerationTimeout) - this.disconnectWebsockets() - this.initWithCipherKeyAndChannelName(message.cipher, message.channel) - this.initWebsockets() + this.keysGenerationTimeout && + clearTimeout(this.keysGenerationTimeout); + this.disconnectWebsockets(); + this.initWithCipherKeyAndChannelName(message.cipher, message.channel); + this.initWebsockets(); } else if (message.event === 'end-sync') { - this.disconnectWebsockets() - this.setState({ syncing: false, completed: true }) + this.disconnectWebsockets(); + this.setState({ syncing: false, completed: true }); } }, - } + }; - this.pubnub.addListener(this.pubnubListener) + this.pubnub.addListener(this.pubnubListener); this.pubnub.subscribe({ channels: [this.channelName], withPresence: false, - }) + }); } disconnectWebsockets() { if (this.pubnub && this.pubnubListener) { - this.pubnub.removeListener(this.pubnubListener) + this.pubnub.removeListener(this.pubnubListener); } } // Calculating a PubNub Message Payload Size. calculatePayloadSize(channel, message) { - return encodeURIComponent(channel + JSON.stringify(message)).length + 100 + return encodeURIComponent(channel + JSON.stringify(message)).length + 100; } chunkString(str, size) { - const numChunks = Math.ceil(str.length / size) - const chunks = new Array(numChunks) - let o = 0 + const numChunks = Math.ceil(str.length / size); + const chunks = new Array(numChunks); + let o = 0; for (let i = 0; i < numChunks; i += 1) { - chunks[i] = str.substr(o, size) - o += size + chunks[i] = str.substr(o, size); + o += size; } - return chunks + return chunks; } notifyError(errorMsg) { @@ -200,28 +201,28 @@ export default class MobileSyncPage extends Component { }, (status, response) => { if (status.error) { - reject(response) + reject(response); } else { - resolve() + resolve(); } }, - ) - }) + ); + }); } async startSyncing() { if (this.syncing) { - return + return; } - this.syncing = true - this.setState({ syncing: true }) + this.syncing = true; + this.setState({ syncing: true }); const { accounts, network, preferences, transactions, - } = await this.props.fetchInfoToSync() + } = await this.props.fetchInfoToSync(); const allDataStr = JSON.stringify({ accounts, @@ -233,19 +234,19 @@ export default class MobileSyncPage extends Component { seed: this.state.seedWords, importedAccounts: this.state.importedAccounts, }, - }) + }); - const chunks = this.chunkString(allDataStr, 17000) - const totalChunks = chunks.length + const chunks = this.chunkString(allDataStr, 17000); + const totalChunks = chunks.length; try { for (let i = 0; i < totalChunks; i++) { - await this.sendMessage(chunks[i], i + 1, totalChunks) + await this.sendMessage(chunks[i], i + 1, totalChunks); } } catch (e) { - this.props.displayWarning('Sync failed :(') - this.setState({ syncing: false }) - this.syncing = false - this.notifyError(e.toString()) + this.props.displayWarning('Sync failed :('); + this.setState({ syncing: false }); + this.syncing = false; + this.notifyError(e.toString()); } } @@ -265,18 +266,18 @@ export default class MobileSyncPage extends Component { }, (status, response) => { if (status.error) { - reject(response) + reject(response); } else { - resolve() + resolve(); } }, - ) - }) + ); + }); } componentWillUnmount() { - this.clearTimeouts() - this.disconnectWebsockets() + this.clearTimeouts(); + this.disconnectWebsockets(); } renderWarning(text) { @@ -286,15 +287,15 @@ export default class MobileSyncPage extends Component {
    {text}
    - ) + ); } renderContent() { - const { syncing, completed, screen } = this.state - const { t } = this.context + const { syncing, completed, screen } = this.state; + const { t } = this.context; if (syncing) { - return + return ; } if (completed) { @@ -310,7 +311,7 @@ export default class MobileSyncPage extends Component { {t('syncWithMobileComplete')} - ) + ); } return screen === PASSWORD_PROMPT_SCREEN ? ( @@ -327,11 +328,11 @@ export default class MobileSyncPage extends Component { {this.renderRevealSeedContent()} - ) + ); } renderPasswordPromptContent() { - const { t } = this.context + const { t } = this.context; return (
    this.handleSubmit(event)}> @@ -356,17 +357,17 @@ export default class MobileSyncPage extends Component {
    {this.state.error}
    )}
    - ) + ); } renderRevealSeedContent() { - const qrImage = qrCode(0, 'M') + const qrImage = qrCode(0, 'M'); qrImage.addData( `metamask-sync:${this.state.channelName}|@|${this.state.cipherKey}`, - ) - qrImage.make() + ); + qrImage.make(); - const { t } = this.context + const { t } = this.context; return (
    - ) + ); } renderFooter() { return this.state.screen === PASSWORD_PROMPT_SCREEN ? this.renderPasswordPromptFooter() - : this.renderRevealSeedFooter() + : this.renderRevealSeedFooter(); } renderPasswordPromptFooter() { - const { t } = this.context - const { password } = this.state + const { t } = this.context; + const { password } = this.state; return (
    @@ -421,11 +422,11 @@ export default class MobileSyncPage extends Component { {t('next')}
    - ) + ); } renderRevealSeedFooter() { - const { t } = this.context + const { t } = this.context; return (
    @@ -438,12 +439,12 @@ export default class MobileSyncPage extends Component { {t('close')}
    - ) + ); } render() { - const { t } = this.context - const { screen } = this.state + const { t } = this.context; + const { screen } = this.state; return (
    @@ -465,6 +466,6 @@ export default class MobileSyncPage extends Component {
    {this.renderContent()}
    {this.renderFooter()}
    - ) + ); } } diff --git a/ui/app/pages/mobile-sync/mobile-sync.container.js b/ui/app/pages/mobile-sync/mobile-sync.container.js index 440b16e89..1172a97dc 100644 --- a/ui/app/pages/mobile-sync/mobile-sync.container.js +++ b/ui/app/pages/mobile-sync/mobile-sync.container.js @@ -1,13 +1,13 @@ -import { connect } from 'react-redux' +import { connect } from 'react-redux'; import { displayWarning, requestRevealSeedWords, fetchInfoToSync, exportAccounts, -} from '../../store/actions' -import { getMostRecentOverviewPage } from '../../ducks/history/history' -import { getMetaMaskKeyrings } from '../../selectors' -import MobileSyncPage from './mobile-sync.component' +} from '../../store/actions'; +import { getMostRecentOverviewPage } from '../../ducks/history/history'; +import { getMetaMaskKeyrings } from '../../selectors'; +import MobileSyncPage from './mobile-sync.component'; const mapDispatchToProps = (dispatch) => { return { @@ -17,19 +17,19 @@ const mapDispatchToProps = (dispatch) => { displayWarning: (message) => dispatch(displayWarning(message || null)), exportAccounts: (password, addresses) => dispatch(exportAccounts(password, addresses)), - } -} + }; +}; const mapStateToProps = (state) => { const { metamask: { selectedAddress }, - } = state + } = state; return { mostRecentOverviewPage: getMostRecentOverviewPage(state), selectedAddress, keyrings: getMetaMaskKeyrings(state), - } -} + }; +}; -export default connect(mapStateToProps, mapDispatchToProps)(MobileSyncPage) +export default connect(mapStateToProps, mapDispatchToProps)(MobileSyncPage); diff --git a/ui/app/pages/permissions-connect/choose-account/choose-account.component.js b/ui/app/pages/permissions-connect/choose-account/choose-account.component.js index fe1d67d7f..8e245e62e 100644 --- a/ui/app/pages/permissions-connect/choose-account/choose-account.component.js +++ b/ui/app/pages/permissions-connect/choose-account/choose-account.component.js @@ -1,18 +1,18 @@ -import PropTypes from 'prop-types' -import React, { Component } from 'react' -import classnames from 'classnames' -import Identicon from '../../../components/ui/identicon' -import Button from '../../../components/ui/button' +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import classnames from 'classnames'; +import Identicon from '../../../components/ui/identicon'; +import Button from '../../../components/ui/button'; import CheckBox, { CHECKED, INDETERMINATE, UNCHECKED, -} from '../../../components/ui/check-box' -import Tooltip from '../../../components/ui/tooltip' -import { PRIMARY } from '../../../helpers/constants/common' -import UserPreferencedCurrencyDisplay from '../../../components/app/user-preferenced-currency-display' -import PermissionsConnectHeader from '../../../components/app/permissions-connect-header' -import PermissionsConnectFooter from '../../../components/app/permissions-connect-footer' +} from '../../../components/ui/check-box'; +import Tooltip from '../../../components/ui/tooltip'; +import { PRIMARY } from '../../../helpers/constants/common'; +import UserPreferencedCurrencyDisplay from '../../../components/app/user-preferenced-currency-display'; +import PermissionsConnectHeader from '../../../components/app/permissions-connect-header'; +import PermissionsConnectFooter from '../../../components/app/permissions-connect-footer'; export default class ChooseAccount extends Component { static propTypes = { @@ -38,62 +38,62 @@ export default class ChooseAccount extends Component { name: PropTypes.string.isRequired, origin: PropTypes.string.isRequired, }), - } + }; state = { selectedAccounts: this.props.selectedAccountAddresses, - } + }; static defaultProps = { addressLastConnectedMap: {}, - } + }; static contextTypes = { t: PropTypes.func, - } + }; handleAccountClick(address) { - const { selectedAccounts } = this.state + const { selectedAccounts } = this.state; - const newSelectedAccounts = new Set(selectedAccounts) + const newSelectedAccounts = new Set(selectedAccounts); if (newSelectedAccounts.has(address)) { - newSelectedAccounts.delete(address) + newSelectedAccounts.delete(address); } else { - newSelectedAccounts.add(address) + newSelectedAccounts.add(address); } - this.setState({ selectedAccounts: newSelectedAccounts }) + this.setState({ selectedAccounts: newSelectedAccounts }); } selectAll() { - const { accounts } = this.props + const { accounts } = this.props; const newSelectedAccounts = new Set( accounts.map((account) => account.address), - ) + ); - this.setState({ selectedAccounts: newSelectedAccounts }) + this.setState({ selectedAccounts: newSelectedAccounts }); } deselectAll() { - this.setState({ selectedAccounts: new Set() }) + this.setState({ selectedAccounts: new Set() }); } allAreSelected() { - const { accounts } = this.props - const { selectedAccounts } = this.state + const { accounts } = this.props; + const { selectedAccounts } = this.state; - return accounts.every(({ address }) => selectedAccounts.has(address)) + return accounts.every(({ address }) => selectedAccounts.has(address)); } renderAccountsList = () => { - const { accounts, nativeCurrency, addressLastConnectedMap } = this.props - const { selectedAccounts } = this.state + const { accounts, nativeCurrency, addressLastConnectedMap } = this.props; + const { selectedAccounts } = this.state; return (
    {accounts.map((account, index) => { - const { address, addressLabel, balance } = account + const { address, addressLabel, balance } = account; return (
    ) : null}
    - ) + ); })}
    - ) - } + ); + }; renderAccountsListHeader() { - const { t } = this.context - const { selectNewAccountViaModal, accounts } = this.props - const { selectedAccounts } = this.state + const { t } = this.context; + const { selectNewAccountViaModal, accounts } = this.props; + const { selectedAccounts } = this.state; - let checked + let checked; if (this.allAreSelected()) { - checked = CHECKED + checked = CHECKED; } else if (selectedAccounts.size === 0) { - checked = UNCHECKED + checked = UNCHECKED; } else { - checked = INDETERMINATE + checked = INDETERMINATE; } return ( @@ -191,7 +191,7 @@ export default class ChooseAccount extends Component { {this.context.t('newAccount')} - ) + ); } render() { @@ -201,9 +201,9 @@ export default class ChooseAccount extends Component { cancelPermissionsRequest, targetDomainMetadata, accounts, - } = this.props - const { selectedAccounts } = this.state - const { t } = this.context + } = this.props; + const { selectedAccounts } = this.state; + const { t } = this.context; return (
    - ) + ); } } diff --git a/ui/app/pages/permissions-connect/choose-account/index.js b/ui/app/pages/permissions-connect/choose-account/index.js index 10b4cd224..3b25d36c7 100644 --- a/ui/app/pages/permissions-connect/choose-account/index.js +++ b/ui/app/pages/permissions-connect/choose-account/index.js @@ -1 +1 @@ -export { default } from './choose-account.component' +export { default } from './choose-account.component'; diff --git a/ui/app/pages/permissions-connect/index.js b/ui/app/pages/permissions-connect/index.js index 06798a2f6..263242e1a 100644 --- a/ui/app/pages/permissions-connect/index.js +++ b/ui/app/pages/permissions-connect/index.js @@ -1 +1 @@ -export { default } from './permissions-connect.container' +export { default } from './permissions-connect.container'; diff --git a/ui/app/pages/permissions-connect/permissions-connect.component.js b/ui/app/pages/permissions-connect/permissions-connect.component.js index 06a4f136c..1927af9ae 100644 --- a/ui/app/pages/permissions-connect/permissions-connect.component.js +++ b/ui/app/pages/permissions-connect/permissions-connect.component.js @@ -1,14 +1,14 @@ -import PropTypes from 'prop-types' -import React, { Component } from 'react' -import { Switch, Route } from 'react-router-dom' -import { getEnvironmentType } from '../../../../app/scripts/lib/util' -import { ENVIRONMENT_TYPE_NOTIFICATION } from '../../../../shared/constants/app' -import { DEFAULT_ROUTE } from '../../helpers/constants/routes' -import PermissionPageContainer from '../../components/app/permission-page-container' -import ChooseAccount from './choose-account' -import PermissionsRedirect from './redirect' +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { Switch, Route } from 'react-router-dom'; +import { getEnvironmentType } from '../../../../app/scripts/lib/util'; +import { ENVIRONMENT_TYPE_NOTIFICATION } from '../../../../shared/constants/app'; +import { DEFAULT_ROUTE } from '../../helpers/constants/routes'; +import PermissionPageContainer from '../../components/app/permission-page-container'; +import ChooseAccount from './choose-account'; +import PermissionsRedirect from './redirect'; -const APPROVE_TIMEOUT = 1200 +const APPROVE_TIMEOUT = 1200; export default class PermissionConnect extends Component { static propTypes = { @@ -37,18 +37,18 @@ export default class PermissionConnect extends Component { name: PropTypes.string.isRequired, origin: PropTypes.string.isRequired, }), - } + }; static defaultProps = { origin: '', nativeCurrency: '', permissionsRequest: undefined, permissionsRequestId: '', - } + }; static contextTypes = { t: PropTypes.func, - } + }; state = { redirecting: false, @@ -56,23 +56,23 @@ export default class PermissionConnect extends Component { permissionsApproved: null, origin: this.props.origin, targetDomainMetadata: this.props.targetDomainMetadata || {}, - } + }; beforeUnload = () => { - const { permissionsRequestId, rejectPermissionsRequest } = this.props - const { permissionsApproved } = this.state + const { permissionsRequestId, rejectPermissionsRequest } = this.props; + const { permissionsApproved } = this.state; if (permissionsApproved === null && permissionsRequestId) { - rejectPermissionsRequest(permissionsRequestId) + rejectPermissionsRequest(permissionsRequestId); } - } + }; removeBeforeUnload = () => { - const environmentType = getEnvironmentType() + const environmentType = getEnvironmentType(); if (environmentType === ENVIRONMENT_TYPE_NOTIFICATION) { - window.removeEventListener('beforeunload', this.beforeUnload) + window.removeEventListener('beforeunload', this.beforeUnload); } - } + }; componentDidMount() { const { @@ -80,47 +80,47 @@ export default class PermissionConnect extends Component { getRequestAccountTabIds, permissionsRequest, history, - } = this.props - getCurrentWindowTab() - getRequestAccountTabIds() + } = this.props; + getCurrentWindowTab(); + getRequestAccountTabIds(); if (!permissionsRequest) { - history.push(DEFAULT_ROUTE) - return + history.push(DEFAULT_ROUTE); + return; } - const environmentType = getEnvironmentType() + const environmentType = getEnvironmentType(); if (environmentType === ENVIRONMENT_TYPE_NOTIFICATION) { - window.addEventListener('beforeunload', this.beforeUnload) + window.addEventListener('beforeunload', this.beforeUnload); } } static getDerivedStateFromProps(props, state) { - const { permissionsRequest, targetDomainMetadata } = props - const { targetDomainMetadata: savedMetadata } = state + const { permissionsRequest, targetDomainMetadata } = props; + const { targetDomainMetadata: savedMetadata } = state; if ( permissionsRequest && savedMetadata.origin !== targetDomainMetadata?.origin ) { - return { targetDomainMetadata } + return { targetDomainMetadata }; } - return null + return null; } componentDidUpdate(prevProps) { - const { permissionsRequest, lastConnectedInfo } = this.props - const { redirecting, origin } = this.state + const { permissionsRequest, lastConnectedInfo } = this.props; + const { redirecting, origin } = this.state; if (!permissionsRequest && prevProps.permissionsRequest && !redirecting) { const accountsLastApprovedTime = - lastConnectedInfo[origin]?.lastApproved || 0 + lastConnectedInfo[origin]?.lastApproved || 0; const initialAccountsLastApprovedTime = - prevProps.lastConnectedInfo[origin]?.lastApproved || 0 + prevProps.lastConnectedInfo[origin]?.lastApproved || 0; const approved = - accountsLastApprovedTime > initialAccountsLastApprovedTime - this.redirect(approved) + accountsLastApprovedTime > initialAccountsLastApprovedTime; + this.redirect(approved); } } @@ -130,42 +130,42 @@ export default class PermissionConnect extends Component { selectedAccountAddresses: addresses, }, () => this.props.history.push(this.props.confirmPermissionPath), - ) - } + ); + }; redirect(approved) { - const { history } = this.props + const { history } = this.props; this.setState({ redirecting: true, permissionsApproved: approved, - }) - this.removeBeforeUnload() + }); + this.removeBeforeUnload(); if (approved) { - setTimeout(() => history.push(DEFAULT_ROUTE), APPROVE_TIMEOUT) + setTimeout(() => history.push(DEFAULT_ROUTE), APPROVE_TIMEOUT); } else { - history.push(DEFAULT_ROUTE) + history.push(DEFAULT_ROUTE); } } cancelPermissionsRequest = async (requestId) => { - const { rejectPermissionsRequest } = this.props + const { rejectPermissionsRequest } = this.props; if (requestId) { - await rejectPermissionsRequest(requestId) - this.redirect(false) + await rejectPermissionsRequest(requestId); + this.redirect(false); } - } + }; goBack() { - const { history, connectPath } = this.props - history.push(connectPath) + const { history, connectPath } = this.props; + history.push(connectPath); } renderTopBar() { - const { redirecting } = this.state - const { page } = this.props - const { t } = this.context + const { redirecting } = this.state; + const { page } = this.props; + const { t } = this.context; return redirecting ? null : (
    {page === '2' ? ( @@ -181,7 +181,7 @@ export default class PermissionConnect extends Component { {t('xOfY', [page, '2'])}
    - ) + ); } render() { @@ -196,13 +196,13 @@ export default class PermissionConnect extends Component { permissionsRequestId, connectPath, confirmPermissionPath, - } = this.props + } = this.props; const { selectedAccountAddresses, permissionsApproved, redirecting, targetDomainMetadata, - } = this.state + } = this.state; return (
    @@ -224,7 +224,7 @@ export default class PermissionConnect extends Component { onCreateNewAccount: (address) => handleAccountClick(address), newAccountNumber, - }) + }); }} addressLastConnectedMap={addressLastConnectedMap} cancelPermissionsRequest={(requestId) => @@ -243,8 +243,8 @@ export default class PermissionConnect extends Component { { - approvePermissionsRequest(...args) - this.redirect(true) + approvePermissionsRequest(...args); + this.redirect(true); }} rejectPermissionsRequest={(requestId) => this.cancelPermissionsRequest(requestId) @@ -259,6 +259,6 @@ export default class PermissionConnect extends Component { )}
    - ) + ); } } diff --git a/ui/app/pages/permissions-connect/permissions-connect.container.js b/ui/app/pages/permissions-connect/permissions-connect.container.js index 28e71c359..abf349208 100644 --- a/ui/app/pages/permissions-connect/permissions-connect.container.js +++ b/ui/app/pages/permissions-connect/permissions-connect.container.js @@ -1,5 +1,5 @@ -import { connect } from 'react-redux' -import PropTypes from 'prop-types' +import { connect } from 'react-redux'; +import PropTypes from 'prop-types'; import { getPermissionsRequests, getNativeCurrency, @@ -7,21 +7,21 @@ import { getLastConnectedInfo, getDomainMetadata, getSelectedAddress, -} from '../../selectors' +} from '../../selectors'; -import { formatDate } from '../../helpers/utils/util' +import { formatDate } from '../../helpers/utils/util'; import { approvePermissionsRequest, rejectPermissionsRequest, showModal, getCurrentWindowTab, getRequestAccountTabIds, -} from '../../store/actions' +} from '../../store/actions'; import { CONNECT_ROUTE, CONNECT_CONFIRM_PERMISSIONS_ROUTE, -} from '../../helpers/constants/routes' -import PermissionApproval from './permissions-connect.component' +} from '../../helpers/constants/routes'; +import PermissionApproval from './permissions-connect.component'; const mapStateToProps = (state, ownProps) => { const { @@ -29,56 +29,56 @@ const mapStateToProps = (state, ownProps) => { params: { id: permissionsRequestId }, }, location: { pathname }, - } = ownProps - const permissionsRequests = getPermissionsRequests(state) - const currentAddress = getSelectedAddress(state) + } = ownProps; + const permissionsRequests = getPermissionsRequests(state); + const currentAddress = getSelectedAddress(state); const permissionsRequest = permissionsRequests.find( (req) => req.metadata.id === permissionsRequestId, - ) + ); - const { metadata = {} } = permissionsRequest || {} - const { origin } = metadata - const nativeCurrency = getNativeCurrency(state) + const { metadata = {} } = permissionsRequest || {}; + const { origin } = metadata; + const nativeCurrency = getNativeCurrency(state); - const domainMetadata = getDomainMetadata(state) + const domainMetadata = getDomainMetadata(state); - let targetDomainMetadata = null + let targetDomainMetadata = null; if (origin) { if (domainMetadata[origin]) { - targetDomainMetadata = { ...domainMetadata[origin], origin } + targetDomainMetadata = { ...domainMetadata[origin], origin }; } else { - const targetUrl = new URL(origin) + const targetUrl = new URL(origin); targetDomainMetadata = { host: targetUrl.host, name: targetUrl.hostname, origin, - } + }; } } - const accountsWithLabels = getAccountsWithLabels(state) + const accountsWithLabels = getAccountsWithLabels(state); - const lastConnectedInfo = getLastConnectedInfo(state) || {} - const addressLastConnectedMap = lastConnectedInfo[origin]?.accounts || {} + const lastConnectedInfo = getLastConnectedInfo(state) || {}; + const addressLastConnectedMap = lastConnectedInfo[origin]?.accounts || {}; Object.keys(addressLastConnectedMap).forEach((key) => { addressLastConnectedMap[key] = formatDate( addressLastConnectedMap[key], 'yyyy-MM-dd', - ) - }) + ); + }); - const connectPath = `${CONNECT_ROUTE}/${permissionsRequestId}` - const confirmPermissionPath = `${CONNECT_ROUTE}/${permissionsRequestId}${CONNECT_CONFIRM_PERMISSIONS_ROUTE}` + const connectPath = `${CONNECT_ROUTE}/${permissionsRequestId}`; + const confirmPermissionPath = `${CONNECT_ROUTE}/${permissionsRequestId}${CONNECT_CONFIRM_PERMISSIONS_ROUTE}`; - let page = '' + let page = ''; if (pathname === connectPath) { - page = '1' + page = '1'; } else if (pathname === confirmPermissionPath) { - page = '2' + page = '2'; } else { - throw new Error('Incorrect path for permissions-connect component') + throw new Error('Incorrect path for permissions-connect component'); } return { @@ -95,8 +95,8 @@ const mapStateToProps = (state, ownProps) => { confirmPermissionPath, page, targetDomainMetadata, - } -} + }; +}; const mapDispatchToProps = (dispatch) => { return { @@ -111,17 +111,17 @@ const mapDispatchToProps = (dispatch) => { onCreateNewAccount, newAccountNumber, }), - ) + ); }, getRequestAccountTabIds: () => dispatch(getRequestAccountTabIds()), getCurrentWindowTab: () => dispatch(getCurrentWindowTab()), - } -} + }; +}; const PermissionApprovalContainer = connect( mapStateToProps, mapDispatchToProps, -)(PermissionApproval) +)(PermissionApproval); PermissionApprovalContainer.propTypes = { history: PropTypes.object.isRequired, @@ -130,6 +130,6 @@ PermissionApprovalContainer.propTypes = { id: PropTypes.string, }).isRequired, }).isRequired, -} +}; -export default PermissionApprovalContainer +export default PermissionApprovalContainer; diff --git a/ui/app/pages/permissions-connect/redirect/index.js b/ui/app/pages/permissions-connect/redirect/index.js index eebe75550..d389265e2 100644 --- a/ui/app/pages/permissions-connect/redirect/index.js +++ b/ui/app/pages/permissions-connect/redirect/index.js @@ -1 +1 @@ -export { default } from './permissions-redirect.component' +export { default } from './permissions-redirect.component'; diff --git a/ui/app/pages/permissions-connect/redirect/permissions-redirect.component.js b/ui/app/pages/permissions-connect/redirect/permissions-redirect.component.js index 6f02b550a..701a9dc4a 100644 --- a/ui/app/pages/permissions-connect/redirect/permissions-redirect.component.js +++ b/ui/app/pages/permissions-connect/redirect/permissions-redirect.component.js @@ -1,10 +1,10 @@ -import React, { useContext } from 'react' -import PropTypes from 'prop-types' -import SiteIcon from '../../../components/ui/site-icon' -import { I18nContext } from '../../../contexts/i18n' +import React, { useContext } from 'react'; +import PropTypes from 'prop-types'; +import SiteIcon from '../../../components/ui/site-icon'; +import { I18nContext } from '../../../contexts/i18n'; export default function PermissionsRedirect({ domainMetadata }) { - const t = useContext(I18nContext) + const t = useContext(I18nContext); return (
    @@ -24,7 +24,7 @@ export default function PermissionsRedirect({ domainMetadata }) {
    - ) + ); function renderBrokenLine() { return ( @@ -42,7 +42,7 @@ export default function PermissionsRedirect({ domainMetadata }) { strokeDasharray="8 7" /> - ) + ); } } @@ -54,4 +54,4 @@ PermissionsRedirect.propTypes = { name: PropTypes.string.isRequired, origin: PropTypes.string.isRequired, }), -} +}; diff --git a/ui/app/pages/routes/index.js b/ui/app/pages/routes/index.js index a05c9df1a..f92c2a9c7 100644 --- a/ui/app/pages/routes/index.js +++ b/ui/app/pages/routes/index.js @@ -1 +1 @@ -export { default } from './routes.container' +export { default } from './routes.container'; diff --git a/ui/app/pages/routes/routes.component.js b/ui/app/pages/routes/routes.component.js index 5aaf80124..c563d2b03 100644 --- a/ui/app/pages/routes/routes.component.js +++ b/ui/app/pages/routes/routes.component.js @@ -1,37 +1,37 @@ -import classnames from 'classnames' -import PropTypes from 'prop-types' -import React, { Component } from 'react' -import { matchPath, Route, Switch } from 'react-router-dom' -import IdleTimer from 'react-idle-timer' +import classnames from 'classnames'; +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { matchPath, Route, Switch } from 'react-router-dom'; +import IdleTimer from 'react-idle-timer'; -import FirstTimeFlow from '../first-time-flow' -import SendTransactionScreen from '../send' -import Swaps from '../swaps' -import ConfirmTransaction from '../confirm-transaction' -import Sidebar from '../../components/app/sidebars' -import Home from '../home' -import Settings from '../settings' -import Authenticated from '../../helpers/higher-order-components/authenticated' -import Initialized from '../../helpers/higher-order-components/initialized' -import Lock from '../lock' -import PermissionsConnect from '../permissions-connect' -import RestoreVaultPage from '../keychains/restore-vault' -import RevealSeedConfirmation from '../keychains/reveal-seed' -import MobileSyncPage from '../mobile-sync' -import AddTokenPage from '../add-token' -import ConfirmAddTokenPage from '../confirm-add-token' -import ConfirmAddSuggestedTokenPage from '../confirm-add-suggested-token' -import CreateAccountPage from '../create-account' -import Loading from '../../components/ui/loading-screen' -import LoadingNetwork from '../../components/app/loading-network-screen' -import NetworkDropdown from '../../components/app/dropdowns/network-dropdown' -import AccountMenu from '../../components/app/account-menu' -import { Modal } from '../../components/app/modals' -import Alert from '../../components/ui/alert' -import AppHeader from '../../components/app/app-header' -import UnlockPage from '../unlock-page' -import Alerts from '../../components/app/alerts' -import Asset from '../asset' +import FirstTimeFlow from '../first-time-flow'; +import SendTransactionScreen from '../send'; +import Swaps from '../swaps'; +import ConfirmTransaction from '../confirm-transaction'; +import Sidebar from '../../components/app/sidebars'; +import Home from '../home'; +import Settings from '../settings'; +import Authenticated from '../../helpers/higher-order-components/authenticated'; +import Initialized from '../../helpers/higher-order-components/initialized'; +import Lock from '../lock'; +import PermissionsConnect from '../permissions-connect'; +import RestoreVaultPage from '../keychains/restore-vault'; +import RevealSeedConfirmation from '../keychains/reveal-seed'; +import MobileSyncPage from '../mobile-sync'; +import AddTokenPage from '../add-token'; +import ConfirmAddTokenPage from '../confirm-add-token'; +import ConfirmAddSuggestedTokenPage from '../confirm-add-suggested-token'; +import CreateAccountPage from '../create-account'; +import Loading from '../../components/ui/loading-screen'; +import LoadingNetwork from '../../components/app/loading-network-screen'; +import NetworkDropdown from '../../components/app/dropdowns/network-dropdown'; +import AccountMenu from '../../components/app/account-menu'; +import { Modal } from '../../components/app/modals'; +import Alert from '../../components/ui/alert'; +import AppHeader from '../../components/app/app-header'; +import UnlockPage from '../unlock-page'; +import Alerts from '../../components/app/alerts'; +import Asset from '../asset'; import { ADD_TOKEN_ROUTE, @@ -53,14 +53,14 @@ import { SETTINGS_ROUTE, UNLOCK_ROUTE, BUILD_QUOTE_ROUTE, -} from '../../helpers/constants/routes' +} from '../../helpers/constants/routes'; import { ENVIRONMENT_TYPE_NOTIFICATION, ENVIRONMENT_TYPE_POPUP, -} from '../../../../shared/constants/app' -import { getEnvironmentType } from '../../../../app/scripts/lib/util' -import { TRANSACTION_STATUSES } from '../../../../shared/constants/transaction' +} from '../../../../shared/constants/app'; +import { getEnvironmentType } from '../../../../app/scripts/lib/util'; +import { TRANSACTION_STATUSES } from '../../../../shared/constants/transaction'; export default class Routes extends Component { static propTypes = { @@ -88,29 +88,33 @@ export default class Routes extends Component { autoLockTimeLimit: PropTypes.number, pageChanged: PropTypes.func.isRequired, prepareToLeaveSwaps: PropTypes.func, - } + }; static contextTypes = { t: PropTypes.func, metricsEvent: PropTypes.func, - } + }; UNSAFE_componentWillMount() { - const { currentCurrency, pageChanged, setCurrentCurrencyToUSD } = this.props + const { + currentCurrency, + pageChanged, + setCurrentCurrencyToUSD, + } = this.props; if (!currentCurrency) { - setCurrentCurrencyToUSD() + setCurrentCurrencyToUSD(); } this.props.history.listen((locationObj, action) => { if (action === 'PUSH') { - pageChanged(locationObj.pathname) + pageChanged(locationObj.pathname); } - }) + }); } renderRoutes() { - const { autoLockTimeLimit, setLastActiveTime } = this.props + const { autoLockTimeLimit, setLastActiveTime } = this.props; const routes = ( @@ -162,75 +166,75 @@ export default class Routes extends Component { - ) + ); if (autoLockTimeLimit > 0) { return ( {routes} - ) + ); } - return routes + return routes; } onInitializationUnlockPage() { - const { location } = this.props + const { location } = this.props; return Boolean( matchPath(location.pathname, { path: INITIALIZE_UNLOCK_ROUTE, exact: true, }), - ) + ); } onConfirmPage() { - const { location } = this.props + const { location } = this.props; return Boolean( matchPath(location.pathname, { path: CONFIRM_TRANSACTION_ROUTE, exact: false, }), - ) + ); } onSwapsPage() { - const { location } = this.props + const { location } = this.props; return Boolean( matchPath(location.pathname, { path: SWAPS_ROUTE, exact: false }), - ) + ); } onSwapsBuildQuotePage() { - const { location } = this.props + const { location } = this.props; return Boolean( matchPath(location.pathname, { path: BUILD_QUOTE_ROUTE, exact: false }), - ) + ); } hideAppHeader() { - const { location } = this.props + const { location } = this.props; const isInitializing = Boolean( matchPath(location.pathname, { path: INITIALIZE_ROUTE, exact: false, }), - ) + ); if (isInitializing && !this.onInitializationUnlockPage()) { - return true + return true; } - const windowType = getEnvironmentType() + const windowType = getEnvironmentType(); if (windowType === ENVIRONMENT_TYPE_NOTIFICATION) { - return true + return true; } if (windowType === ENVIRONMENT_TYPE_POPUP && this.onConfirmPage()) { - return true + return true; } const isHandlingPermissionsRequest = Boolean( @@ -238,9 +242,9 @@ export default class Routes extends Component { path: CONNECT_ROUTE, exact: false, }), - ) + ); - return isHandlingPermissionsRequest + return isHandlingPermissionsRequest; } render() { @@ -258,27 +262,27 @@ export default class Routes extends Component { submittedPendingTransactions, isMouseUser, prepareToLeaveSwaps, - } = this.props - const isLoadingNetwork = network === 'loading' + } = this.props; + const isLoadingNetwork = network === 'loading'; const loadMessage = loadingMessage || isLoadingNetwork ? this.getConnectingLabel(loadingMessage) - : null + : null; const { isOpen: sidebarIsOpen, transitionName: sidebarTransitionName, type: sidebarType, props, - } = sidebar - const { transaction: sidebarTransaction } = props || {} + } = sidebar; + const { transaction: sidebarTransaction } = props || {}; const sidebarShouldClose = sidebarTransaction && !sidebarTransaction.status === TRANSACTION_STATUSES.FAILED && !submittedPendingTransactions.find( ({ id }) => id === sidebarTransaction.id, - ) + ); return (
    setMouseUserState(true)} onKeyDown={(e) => { if (e.keyCode === 9) { - setMouseUserState(false) + setMouseUserState(false); } }} > @@ -299,7 +303,7 @@ export default class Routes extends Component { disableNetworkIndicator={this.onSwapsPage()} onClick={async () => { if (this.onSwapsPage()) { - await prepareToLeaveSwaps() + await prepareToLeaveSwaps(); } }} disabled={ @@ -328,59 +332,59 @@ export default class Routes extends Component {
    {isUnlocked ? : null} - ) + ); } toggleMetamaskActive() { if (this.props.isUnlocked) { // currently active: deactivate - this.props.lockMetaMask() + this.props.lockMetaMask(); } else { // currently inactive: redirect to password box - const passwordBox = document.querySelector('input[type=password]') + const passwordBox = document.querySelector('input[type=password]'); if (!passwordBox) { - return + return; } - passwordBox.focus() + passwordBox.focus(); } } getConnectingLabel(loadingMessage) { if (loadingMessage) { - return loadingMessage + return loadingMessage; } - const { provider, providerId } = this.props + const { provider, providerId } = this.props; switch (provider.type) { case 'mainnet': - return this.context.t('connectingToMainnet') + return this.context.t('connectingToMainnet'); case 'ropsten': - return this.context.t('connectingToRopsten') + return this.context.t('connectingToRopsten'); case 'kovan': - return this.context.t('connectingToKovan') + return this.context.t('connectingToKovan'); case 'rinkeby': - return this.context.t('connectingToRinkeby') + return this.context.t('connectingToRinkeby'); case 'goerli': - return this.context.t('connectingToGoerli') + return this.context.t('connectingToGoerli'); default: - return this.context.t('connectingTo', [providerId]) + return this.context.t('connectingTo', [providerId]); } } getNetworkName() { switch (this.props.provider.type) { case 'mainnet': - return this.context.t('mainnet') + return this.context.t('mainnet'); case 'ropsten': - return this.context.t('ropsten') + return this.context.t('ropsten'); case 'kovan': - return this.context.t('kovan') + return this.context.t('kovan'); case 'rinkeby': - return this.context.t('rinkeby') + return this.context.t('rinkeby'); case 'goerli': - return this.context.t('goerli') + return this.context.t('goerli'); default: - return this.context.t('unknownNetwork') + return this.context.t('unknownNetwork'); } } } diff --git a/ui/app/pages/routes/routes.container.js b/ui/app/pages/routes/routes.container.js index 5fc62e815..0145b4803 100644 --- a/ui/app/pages/routes/routes.container.js +++ b/ui/app/pages/routes/routes.container.js @@ -1,32 +1,32 @@ -import { connect } from 'react-redux' -import { withRouter } from 'react-router-dom' -import { compose } from 'redux' +import { connect } from 'react-redux'; +import { withRouter } from 'react-router-dom'; +import { compose } from 'redux'; import { getNetworkIdentifier, getPreferences, submittedPendingTransactionsSelector, -} from '../../selectors' +} from '../../selectors'; import { hideSidebar, lockMetamask, setCurrentCurrency, setLastActiveTime, setMouseUserState, -} from '../../store/actions' -import { pageChanged } from '../../ducks/history/history' -import { prepareToLeaveSwaps } from '../../ducks/swaps/swaps' -import Routes from './routes.component' +} from '../../store/actions'; +import { pageChanged } from '../../ducks/history/history'; +import { prepareToLeaveSwaps } from '../../ducks/swaps/swaps'; +import Routes from './routes.component'; function mapStateToProps(state) { - const { appState } = state + const { appState } = state; const { sidebar, alertOpen, alertMessage, isLoading, loadingMessage, - } = appState - const { autoLockTimeLimit = 0 } = getPreferences(state) + } = appState; + const { autoLockTimeLimit = 0 } = getPreferences(state); return { sidebar, @@ -44,7 +44,7 @@ function mapStateToProps(state) { isMouseUser: state.appState.isMouseUser, providerId: getNetworkIdentifier(state), autoLockTimeLimit, - } + }; } function mapDispatchToProps(dispatch) { @@ -57,10 +57,10 @@ function mapDispatchToProps(dispatch) { setLastActiveTime: () => dispatch(setLastActiveTime()), pageChanged: (path) => dispatch(pageChanged(path)), prepareToLeaveSwaps: () => dispatch(prepareToLeaveSwaps()), - } + }; } export default compose( withRouter, connect(mapStateToProps, mapDispatchToProps), -)(Routes) +)(Routes); diff --git a/ui/app/pages/send/index.js b/ui/app/pages/send/index.js index b5114babc..36fa285d4 100644 --- a/ui/app/pages/send/index.js +++ b/ui/app/pages/send/index.js @@ -1 +1 @@ -export { default } from './send.container' +export { default } from './send.container'; diff --git a/ui/app/pages/send/send-content/add-recipient/add-recipient.component.js b/ui/app/pages/send/send-content/add-recipient/add-recipient.component.js index 1c43d8927..a2126b552 100644 --- a/ui/app/pages/send/send-content/add-recipient/add-recipient.component.js +++ b/ui/app/pages/send/send-content/add-recipient/add-recipient.component.js @@ -1,13 +1,13 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import Fuse from 'fuse.js' -import Identicon from '../../../../components/ui/identicon' -import { isValidAddress } from '../../../../helpers/utils/util' -import Dialog from '../../../../components/ui/dialog' -import ContactList from '../../../../components/app/contact-list' -import RecipientGroup from '../../../../components/app/contact-list/recipient-group/recipient-group.component' -import { ellipsify } from '../../send.utils' -import Button from '../../../../components/ui/button' +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import Fuse from 'fuse.js'; +import Identicon from '../../../../components/ui/identicon'; +import { isValidAddress } from '../../../../helpers/utils/util'; +import Dialog from '../../../../components/ui/dialog'; +import ContactList from '../../../../components/app/contact-list'; +import RecipientGroup from '../../../../components/app/contact-list/recipient-group/recipient-group.component'; +import { ellipsify } from '../../send.utils'; +import Button from '../../../../components/ui/button'; export default class AddRecipient extends Component { static propTypes = { @@ -23,10 +23,10 @@ export default class AddRecipient extends Component { contacts: PropTypes.array, nonContacts: PropTypes.array, setInternalSearch: PropTypes.func, - } + }; constructor(props) { - super(props) + super(props); this.recentFuse = new Fuse(props.nonContacts, { shouldSort: true, threshold: 0.45, @@ -35,7 +35,7 @@ export default class AddRecipient extends Component { maxPatternLength: 32, minMatchCharLength: 1, keys: [{ name: 'address', weight: 0.5 }], - }) + }); this.contactFuse = new Fuse(props.contacts, { shouldSort: true, @@ -48,66 +48,66 @@ export default class AddRecipient extends Component { { name: 'name', weight: 0.5 }, { name: 'address', weight: 0.5 }, ], - }) + }); } static contextTypes = { t: PropTypes.func, metricsEvent: PropTypes.func, - } + }; state = { isShowingTransfer: false, - } + }; selectRecipient = (to, nickname = '') => { - const { updateSendTo, updateGas } = this.props + const { updateSendTo, updateGas } = this.props; - updateSendTo(to, nickname) - updateGas({ to }) - } + updateSendTo(to, nickname); + updateGas({ to }); + }; searchForContacts = () => { - const { query, contacts } = this.props + const { query, contacts } = this.props; - let _contacts = contacts + let _contacts = contacts; if (query) { - this.contactFuse.setCollection(contacts) - _contacts = this.contactFuse.search(query) + this.contactFuse.setCollection(contacts); + _contacts = this.contactFuse.search(query); } - return _contacts - } + return _contacts; + }; searchForRecents = () => { - const { query, nonContacts } = this.props + const { query, nonContacts } = this.props; - let _nonContacts = nonContacts + let _nonContacts = nonContacts; if (query) { - this.recentFuse.setCollection(nonContacts) - _nonContacts = this.recentFuse.search(query) + this.recentFuse.setCollection(nonContacts); + _nonContacts = this.recentFuse.search(query); } - return _nonContacts - } + return _nonContacts; + }; render() { - const { ensResolution, query, addressBookEntryName } = this.props - const { isShowingTransfer } = this.state + const { ensResolution, query, addressBookEntryName } = this.props; + const { isShowingTransfer } = this.state; - let content + let content; if (isValidAddress(query)) { - content = this.renderExplicitAddress(query) + content = this.renderExplicitAddress(query); } else if (ensResolution) { content = this.renderExplicitAddress( ensResolution, addressBookEntryName || query, - ) + ); } else if (isShowingTransfer) { - content = this.renderTransfer() + content = this.renderTransfer(); } return ( @@ -115,7 +115,7 @@ export default class AddRecipient extends Component { {this.renderDialogs()} {content || this.renderMain()} - ) + ); } renderExplicitAddress(address, name) { @@ -137,21 +137,21 @@ export default class AddRecipient extends Component { )} - ) + ); } renderTransfer() { - let { ownedAccounts } = this.props - const { query, setInternalSearch } = this.props - const { t } = this.context - const { isShowingTransfer } = this.state + let { ownedAccounts } = this.props; + const { query, setInternalSearch } = this.props; + const { t } = this.context; + const { isShowingTransfer } = this.state; if (isShowingTransfer && query) { ownedAccounts = ownedAccounts.filter( (item) => item.name.toLowerCase().indexOf(query.toLowerCase()) > -1 || item.address.toLowerCase().indexOf(query.toLowerCase()) > -1, - ) + ); } return ( @@ -160,8 +160,8 @@ export default class AddRecipient extends Component { type="link" className="send__select-recipient-wrapper__list__link" onClick={() => { - setInternalSearch(false) - this.setState({ isShowingTransfer: false }) + setInternalSearch(false); + this.setState({ isShowingTransfer: false }); }} >
    @@ -173,17 +173,17 @@ export default class AddRecipient extends Component { onSelect={this.selectRecipient} />
    - ) + ); } renderMain() { - const { t } = this.context + const { t } = this.context; const { query, ownedAccounts = [], addressBook, setInternalSearch, - } = this.props + } = this.props; return (
    @@ -198,8 +198,8 @@ export default class AddRecipient extends Component { type="link" className="send__select-recipient-wrapper__list__link" onClick={() => { - setInternalSearch(true) - this.setState({ isShowingTransfer: true }) + setInternalSearch(true); + this.setState({ isShowingTransfer: true }); }} > {t('transferBetweenAccounts')} @@ -207,17 +207,17 @@ export default class AddRecipient extends Component { )}
    - ) + ); } renderDialogs() { - const { toError, ensResolutionError, ensResolution } = this.props - const { t } = this.context - const contacts = this.searchForContacts() - const recents = this.searchForRecents() + const { toError, ensResolutionError, ensResolution } = this.props; + const { t } = this.context; + const contacts = this.searchForContacts(); + const recents = this.searchForRecents(); if (contacts.length || recents.length) { - return null + return null; } if (ensResolutionError) { @@ -225,7 +225,7 @@ export default class AddRecipient extends Component { {ensResolutionError} - ) + ); } if (toError && toError !== 'required' && !ensResolution) { @@ -233,9 +233,9 @@ export default class AddRecipient extends Component { {t(toError)} - ) + ); } - return null + return null; } } diff --git a/ui/app/pages/send/send-content/add-recipient/add-recipient.container.js b/ui/app/pages/send/send-content/add-recipient/add-recipient.container.js index c3f141183..2e3ea94fc 100644 --- a/ui/app/pages/send/send-content/add-recipient/add-recipient.container.js +++ b/ui/app/pages/send/send-content/add-recipient/add-recipient.container.js @@ -1,31 +1,31 @@ -import { connect } from 'react-redux' +import { connect } from 'react-redux'; import { getSendEnsResolution, getSendEnsResolutionError, accountsWithSendEtherInfoSelector, getAddressBook, getAddressBookEntry, -} from '../../../../selectors' +} from '../../../../selectors'; -import { updateSendTo } from '../../../../store/actions' -import AddRecipient from './add-recipient.component' +import { updateSendTo } from '../../../../store/actions'; +import AddRecipient from './add-recipient.component'; -export default connect(mapStateToProps, mapDispatchToProps)(AddRecipient) +export default connect(mapStateToProps, mapDispatchToProps)(AddRecipient); function mapStateToProps(state) { - const ensResolution = getSendEnsResolution(state) + const ensResolution = getSendEnsResolution(state); - let addressBookEntryName = '' + let addressBookEntryName = ''; if (ensResolution) { - const addressBookEntry = getAddressBookEntry(state, ensResolution) || {} - addressBookEntryName = addressBookEntry.name + const addressBookEntry = getAddressBookEntry(state, ensResolution) || {}; + addressBookEntryName = addressBookEntry.name; } - const addressBook = getAddressBook(state) + const addressBook = getAddressBook(state); const ownedAccounts = accountsWithSendEtherInfoSelector(state).sort((a, b) => a.name.localeCompare(b.name), - ) + ); return { addressBook, @@ -35,11 +35,11 @@ function mapStateToProps(state) { ensResolutionError: getSendEnsResolutionError(state), nonContacts: addressBook.filter(({ name }) => !name), ownedAccounts, - } + }; } function mapDispatchToProps(dispatch) { return { updateSendTo: (to, nickname) => dispatch(updateSendTo(to, nickname)), - } + }; } diff --git a/ui/app/pages/send/send-content/add-recipient/add-recipient.js b/ui/app/pages/send/send-content/add-recipient/add-recipient.js index 47b64f774..9a423e974 100644 --- a/ui/app/pages/send/send-content/add-recipient/add-recipient.js +++ b/ui/app/pages/send/send-content/add-recipient/add-recipient.js @@ -1,41 +1,41 @@ -import ethUtil from 'ethereumjs-util' -import contractMap from '@metamask/contract-metadata' +import ethUtil from 'ethereumjs-util'; +import contractMap from '@metamask/contract-metadata'; import { REQUIRED_ERROR, INVALID_RECIPIENT_ADDRESS_ERROR, KNOWN_RECIPIENT_ADDRESS_ERROR, INVALID_RECIPIENT_ADDRESS_NOT_ETH_NETWORK_ERROR, -} from '../../send.constants' +} from '../../send.constants'; import { isValidAddress, isEthNetwork, checkExistingAddresses, -} from '../../../../helpers/utils/util' +} from '../../../../helpers/utils/util'; export function getToErrorObject(to, hasHexData = false, network) { - let toError = null + let toError = null; if (!to) { if (!hasHexData) { - toError = REQUIRED_ERROR + toError = REQUIRED_ERROR; } } else if (!isValidAddress(to) && !toError) { toError = isEthNetwork(network) ? INVALID_RECIPIENT_ADDRESS_ERROR - : INVALID_RECIPIENT_ADDRESS_NOT_ETH_NETWORK_ERROR + : INVALID_RECIPIENT_ADDRESS_NOT_ETH_NETWORK_ERROR; } - return { to: toError } + return { to: toError }; } export function getToWarningObject(to, tokens = [], sendToken = null) { - let toWarning = null + let toWarning = null; if ( sendToken && (ethUtil.toChecksumAddress(to) in contractMap || checkExistingAddresses(to, tokens)) ) { - toWarning = KNOWN_RECIPIENT_ADDRESS_ERROR + toWarning = KNOWN_RECIPIENT_ADDRESS_ERROR; } - return { to: toWarning } + return { to: toWarning }; } diff --git a/ui/app/pages/send/send-content/add-recipient/ens-input.component.js b/ui/app/pages/send/send-content/add-recipient/ens-input.component.js index a1d884e79..a0977406e 100644 --- a/ui/app/pages/send/send-content/add-recipient/ens-input.component.js +++ b/ui/app/pages/send/send-content/add-recipient/ens-input.component.js @@ -1,28 +1,28 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import classnames from 'classnames' +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; -import { debounce } from 'lodash' -import copyToClipboard from 'copy-to-clipboard/index' -import ENS from 'ethjs-ens' -import networkMap from 'ethereum-ens-network-map' -import log from 'loglevel' -import { ellipsify } from '../../send.utils' +import { debounce } from 'lodash'; +import copyToClipboard from 'copy-to-clipboard/index'; +import ENS from 'ethjs-ens'; +import networkMap from 'ethereum-ens-network-map'; +import log from 'loglevel'; +import { ellipsify } from '../../send.utils'; import { isValidDomainName, isValidAddress, isValidAddressHead, -} from '../../../../helpers/utils/util' -import { MAINNET_NETWORK_ID } from '../../../../../../shared/constants/network' +} from '../../../../helpers/utils/util'; +import { MAINNET_NETWORK_ID } from '../../../../../../shared/constants/network'; // Local Constants -const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000' -const ZERO_X_ERROR_ADDRESS = '0x' +const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'; +const ZERO_X_ERROR_ADDRESS = '0x'; export default class EnsInput extends Component { static contextTypes = { t: PropTypes.func, - } + }; static propTypes = { className: PropTypes.string, @@ -39,51 +39,51 @@ export default class EnsInput extends Component { contact: PropTypes.object, value: PropTypes.string, internalSearch: PropTypes.bool, - } + }; state = { input: '', toError: null, ensResolution: undefined, - } + }; componentDidMount() { - const { network, internalSearch } = this.props - const networkHasEnsSupport = getNetworkEnsSupport(network) - this.setState({ ensResolution: ZERO_ADDRESS }) + const { network, internalSearch } = this.props; + const networkHasEnsSupport = getNetworkEnsSupport(network); + this.setState({ ensResolution: ZERO_ADDRESS }); if (networkHasEnsSupport && !internalSearch) { - const provider = global.ethereumProvider - this.ens = new ENS({ provider, network }) - this.checkName = debounce(this.lookupEnsName, 200) + const provider = global.ethereumProvider; + this.ens = new ENS({ provider, network }); + this.checkName = debounce(this.lookupEnsName, 200); } } componentDidUpdate(prevProps) { - const { input } = this.state - const { network, value, internalSearch } = this.props + const { input } = this.state; + const { network, value, internalSearch } = this.props; - let newValue + let newValue; // Set the value of our input based on QR code provided by parent - const newProvidedValue = input !== value && prevProps.value !== value + const newProvidedValue = input !== value && prevProps.value !== value; if (newProvidedValue) { - newValue = value + newValue = value; } if (prevProps.network !== network) { - const provider = global.ethereumProvider - this.ens = new ENS({ provider, network }) + const provider = global.ethereumProvider; + this.ens = new ENS({ provider, network }); if (!newProvidedValue) { - newValue = input + newValue = input; } } if (newValue !== undefined) { - this.onChange({ target: { value: newValue } }) + this.onChange({ target: { value: newValue } }); } if (!internalSearch && prevProps.internalSearch) { - this.resetInput() + this.resetInput(); } } @@ -92,28 +92,28 @@ export default class EnsInput extends Component { updateEnsResolution, updateEnsResolutionError, onReset, - } = this.props - this.onChange({ target: { value: '' } }) - onReset() - updateEnsResolution('') - updateEnsResolutionError('') - } + } = this.props; + this.onChange({ target: { value: '' } }); + onReset(); + updateEnsResolution(''); + updateEnsResolutionError(''); + }; lookupEnsName = (ensName) => { - const { network } = this.props - const recipient = ensName.trim() + const { network } = this.props; + const recipient = ensName.trim(); - log.info(`ENS attempting to resolve name: ${recipient}`) + log.info(`ENS attempting to resolve name: ${recipient}`); this.ens .lookup(recipient) .then((address) => { if (address === ZERO_ADDRESS) { - throw new Error(this.context.t('noAddressForName')) + throw new Error(this.context.t('noAddressForName')); } if (address === ZERO_X_ERROR_ADDRESS) { - throw new Error(this.context.t('ensRegistrationError')) + throw new Error(this.context.t('ensRegistrationError')); } - this.props.updateEnsResolution(address) + this.props.updateEnsResolution(address); }) .catch((reason) => { if ( @@ -124,21 +124,21 @@ export default class EnsInput extends Component { network === MAINNET_NETWORK_ID ? this.context.t('noAddressForName') : this.context.t('ensNotFoundOnCurrentNetwork'), - ) + ); } else { - log.error(reason) - this.props.updateEnsResolutionError(reason.message) + log.error(reason); + this.props.updateEnsResolutionError(reason.message); } - }) - } + }); + }; onPaste = (event) => { event.clipboardData.items[0].getAsString((text) => { if (isValidAddress(text)) { - this.props.onPaste(text) + this.props.onPaste(text); } - }) - } + }); + }; onChange = (e) => { const { @@ -148,13 +148,13 @@ export default class EnsInput extends Component { updateEnsResolutionError, onValidAddressTyped, internalSearch, - } = this.props - const input = e.target.value - const networkHasEnsSupport = getNetworkEnsSupport(network) + } = this.props; + const input = e.target.value; + const networkHasEnsSupport = getNetworkEnsSupport(network); - this.setState({ input }, () => onChange(input)) + this.setState({ input }, () => onChange(input)); if (internalSearch) { - return null + return null; } // Empty ENS state if input is empty // maybe scan ENS @@ -164,31 +164,31 @@ export default class EnsInput extends Component { !isValidAddress(input) && !isValidAddressHead(input) ) { - updateEnsResolution('') + updateEnsResolution(''); updateEnsResolutionError( networkHasEnsSupport ? '' : 'Network does not support ENS', - ) - return null + ); + return null; } if (isValidDomainName(input)) { - this.lookupEnsName(input) + this.lookupEnsName(input); } else if (onValidAddressTyped && isValidAddress(input)) { - onValidAddressTyped(input) + onValidAddressTyped(input); } else { - updateEnsResolution('') - updateEnsResolutionError('') + updateEnsResolution(''); + updateEnsResolutionError(''); } - return null - } + return null; + }; render() { - const { t } = this.context - const { className, selectedAddress } = this.props - const { input } = this.state + const { t } = this.context; + const { className, selectedAddress } = this.props; + const { input } = this.state; if (selectedAddress) { - return this.renderSelected() + return this.renderSelected(); } return ( @@ -218,26 +218,26 @@ export default class EnsInput extends Component { })} onClick={() => { if (input) { - this.resetInput() + this.resetInput(); } else { - this.props.scanQrCode() + this.props.scanQrCode(); } }} /> - ) + ); } renderSelected() { - const { t } = this.context + const { t } = this.context; const { className, selectedAddress, selectedName, contact = {}, - } = this.props - const name = contact.name || selectedName + } = this.props; + const name = contact.name || selectedName; return (
    @@ -263,11 +263,11 @@ export default class EnsInput extends Component { />
    - ) + ); } ensIcon(recipient) { - const { hoverText } = this.state + const { hoverText } = this.state; return ( {this.ensIconContents(recipient)} - ) + ); } ensIconContents() { - const { loadingEns, ensFailure, ensResolution, toError } = this.state + const { loadingEns, ensFailure, ensResolution, toError } = this.state; if (toError) { - return null + return null; } if (loadingEns) { @@ -301,11 +301,11 @@ export default class EnsInput extends Component { transform: 'translateY(-6px)', }} /> - ) + ); } if (ensFailure) { - return + return ; } if (ensResolution && ensResolution !== ZERO_ADDRESS) { @@ -314,18 +314,18 @@ export default class EnsInput extends Component { className="fa fa-check-circle fa-lg cursor-pointer" style={{ color: 'green' }} onClick={(event) => { - event.preventDefault() - event.stopPropagation() - copyToClipboard(ensResolution) + event.preventDefault(); + event.stopPropagation(); + copyToClipboard(ensResolution); }} /> - ) + ); } - return null + return null; } } function getNetworkEnsSupport(network) { - return Boolean(networkMap[network]) + return Boolean(networkMap[network]); } diff --git a/ui/app/pages/send/send-content/add-recipient/ens-input.container.js b/ui/app/pages/send/send-content/add-recipient/ens-input.container.js index 712d54ecb..f8ad890bc 100644 --- a/ui/app/pages/send/send-content/add-recipient/ens-input.container.js +++ b/ui/app/pages/send/send-content/add-recipient/ens-input.container.js @@ -1,18 +1,18 @@ -import { connect } from 'react-redux' +import { connect } from 'react-redux'; import { getCurrentNetwork, getSendTo, getSendToNickname, getAddressBookEntry, -} from '../../../../selectors' -import EnsInput from './ens-input.component' +} from '../../../../selectors'; +import EnsInput from './ens-input.component'; export default connect((state) => { - const selectedAddress = getSendTo(state) + const selectedAddress = getSendTo(state); return { network: getCurrentNetwork(state), selectedAddress, selectedName: getSendToNickname(state), contact: getAddressBookEntry(state, selectedAddress), - } -})(EnsInput) + }; +})(EnsInput); diff --git a/ui/app/pages/send/send-content/add-recipient/ens-input.js b/ui/app/pages/send/send-content/add-recipient/ens-input.js index 6833ccd03..16c5c26ab 100644 --- a/ui/app/pages/send/send-content/add-recipient/ens-input.js +++ b/ui/app/pages/send/send-content/add-recipient/ens-input.js @@ -1 +1 @@ -export { default } from './ens-input.container' +export { default } from './ens-input.container'; diff --git a/ui/app/pages/send/send-content/add-recipient/index.js b/ui/app/pages/send/send-content/add-recipient/index.js index d661bd74b..81697dcc5 100644 --- a/ui/app/pages/send/send-content/add-recipient/index.js +++ b/ui/app/pages/send/send-content/add-recipient/index.js @@ -1 +1 @@ -export { default } from './add-recipient.container' +export { default } from './add-recipient.container'; diff --git a/ui/app/pages/send/send-content/add-recipient/tests/add-recipient-component.test.js b/ui/app/pages/send/send-content/add-recipient/tests/add-recipient-component.test.js index fddaf3da7..7736969e9 100644 --- a/ui/app/pages/send/send-content/add-recipient/tests/add-recipient-component.test.js +++ b/ui/app/pages/send/send-content/add-recipient/tests/add-recipient-component.test.js @@ -1,9 +1,9 @@ -import assert from 'assert' -import React from 'react' -import { shallow } from 'enzyme' -import sinon from 'sinon' -import AddRecipient from '../add-recipient.component' -import Dialog from '../../../../../components/ui/dialog' +import assert from 'assert'; +import React from 'react'; +import { shallow } from 'enzyme'; +import sinon from 'sinon'; +import AddRecipient from '../add-recipient.component'; +import Dialog from '../../../../../components/ui/dialog'; const propsMethodSpies = { closeToDropdown: sinon.spy(), @@ -12,11 +12,11 @@ const propsMethodSpies = { updateSendTo: sinon.spy(), updateSendToError: sinon.spy(), updateSendToWarning: sinon.spy(), -} +}; describe('AddRecipient Component', function () { - let wrapper - let instance + let wrapper; + let instance; beforeEach(function () { wrapper = shallow( @@ -53,60 +53,60 @@ describe('AddRecipient Component', function () { ]} />, { context: { t: (str) => `${str}_t` } }, - ) - instance = wrapper.instance() - }) + ); + instance = wrapper.instance(); + }); afterEach(function () { - propsMethodSpies.closeToDropdown.resetHistory() - propsMethodSpies.openToDropdown.resetHistory() - propsMethodSpies.updateSendTo.resetHistory() - propsMethodSpies.updateSendToError.resetHistory() - propsMethodSpies.updateSendToWarning.resetHistory() - propsMethodSpies.updateGas.resetHistory() - }) + propsMethodSpies.closeToDropdown.resetHistory(); + propsMethodSpies.openToDropdown.resetHistory(); + propsMethodSpies.updateSendTo.resetHistory(); + propsMethodSpies.updateSendToError.resetHistory(); + propsMethodSpies.updateSendToWarning.resetHistory(); + propsMethodSpies.updateGas.resetHistory(); + }); describe('selectRecipient', function () { it('should call updateSendTo', function () { - assert.strictEqual(propsMethodSpies.updateSendTo.callCount, 0) - instance.selectRecipient('mockTo2', 'mockNickname') - assert.strictEqual(propsMethodSpies.updateSendTo.callCount, 1) + assert.strictEqual(propsMethodSpies.updateSendTo.callCount, 0); + instance.selectRecipient('mockTo2', 'mockNickname'); + assert.strictEqual(propsMethodSpies.updateSendTo.callCount, 1); assert.deepStrictEqual(propsMethodSpies.updateSendTo.getCall(0).args, [ 'mockTo2', 'mockNickname', - ]) - }) + ]); + }); it('should call updateGas if there is no to error', function () { - assert.strictEqual(propsMethodSpies.updateGas.callCount, 0) - instance.selectRecipient(false) - assert.strictEqual(propsMethodSpies.updateGas.callCount, 1) - }) - }) + assert.strictEqual(propsMethodSpies.updateGas.callCount, 0); + instance.selectRecipient(false); + assert.strictEqual(propsMethodSpies.updateGas.callCount, 1); + }); + }); describe('render', function () { it('should render a component', function () { assert.strictEqual( wrapper.find('.send__select-recipient-wrapper').length, 1, - ) - }) + ); + }); it('should render no content if there are no recents, transfers, and contacts', function () { wrapper.setProps({ ownedAccounts: [], addressBook: [], - }) + }); assert.strictEqual( wrapper.find('.send__select-recipient-wrapper__list__link').length, 0, - ) + ); assert.strictEqual( wrapper.find('.send__select-recipient-wrapper__group').length, 0, - ) - }) + ); + }); it('should render transfer', function () { wrapper.setProps({ @@ -115,20 +115,20 @@ describe('AddRecipient Component', function () { { address: '0x124', name: '124' }, ], addressBook: [{ address: '0x456', name: 'test-name' }], - }) - wrapper.setState({ isShowingTransfer: true }) + }); + wrapper.setState({ isShowingTransfer: true }); const xferLink = wrapper.find( '.send__select-recipient-wrapper__list__link', - ) - assert.strictEqual(xferLink.length, 1) + ); + assert.strictEqual(xferLink.length, 1); - const groups = wrapper.find('RecipientGroup') + const groups = wrapper.find('RecipientGroup'); assert.strictEqual( groups.shallow().find('.send__select-recipient-wrapper__group').length, 1, - ) - }) + ); + }); it('should render ContactList', function () { wrapper.setProps({ @@ -137,12 +137,12 @@ describe('AddRecipient Component', function () { { address: '0x124', name: '124' }, ], addressBook: [{ address: '0x125' }], - }) + }); - const contactList = wrapper.find('ContactList') + const contactList = wrapper.find('ContactList'); - assert.strictEqual(contactList.length, 1) - }) + assert.strictEqual(contactList.length, 1); + }); it('should render contacts', function () { wrapper.setProps({ @@ -151,22 +151,22 @@ describe('AddRecipient Component', function () { { address: '0x126', name: 'alex' }, { address: '0x127', name: 'catherine' }, ], - }) - wrapper.setState({ isShowingTransfer: false }) + }); + wrapper.setState({ isShowingTransfer: false }); const xferLink = wrapper.find( '.send__select-recipient-wrapper__list__link', - ) - assert.strictEqual(xferLink.length, 0) + ); + assert.strictEqual(xferLink.length, 0); - const groups = wrapper.find('ContactList') - assert.strictEqual(groups.length, 1) + const groups = wrapper.find('ContactList'); + assert.strictEqual(groups.length, 1); assert.strictEqual( groups.find('.send__select-recipient-wrapper__group-item').length, 0, - ) - }) + ); + }); it('should render error when query has no results', function () { wrapper.setProps({ @@ -174,14 +174,14 @@ describe('AddRecipient Component', function () { toError: 'bad', contacts: [], nonContacts: [], - }) + }); - const dialog = wrapper.find(Dialog) + const dialog = wrapper.find(Dialog); - assert.strictEqual(dialog.props().type, 'error') - assert.strictEqual(dialog.props().children, 'bad_t') - assert.strictEqual(dialog.length, 1) - }) + assert.strictEqual(dialog.props().type, 'error'); + assert.strictEqual(dialog.props().children, 'bad_t'); + assert.strictEqual(dialog.length, 1); + }); it('should render error when query has ens does not resolve', function () { wrapper.setProps({ @@ -190,26 +190,26 @@ describe('AddRecipient Component', function () { ensResolutionError: 'very bad', contacts: [], nonContacts: [], - }) + }); - const dialog = wrapper.find(Dialog) + const dialog = wrapper.find(Dialog); - assert.strictEqual(dialog.props().type, 'error') - assert.strictEqual(dialog.props().children, 'very bad') - assert.strictEqual(dialog.length, 1) - }) + assert.strictEqual(dialog.props().type, 'error'); + assert.strictEqual(dialog.props().children, 'very bad'); + assert.strictEqual(dialog.length, 1); + }); it('should not render error when ens resolved', function () { wrapper.setProps({ addressBook: [], toError: 'bad', ensResolution: '0x128', - }) + }); - const dialog = wrapper.find(Dialog) + const dialog = wrapper.find(Dialog); - assert.strictEqual(dialog.length, 0) - }) + assert.strictEqual(dialog.length, 0); + }); it('should not render error when query has results', function () { wrapper.setProps({ @@ -219,11 +219,11 @@ describe('AddRecipient Component', function () { { address: '0x127', name: 'catherine' }, ], toError: 'bad', - }) + }); - const dialog = wrapper.find(Dialog) + const dialog = wrapper.find(Dialog); - assert.strictEqual(dialog.length, 0) - }) - }) -}) + assert.strictEqual(dialog.length, 0); + }); + }); +}); diff --git a/ui/app/pages/send/send-content/add-recipient/tests/add-recipient-container.test.js b/ui/app/pages/send/send-content/add-recipient/tests/add-recipient-container.test.js index f488b2f4e..a7b4abeb8 100644 --- a/ui/app/pages/send/send-content/add-recipient/tests/add-recipient-container.test.js +++ b/ui/app/pages/send/send-content/add-recipient/tests/add-recipient-container.test.js @@ -1,20 +1,20 @@ -import assert from 'assert' -import proxyquire from 'proxyquire' -import sinon from 'sinon' +import assert from 'assert'; +import proxyquire from 'proxyquire'; +import sinon from 'sinon'; -let mapStateToProps -let mapDispatchToProps +let mapStateToProps; +let mapDispatchToProps; const actionSpies = { updateSendTo: sinon.spy(), -} +}; proxyquire('../add-recipient.container.js', { 'react-redux': { connect: (ms, md) => { - mapStateToProps = ms - mapDispatchToProps = md - return () => ({}) + mapStateToProps = ms; + mapDispatchToProps = md; + return () => ({}); }, }, '../../../../selectors': { @@ -28,7 +28,7 @@ proxyquire('../add-recipient.container.js', { ], }, '../../../../store/actions': actionSpies, -}) +}); describe('add-recipient container', function () { describe('mapStateToProps()', function () { @@ -44,24 +44,24 @@ describe('add-recipient container', function () { ], addressBookEntryName: undefined, nonContacts: [], - }) - }) - }) + }); + }); + }); describe('mapDispatchToProps()', function () { describe('updateSendTo()', function () { - const dispatchSpy = sinon.spy() - const mapDispatchToPropsObject = mapDispatchToProps(dispatchSpy) + const dispatchSpy = sinon.spy(); + const mapDispatchToPropsObject = mapDispatchToProps(dispatchSpy); it('should dispatch an action', function () { - mapDispatchToPropsObject.updateSendTo('mockTo', 'mockNickname') - assert(dispatchSpy.calledOnce) - assert(actionSpies.updateSendTo.calledOnce) + mapDispatchToPropsObject.updateSendTo('mockTo', 'mockNickname'); + assert(dispatchSpy.calledOnce); + assert(actionSpies.updateSendTo.calledOnce); assert.deepStrictEqual(actionSpies.updateSendTo.getCall(0).args, [ 'mockTo', 'mockNickname', - ]) - }) - }) - }) -}) + ]); + }); + }); + }); +}); diff --git a/ui/app/pages/send/send-content/add-recipient/tests/add-recipient-utils.test.js b/ui/app/pages/send/send-content/add-recipient/tests/add-recipient-utils.test.js index bfd83cbd7..9d4947107 100644 --- a/ui/app/pages/send/send-content/add-recipient/tests/add-recipient-utils.test.js +++ b/ui/app/pages/send/send-content/add-recipient/tests/add-recipient-utils.test.js @@ -1,52 +1,52 @@ -import assert from 'assert' -import proxyquire from 'proxyquire' -import sinon from 'sinon' +import assert from 'assert'; +import proxyquire from 'proxyquire'; +import sinon from 'sinon'; import { REQUIRED_ERROR, INVALID_RECIPIENT_ADDRESS_ERROR, KNOWN_RECIPIENT_ADDRESS_ERROR, -} from '../../../send.constants' +} from '../../../send.constants'; const stubs = { isValidAddress: sinon .stub() .callsFake((to) => Boolean(to.match(/^[0xabcdef123456798]+$/u))), -} +}; const toRowUtils = proxyquire('../add-recipient.js', { '../../../../helpers/utils/util': { isValidAddress: stubs.isValidAddress, }, -}) -const { getToErrorObject, getToWarningObject } = toRowUtils +}); +const { getToErrorObject, getToWarningObject } = toRowUtils; describe('add-recipient utils', function () { describe('getToErrorObject()', function () { it('should return a required error if "to" is falsy', function () { assert.deepStrictEqual(getToErrorObject(null), { to: REQUIRED_ERROR, - }) - }) + }); + }); it('should return null if "to" is falsy and hexData is truthy', function () { assert.deepStrictEqual(getToErrorObject(null, true), { to: null, - }) - }) + }); + }); it('should return an invalid recipient error if "to" is truthy but invalid', function () { assert.deepStrictEqual(getToErrorObject('mockInvalidTo'), { to: INVALID_RECIPIENT_ADDRESS_ERROR, - }) - }) + }); + }); it('should return null if "to" is truthy and valid', function () { assert.deepStrictEqual(getToErrorObject('0xabc123'), { to: null, - }) - }) - }) + }); + }); + }); describe('getToWarningObject()', function () { it('should return a known address recipient error if "to" is a token address', function () { @@ -57,8 +57,8 @@ describe('add-recipient utils', function () { { to: KNOWN_RECIPIENT_ADDRESS_ERROR, }, - ) - }) + ); + }); it('should null if "to" is a token address but sendToken is falsy', function () { assert.deepStrictEqual( @@ -66,8 +66,8 @@ describe('add-recipient utils', function () { { to: null, }, - ) - }) + ); + }); it('should return a known address recipient error if "to" is part of contract metadata', function () { assert.deepStrictEqual( @@ -79,8 +79,8 @@ describe('add-recipient utils', function () { { to: KNOWN_RECIPIENT_ADDRESS_ERROR, }, - ) - }) + ); + }); it('should null if "to" is part of contract metadata but sendToken is falsy', function () { assert.deepStrictEqual( getToWarningObject( @@ -91,7 +91,7 @@ describe('add-recipient utils', function () { { to: KNOWN_RECIPIENT_ADDRESS_ERROR, }, - ) - }) - }) -}) + ); + }); + }); +}); diff --git a/ui/app/pages/send/send-content/index.js b/ui/app/pages/send/send-content/index.js index 542da4674..c7c4479bb 100644 --- a/ui/app/pages/send/send-content/index.js +++ b/ui/app/pages/send/send-content/index.js @@ -1 +1 @@ -export { default } from './send-content.container' +export { default } from './send-content.container'; diff --git a/ui/app/pages/send/send-content/send-amount-row/amount-max-button/amount-max-button.component.js b/ui/app/pages/send/send-content/send-amount-row/amount-max-button/amount-max-button.component.js index 7fbeb09a1..db520fcdc 100644 --- a/ui/app/pages/send/send-content/send-amount-row/amount-max-button/amount-max-button.component.js +++ b/ui/app/pages/send/send-content/send-amount-row/amount-max-button/amount-max-button.component.js @@ -1,6 +1,6 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import classnames from 'classnames' +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; export default class AmountMaxButton extends Component { static propTypes = { @@ -14,12 +14,12 @@ export default class AmountMaxButton extends Component { setAmountToMax: PropTypes.func, setMaxModeTo: PropTypes.func, tokenBalance: PropTypes.string, - } + }; static contextTypes = { t: PropTypes.func, metricsEvent: PropTypes.func, - } + }; setMaxAmount() { const { @@ -28,19 +28,19 @@ export default class AmountMaxButton extends Component { sendToken, setAmountToMax, tokenBalance, - } = this.props + } = this.props; setAmountToMax({ balance, gasTotal, sendToken, tokenBalance, - }) + }); } onMaxClick = () => { - const { setMaxModeTo, clearMaxAmount, maxModeOn } = this.props - const { metricsEvent } = this.context + const { setMaxModeTo, clearMaxAmount, maxModeOn } = this.props; + const { metricsEvent } = this.context; metricsEvent({ eventOpts: { @@ -48,18 +48,18 @@ export default class AmountMaxButton extends Component { action: 'Edit Screen', name: 'Clicked "Amount Max"', }, - }) + }); if (maxModeOn) { - setMaxModeTo(false) - clearMaxAmount() + setMaxModeTo(false); + clearMaxAmount(); } else { - setMaxModeTo(true) - this.setMaxAmount() + setMaxModeTo(true); + this.setMaxAmount(); } - } + }; render() { - const { maxModeOn, buttonDataLoading, inError } = this.props + const { maxModeOn, buttonDataLoading, inError } = this.props; return (
    - ) + ); } } diff --git a/ui/app/pages/send/send-content/send-amount-row/amount-max-button/amount-max-button.container.js b/ui/app/pages/send/send-content/send-amount-row/amount-max-button/amount-max-button.container.js index 3274734e4..593d3e57a 100644 --- a/ui/app/pages/send/send-content/send-amount-row/amount-max-button/amount-max-button.container.js +++ b/ui/app/pages/send/send-content/send-amount-row/amount-max-button/amount-max-button.container.js @@ -1,4 +1,4 @@ -import { connect } from 'react-redux' +import { connect } from 'react-redux'; import { getGasTotal, getSendToken, @@ -6,13 +6,13 @@ import { getTokenBalance, getSendMaxModeState, getBasicGasEstimateLoadingStatus, -} from '../../../../../selectors' -import { updateSendAmount, setMaxModeTo } from '../../../../../store/actions' -import { updateSendErrors } from '../../../../../ducks/send/send.duck' -import { calcMaxAmount } from './amount-max-button.utils' -import AmountMaxButton from './amount-max-button.component' +} from '../../../../../selectors'; +import { updateSendAmount, setMaxModeTo } from '../../../../../store/actions'; +import { updateSendErrors } from '../../../../../ducks/send/send.duck'; +import { calcMaxAmount } from './amount-max-button.utils'; +import AmountMaxButton from './amount-max-button.component'; -export default connect(mapStateToProps, mapDispatchToProps)(AmountMaxButton) +export default connect(mapStateToProps, mapDispatchToProps)(AmountMaxButton); function mapStateToProps(state) { return { @@ -22,18 +22,18 @@ function mapStateToProps(state) { maxModeOn: getSendMaxModeState(state), sendToken: getSendToken(state), tokenBalance: getTokenBalance(state), - } + }; } function mapDispatchToProps(dispatch) { return { setAmountToMax: (maxAmountDataObject) => { - dispatch(updateSendErrors({ amount: null })) - dispatch(updateSendAmount(calcMaxAmount(maxAmountDataObject))) + dispatch(updateSendErrors({ amount: null })); + dispatch(updateSendAmount(calcMaxAmount(maxAmountDataObject))); }, clearMaxAmount: () => { - dispatch(updateSendAmount('0')) + dispatch(updateSendAmount('0')); }, setMaxModeTo: (bool) => dispatch(setMaxModeTo(bool)), - } + }; } diff --git a/ui/app/pages/send/send-content/send-amount-row/amount-max-button/amount-max-button.utils.js b/ui/app/pages/send/send-content/send-amount-row/amount-max-button/amount-max-button.utils.js index 39045a78e..934e2fd0a 100644 --- a/ui/app/pages/send/send-content/send-amount-row/amount-max-button/amount-max-button.utils.js +++ b/ui/app/pages/send/send-content/send-amount-row/amount-max-button/amount-max-button.utils.js @@ -1,12 +1,12 @@ import { multiplyCurrencies, subtractCurrencies, -} from '../../../../../helpers/utils/conversion-util' -import { addHexPrefix } from '../../../../../../../app/scripts/lib/util' +} from '../../../../../helpers/utils/conversion-util'; +import { addHexPrefix } from '../../../../../../../app/scripts/lib/util'; export function calcMaxAmount({ balance, gasTotal, sendToken, tokenBalance }) { - const { decimals } = sendToken || {} - const multiplier = Math.pow(10, Number(decimals || 0)) + const { decimals } = sendToken || {}; + const multiplier = Math.pow(10, Number(decimals || 0)); return sendToken ? multiplyCurrencies(tokenBalance, multiplier, { @@ -18,5 +18,5 @@ export function calcMaxAmount({ balance, gasTotal, sendToken, tokenBalance }) { toNumericBase: 'hex', aBase: 16, bBase: 16, - }) + }); } diff --git a/ui/app/pages/send/send-content/send-amount-row/amount-max-button/index.js b/ui/app/pages/send/send-content/send-amount-row/amount-max-button/index.js index ee8271494..26d87ffb5 100644 --- a/ui/app/pages/send/send-content/send-amount-row/amount-max-button/index.js +++ b/ui/app/pages/send/send-content/send-amount-row/amount-max-button/index.js @@ -1 +1 @@ -export { default } from './amount-max-button.container' +export { default } from './amount-max-button.container'; diff --git a/ui/app/pages/send/send-content/send-amount-row/amount-max-button/tests/amount-max-button-component.test.js b/ui/app/pages/send/send-content/send-amount-row/amount-max-button/tests/amount-max-button-component.test.js index fb040de64..42d7646a9 100644 --- a/ui/app/pages/send/send-content/send-amount-row/amount-max-button/tests/amount-max-button-component.test.js +++ b/ui/app/pages/send/send-content/send-amount-row/amount-max-button/tests/amount-max-button-component.test.js @@ -1,23 +1,23 @@ -import assert from 'assert' -import React from 'react' -import { shallow } from 'enzyme' -import sinon from 'sinon' -import AmountMaxButton from '../amount-max-button.component' +import assert from 'assert'; +import React from 'react'; +import { shallow } from 'enzyme'; +import sinon from 'sinon'; +import AmountMaxButton from '../amount-max-button.component'; describe('AmountMaxButton Component', function () { - let wrapper - let instance + let wrapper; + let instance; const propsMethodSpies = { setAmountToMax: sinon.spy(), setMaxModeTo: sinon.spy(), - } + }; - const MOCK_EVENT = { preventDefault: () => undefined } + const MOCK_EVENT = { preventDefault: () => undefined }; before(function () { - sinon.spy(AmountMaxButton.prototype, 'setMaxAmount') - }) + sinon.spy(AmountMaxButton.prototype, 'setMaxAmount'); + }); beforeEach(function () { wrapper = shallow( @@ -36,25 +36,25 @@ describe('AmountMaxButton Component', function () { metricsEvent: () => undefined, }, }, - ) - instance = wrapper.instance() - }) + ); + instance = wrapper.instance(); + }); afterEach(function () { - propsMethodSpies.setAmountToMax.resetHistory() - propsMethodSpies.setMaxModeTo.resetHistory() - AmountMaxButton.prototype.setMaxAmount.resetHistory() - }) + propsMethodSpies.setAmountToMax.resetHistory(); + propsMethodSpies.setMaxModeTo.resetHistory(); + AmountMaxButton.prototype.setMaxAmount.resetHistory(); + }); after(function () { - sinon.restore() - }) + sinon.restore(); + }); describe('setMaxAmount', function () { it('should call setAmountToMax with the correct params', function () { - assert.strictEqual(propsMethodSpies.setAmountToMax.callCount, 0) - instance.setMaxAmount() - assert.strictEqual(propsMethodSpies.setAmountToMax.callCount, 1) + assert.strictEqual(propsMethodSpies.setAmountToMax.callCount, 0); + instance.setMaxAmount(); + assert.strictEqual(propsMethodSpies.setAmountToMax.callCount, 1); assert.deepStrictEqual(propsMethodSpies.setAmountToMax.getCall(0).args, [ { balance: 'mockBalance', @@ -62,31 +62,31 @@ describe('AmountMaxButton Component', function () { sendToken: { address: 'mockTokenAddress' }, tokenBalance: 'mockTokenBalance', }, - ]) - }) - }) + ]); + }); + }); describe('render', function () { it('should render an element with a send-v2__amount-max class', function () { - assert(wrapper.exists('.send-v2__amount-max')) - }) + assert(wrapper.exists('.send-v2__amount-max')); + }); it('should call setMaxModeTo and setMaxAmount when the checkbox is checked', function () { - const { onClick } = wrapper.find('.send-v2__amount-max').props() + const { onClick } = wrapper.find('.send-v2__amount-max').props(); - assert.strictEqual(AmountMaxButton.prototype.setMaxAmount.callCount, 0) - assert.strictEqual(propsMethodSpies.setMaxModeTo.callCount, 0) - onClick(MOCK_EVENT) - assert.strictEqual(AmountMaxButton.prototype.setMaxAmount.callCount, 1) - assert.strictEqual(propsMethodSpies.setMaxModeTo.callCount, 1) + assert.strictEqual(AmountMaxButton.prototype.setMaxAmount.callCount, 0); + assert.strictEqual(propsMethodSpies.setMaxModeTo.callCount, 0); + onClick(MOCK_EVENT); + assert.strictEqual(AmountMaxButton.prototype.setMaxAmount.callCount, 1); + assert.strictEqual(propsMethodSpies.setMaxModeTo.callCount, 1); assert.deepStrictEqual(propsMethodSpies.setMaxModeTo.getCall(0).args, [ true, - ]) - }) + ]); + }); it('should render the expected text when maxModeOn is false', function () { - wrapper.setProps({ maxModeOn: false }) - assert.strictEqual(wrapper.find('.send-v2__amount-max').text(), 'max_t') - }) - }) -}) + wrapper.setProps({ maxModeOn: false }); + assert.strictEqual(wrapper.find('.send-v2__amount-max').text(), 'max_t'); + }); + }); +}); diff --git a/ui/app/pages/send/send-content/send-amount-row/amount-max-button/tests/amount-max-button-container.test.js b/ui/app/pages/send/send-content/send-amount-row/amount-max-button/tests/amount-max-button-container.test.js index ba5325a43..c09e32985 100644 --- a/ui/app/pages/send/send-content/send-amount-row/amount-max-button/tests/amount-max-button-container.test.js +++ b/ui/app/pages/send/send-content/send-amount-row/amount-max-button/tests/amount-max-button-container.test.js @@ -1,24 +1,24 @@ -import assert from 'assert' -import proxyquire from 'proxyquire' -import sinon from 'sinon' +import assert from 'assert'; +import proxyquire from 'proxyquire'; +import sinon from 'sinon'; -let mapStateToProps -let mapDispatchToProps +let mapStateToProps; +let mapDispatchToProps; const actionSpies = { setMaxModeTo: sinon.spy(), updateSendAmount: sinon.spy(), -} +}; const duckActionSpies = { updateSendErrors: sinon.spy(), -} +}; proxyquire('../amount-max-button.container.js', { 'react-redux': { connect: (ms, md) => { - mapStateToProps = ms - mapDispatchToProps = md - return () => ({}) + mapStateToProps = ms; + mapDispatchToProps = md; + return () => ({}); }, }, '../../../../../selectors': { @@ -34,7 +34,7 @@ proxyquire('../amount-max-button.container.js', { }, '../../../../../store/actions': actionSpies, '../../../../../ducks/send/send.duck': duckActionSpies, -}) +}); describe('amount-max-button container', function () { describe('mapStateToProps()', function () { @@ -46,44 +46,44 @@ describe('amount-max-button container', function () { maxModeOn: 'mockMaxModeOn:mockState', sendToken: 'mockSendToken:mockState', tokenBalance: 'mockTokenBalance:mockState', - }) - }) - }) + }); + }); + }); describe('mapDispatchToProps()', function () { - let dispatchSpy - let mapDispatchToPropsObject + let dispatchSpy; + let mapDispatchToPropsObject; beforeEach(function () { - dispatchSpy = sinon.spy() - mapDispatchToPropsObject = mapDispatchToProps(dispatchSpy) - }) + dispatchSpy = sinon.spy(); + mapDispatchToPropsObject = mapDispatchToProps(dispatchSpy); + }); describe('setAmountToMax()', function () { it('should dispatch an action', function () { - mapDispatchToPropsObject.setAmountToMax({ val: 11, foo: 'bar' }) - assert(dispatchSpy.calledTwice) - assert(duckActionSpies.updateSendErrors.calledOnce) + mapDispatchToPropsObject.setAmountToMax({ val: 11, foo: 'bar' }); + assert(dispatchSpy.calledTwice); + assert(duckActionSpies.updateSendErrors.calledOnce); assert.deepStrictEqual( duckActionSpies.updateSendErrors.getCall(0).args[0], { amount: null, }, - ) - assert(actionSpies.updateSendAmount.calledOnce) - assert.strictEqual(actionSpies.updateSendAmount.getCall(0).args[0], 12) - }) - }) + ); + assert(actionSpies.updateSendAmount.calledOnce); + assert.strictEqual(actionSpies.updateSendAmount.getCall(0).args[0], 12); + }); + }); describe('setMaxModeTo()', function () { it('should dispatch an action', function () { - mapDispatchToPropsObject.setMaxModeTo('mockVal') - assert(dispatchSpy.calledOnce) + mapDispatchToPropsObject.setMaxModeTo('mockVal'); + assert(dispatchSpy.calledOnce); assert.strictEqual( actionSpies.setMaxModeTo.getCall(0).args[0], 'mockVal', - ) - }) - }) - }) -}) + ); + }); + }); + }); +}); diff --git a/ui/app/pages/send/send-content/send-amount-row/amount-max-button/tests/amount-max-button-utils.test.js b/ui/app/pages/send/send-content/send-amount-row/amount-max-button/tests/amount-max-button-utils.test.js index c99f0449c..e66395188 100644 --- a/ui/app/pages/send/send-content/send-amount-row/amount-max-button/tests/amount-max-button-utils.test.js +++ b/ui/app/pages/send/send-content/send-amount-row/amount-max-button/tests/amount-max-button-utils.test.js @@ -1,5 +1,5 @@ -import assert from 'assert' -import { calcMaxAmount } from '../amount-max-button.utils' +import assert from 'assert'; +import { calcMaxAmount } from '../amount-max-button.utils'; describe('amount-max-button utils', function () { describe('calcMaxAmount()', function () { @@ -11,8 +11,8 @@ describe('amount-max-button utils', function () { sendToken: false, }), 'ffff00', - ) - }) + ); + }); it('should calculate the correct amount when a sendToken is defined', function () { assert.deepStrictEqual( @@ -23,7 +23,7 @@ describe('amount-max-button utils', function () { tokenBalance: '64', }), 'e8d4a51000', - ) - }) - }) -}) + ); + }); + }); +}); diff --git a/ui/app/pages/send/send-content/send-amount-row/index.js b/ui/app/pages/send/send-content/send-amount-row/index.js index abc6852fe..8f8a60ad2 100644 --- a/ui/app/pages/send/send-content/send-amount-row/index.js +++ b/ui/app/pages/send/send-content/send-amount-row/index.js @@ -1 +1 @@ -export { default } from './send-amount-row.container' +export { default } from './send-amount-row.container'; diff --git a/ui/app/pages/send/send-content/send-amount-row/send-amount-row.component.js b/ui/app/pages/send/send-content/send-amount-row/send-amount-row.component.js index 0e03ac2c0..3f3d64e45 100644 --- a/ui/app/pages/send/send-content/send-amount-row/send-amount-row.component.js +++ b/ui/app/pages/send/send-content/send-amount-row/send-amount-row.component.js @@ -1,10 +1,10 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import { debounce } from 'lodash' -import SendRowWrapper from '../send-row-wrapper' -import UserPreferencedCurrencyInput from '../../../../components/app/user-preferenced-currency-input' -import UserPreferencedTokenInput from '../../../../components/app/user-preferenced-token-input' -import AmountMaxButton from './amount-max-button' +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import { debounce } from 'lodash'; +import SendRowWrapper from '../send-row-wrapper'; +import UserPreferencedCurrencyInput from '../../../../components/app/user-preferenced-currency-input'; +import UserPreferencedTokenInput from '../../../../components/app/user-preferenced-token-input'; +import AmountMaxButton from './amount-max-button'; export default class SendAmountRow extends Component { static propTypes = { @@ -22,26 +22,26 @@ export default class SendAmountRow extends Component { updateSendAmountError: PropTypes.func, updateGas: PropTypes.func, maxModeOn: PropTypes.bool, - } + }; static contextTypes = { t: PropTypes.func, - } + }; componentDidUpdate(prevProps) { - const { maxModeOn: prevMaxModeOn, gasTotal: prevGasTotal } = prevProps - const { maxModeOn, amount, gasTotal, sendToken } = this.props + const { maxModeOn: prevMaxModeOn, gasTotal: prevGasTotal } = prevProps; + const { maxModeOn, amount, gasTotal, sendToken } = this.props; if (maxModeOn && sendToken && !prevMaxModeOn) { - this.updateGas(amount) + this.updateGas(amount); } if (prevGasTotal !== gasTotal) { - this.validateAmount(amount) + this.validateAmount(amount); } } - updateGas = debounce(this.updateGas.bind(this), 500) + updateGas = debounce(this.updateGas.bind(this), 500); validateAmount(amount) { const { @@ -53,7 +53,7 @@ export default class SendAmountRow extends Component { tokenBalance, updateGasFeeError, updateSendAmountError, - } = this.props + } = this.props; updateSendAmountError({ amount, @@ -63,7 +63,7 @@ export default class SendAmountRow extends Component { primaryCurrency, sendToken, tokenBalance, - }) + }); if (sendToken) { updateGasFeeError({ @@ -73,33 +73,33 @@ export default class SendAmountRow extends Component { primaryCurrency, sendToken, tokenBalance, - }) + }); } } updateAmount(amount) { - const { updateSendAmount, setMaxModeTo } = this.props + const { updateSendAmount, setMaxModeTo } = this.props; - setMaxModeTo(false) - updateSendAmount(amount) + setMaxModeTo(false); + updateSendAmount(amount); } updateGas(amount) { - const { sendToken, updateGas } = this.props + const { sendToken, updateGas } = this.props; if (sendToken) { - updateGas({ amount }) + updateGas({ amount }); } } handleChange = (newAmount) => { - this.validateAmount(newAmount) - this.updateGas(newAmount) - this.updateAmount(newAmount) - } + this.validateAmount(newAmount); + this.updateGas(newAmount); + this.updateAmount(newAmount); + }; renderInput() { - const { amount, inError, sendToken } = this.props + const { amount, inError, sendToken } = this.props; return sendToken ? ( - ) + ); } render() { - const { gasTotal, inError } = this.props + const { gasTotal, inError } = this.props; return ( } {this.renderInput()} - ) + ); } } diff --git a/ui/app/pages/send/send-content/send-amount-row/send-amount-row.container.js b/ui/app/pages/send/send-content/send-amount-row/send-amount-row.container.js index 3c73c20ca..f2d5b2e06 100644 --- a/ui/app/pages/send/send-content/send-amount-row/send-amount-row.container.js +++ b/ui/app/pages/send/send-content/send-amount-row/send-amount-row.container.js @@ -1,4 +1,4 @@ -import { connect } from 'react-redux' +import { connect } from 'react-redux'; import { getConversionRate, getGasTotal, @@ -9,13 +9,13 @@ import { getTokenBalance, getSendMaxModeState, sendAmountIsInError, -} from '../../../../selectors' -import { getAmountErrorObject, getGasFeeErrorObject } from '../../send.utils' -import { setMaxModeTo, updateSendAmount } from '../../../../store/actions' -import { updateSendErrors } from '../../../../ducks/send/send.duck' -import SendAmountRow from './send-amount-row.component' +} from '../../../../selectors'; +import { getAmountErrorObject, getGasFeeErrorObject } from '../../send.utils'; +import { setMaxModeTo, updateSendAmount } from '../../../../store/actions'; +import { updateSendErrors } from '../../../../ducks/send/send.duck'; +import SendAmountRow from './send-amount-row.component'; -export default connect(mapStateToProps, mapDispatchToProps)(SendAmountRow) +export default connect(mapStateToProps, mapDispatchToProps)(SendAmountRow); function mapStateToProps(state) { return { @@ -28,7 +28,7 @@ function mapStateToProps(state) { sendToken: getSendToken(state), tokenBalance: getTokenBalance(state), maxModeOn: getSendMaxModeState(state), - } + }; } function mapDispatchToProps(dispatch) { @@ -36,10 +36,10 @@ function mapDispatchToProps(dispatch) { setMaxModeTo: (bool) => dispatch(setMaxModeTo(bool)), updateSendAmount: (newAmount) => dispatch(updateSendAmount(newAmount)), updateGasFeeError: (amountDataObject) => { - dispatch(updateSendErrors(getGasFeeErrorObject(amountDataObject))) + dispatch(updateSendErrors(getGasFeeErrorObject(amountDataObject))); }, updateSendAmountError: (amountDataObject) => { - dispatch(updateSendErrors(getAmountErrorObject(amountDataObject))) + dispatch(updateSendErrors(getAmountErrorObject(amountDataObject))); }, - } + }; } diff --git a/ui/app/pages/send/send-content/send-amount-row/tests/send-amount-row-component.test.js b/ui/app/pages/send/send-content/send-amount-row/tests/send-amount-row-component.test.js index 27c4b3bd9..fd7889004 100644 --- a/ui/app/pages/send/send-content/send-amount-row/tests/send-amount-row-component.test.js +++ b/ui/app/pages/send/send-content/send-amount-row/tests/send-amount-row-component.test.js @@ -1,12 +1,12 @@ -import assert from 'assert' -import React from 'react' -import { shallow } from 'enzyme' -import sinon from 'sinon' -import SendAmountRow from '../send-amount-row.component' +import assert from 'assert'; +import React from 'react'; +import { shallow } from 'enzyme'; +import sinon from 'sinon'; +import SendAmountRow from '../send-amount-row.component'; -import SendRowWrapper from '../../send-row-wrapper/send-row-wrapper.component' -import AmountMaxButton from '../amount-max-button/amount-max-button.container' -import UserPreferencedTokenInput from '../../../../../components/app/user-preferenced-token-input' +import SendRowWrapper from '../../send-row-wrapper/send-row-wrapper.component'; +import AmountMaxButton from '../amount-max-button/amount-max-button.container'; +import UserPreferencedTokenInput from '../../../../../components/app/user-preferenced-token-input'; describe('SendAmountRow Component', function () { describe('validateAmount', function () { @@ -14,11 +14,11 @@ describe('SendAmountRow Component', function () { const { instance, propsMethodSpies: { updateSendAmountError }, - } = shallowRenderSendAmountRow() + } = shallowRenderSendAmountRow(); - assert.strictEqual(updateSendAmountError.callCount, 0) + assert.strictEqual(updateSendAmountError.callCount, 0); - instance.validateAmount('someAmount') + instance.validateAmount('someAmount'); assert.ok( updateSendAmountError.calledOnceWithExactly({ @@ -30,18 +30,18 @@ describe('SendAmountRow Component', function () { sendToken: { address: 'mockTokenAddress' }, tokenBalance: 'mockTokenBalance', }), - ) - }) + ); + }); it('should call updateGasFeeError if sendToken is truthy', function () { const { instance, propsMethodSpies: { updateGasFeeError }, - } = shallowRenderSendAmountRow() + } = shallowRenderSendAmountRow(); - assert.strictEqual(updateGasFeeError.callCount, 0) + assert.strictEqual(updateGasFeeError.callCount, 0); - instance.validateAmount('someAmount') + instance.validateAmount('someAmount'); assert.ok( updateGasFeeError.calledOnceWithExactly({ @@ -52,116 +52,116 @@ describe('SendAmountRow Component', function () { sendToken: { address: 'mockTokenAddress' }, tokenBalance: 'mockTokenBalance', }), - ) - }) + ); + }); it('should call not updateGasFeeError if sendToken is falsey', function () { const { wrapper, instance, propsMethodSpies: { updateGasFeeError }, - } = shallowRenderSendAmountRow() + } = shallowRenderSendAmountRow(); - wrapper.setProps({ sendToken: null }) + wrapper.setProps({ sendToken: null }); - assert.strictEqual(updateGasFeeError.callCount, 0) + assert.strictEqual(updateGasFeeError.callCount, 0); - instance.validateAmount('someAmount') + instance.validateAmount('someAmount'); - assert.strictEqual(updateGasFeeError.callCount, 0) - }) - }) + assert.strictEqual(updateGasFeeError.callCount, 0); + }); + }); describe('updateAmount', function () { it('should call setMaxModeTo', function () { const { instance, propsMethodSpies: { setMaxModeTo }, - } = shallowRenderSendAmountRow() + } = shallowRenderSendAmountRow(); - assert.strictEqual(setMaxModeTo.callCount, 0) + assert.strictEqual(setMaxModeTo.callCount, 0); - instance.updateAmount('someAmount') + instance.updateAmount('someAmount'); - assert.ok(setMaxModeTo.calledOnceWithExactly(false)) - }) + assert.ok(setMaxModeTo.calledOnceWithExactly(false)); + }); it('should call updateSendAmount', function () { const { instance, propsMethodSpies: { updateSendAmount }, - } = shallowRenderSendAmountRow() + } = shallowRenderSendAmountRow(); - assert.strictEqual(updateSendAmount.callCount, 0) + assert.strictEqual(updateSendAmount.callCount, 0); - instance.updateAmount('someAmount') + instance.updateAmount('someAmount'); - assert.ok(updateSendAmount.calledOnceWithExactly('someAmount')) - }) - }) + assert.ok(updateSendAmount.calledOnceWithExactly('someAmount')); + }); + }); describe('render', function () { it('should render a SendRowWrapper component', function () { - const { wrapper } = shallowRenderSendAmountRow() + const { wrapper } = shallowRenderSendAmountRow(); - assert.strictEqual(wrapper.find(SendRowWrapper).length, 1) - }) + assert.strictEqual(wrapper.find(SendRowWrapper).length, 1); + }); it('should pass the correct props to SendRowWrapper', function () { - const { wrapper } = shallowRenderSendAmountRow() + const { wrapper } = shallowRenderSendAmountRow(); const { errorType, label, showError } = wrapper .find(SendRowWrapper) - .props() + .props(); - assert.strictEqual(errorType, 'amount') - assert.strictEqual(label, 'amount_t:') - assert.strictEqual(showError, false) - }) + assert.strictEqual(errorType, 'amount'); + assert.strictEqual(label, 'amount_t:'); + assert.strictEqual(showError, false); + }); it('should render an AmountMaxButton as the first child of the SendRowWrapper', function () { - const { wrapper } = shallowRenderSendAmountRow() + const { wrapper } = shallowRenderSendAmountRow(); - assert(wrapper.find(SendRowWrapper).childAt(0).is(AmountMaxButton)) - }) + assert(wrapper.find(SendRowWrapper).childAt(0).is(AmountMaxButton)); + }); it('should render a UserPreferencedTokenInput as the second child of the SendRowWrapper', function () { - const { wrapper } = shallowRenderSendAmountRow() + const { wrapper } = shallowRenderSendAmountRow(); assert( wrapper.find(SendRowWrapper).childAt(1).is(UserPreferencedTokenInput), - ) - }) + ); + }); it('should render the UserPreferencedTokenInput with the correct props', function () { const { wrapper, instanceSpies: { updateGas, updateAmount, validateAmount }, - } = shallowRenderSendAmountRow() + } = shallowRenderSendAmountRow(); const { onChange, error, value } = wrapper .find(SendRowWrapper) .childAt(1) - .props() + .props(); - assert.strictEqual(error, false) - assert.strictEqual(value, 'mockAmount') - assert.strictEqual(updateGas.callCount, 0) - assert.strictEqual(updateAmount.callCount, 0) - assert.strictEqual(validateAmount.callCount, 0) + assert.strictEqual(error, false); + assert.strictEqual(value, 'mockAmount'); + assert.strictEqual(updateGas.callCount, 0); + assert.strictEqual(updateAmount.callCount, 0); + assert.strictEqual(validateAmount.callCount, 0); - onChange('mockNewAmount') + onChange('mockNewAmount'); - assert.ok(updateGas.calledOnceWithExactly('mockNewAmount')) - assert.ok(updateAmount.calledOnceWithExactly('mockNewAmount')) - assert.ok(validateAmount.calledOnceWithExactly('mockNewAmount')) - }) - }) -}) + assert.ok(updateGas.calledOnceWithExactly('mockNewAmount')); + assert.ok(updateAmount.calledOnceWithExactly('mockNewAmount')); + assert.ok(validateAmount.calledOnceWithExactly('mockNewAmount')); + }); + }); +}); function shallowRenderSendAmountRow() { - const setMaxModeTo = sinon.spy() - const updateGasFeeError = sinon.spy() - const updateSendAmount = sinon.spy() - const updateSendAmountError = sinon.spy() + const setMaxModeTo = sinon.spy(); + const updateGasFeeError = sinon.spy(); + const updateSendAmount = sinon.spy(); + const updateSendAmountError = sinon.spy(); const wrapper = shallow( undefined} />, { context: { t: (str) => `${str}_t` } }, - ) - const instance = wrapper.instance() - const updateAmount = sinon.spy(instance, 'updateAmount') - const updateGas = sinon.spy(instance, 'updateGas') - const validateAmount = sinon.spy(instance, 'validateAmount') + ); + const instance = wrapper.instance(); + const updateAmount = sinon.spy(instance, 'updateAmount'); + const updateGas = sinon.spy(instance, 'updateGas'); + const validateAmount = sinon.spy(instance, 'validateAmount'); return { instance, @@ -200,5 +200,5 @@ function shallowRenderSendAmountRow() { updateGas, validateAmount, }, - } + }; } diff --git a/ui/app/pages/send/send-content/send-amount-row/tests/send-amount-row-container.test.js b/ui/app/pages/send/send-content/send-amount-row/tests/send-amount-row-container.test.js index 3137ef1b4..5e29554ba 100644 --- a/ui/app/pages/send/send-content/send-amount-row/tests/send-amount-row-container.test.js +++ b/ui/app/pages/send/send-content/send-amount-row/tests/send-amount-row-container.test.js @@ -1,22 +1,22 @@ -import assert from 'assert' -import proxyquire from 'proxyquire' -import sinon from 'sinon' +import assert from 'assert'; +import proxyquire from 'proxyquire'; +import sinon from 'sinon'; -let mapDispatchToProps +let mapDispatchToProps; const actionSpies = { setMaxModeTo: sinon.spy(), updateSendAmount: sinon.spy(), -} +}; const duckActionSpies = { updateSendErrors: sinon.spy(), -} +}; proxyquire('../send-amount-row.container.js', { 'react-redux': { connect: (_, md) => { - mapDispatchToProps = md - return () => ({}) + mapDispatchToProps = md; + return () => ({}); }, }, '../../../../selectors': { sendAmountIsInError: (s) => `mockInError:${s}` }, @@ -32,71 +32,71 @@ proxyquire('../send-amount-row.container.js', { }, '../../../../store/actions': actionSpies, '../../../../ducks/send/send.duck': duckActionSpies, -}) +}); describe('send-amount-row container', function () { describe('mapDispatchToProps()', function () { - let dispatchSpy - let mapDispatchToPropsObject + let dispatchSpy; + let mapDispatchToPropsObject; beforeEach(function () { - dispatchSpy = sinon.spy() - mapDispatchToPropsObject = mapDispatchToProps(dispatchSpy) - duckActionSpies.updateSendErrors.resetHistory() - }) + dispatchSpy = sinon.spy(); + mapDispatchToPropsObject = mapDispatchToProps(dispatchSpy); + duckActionSpies.updateSendErrors.resetHistory(); + }); describe('setMaxModeTo()', function () { it('should dispatch an action', function () { - mapDispatchToPropsObject.setMaxModeTo('mockBool') - assert(dispatchSpy.calledOnce) - assert(actionSpies.setMaxModeTo.calledOnce) + mapDispatchToPropsObject.setMaxModeTo('mockBool'); + assert(dispatchSpy.calledOnce); + assert(actionSpies.setMaxModeTo.calledOnce); assert.strictEqual( actionSpies.setMaxModeTo.getCall(0).args[0], 'mockBool', - ) - }) - }) + ); + }); + }); describe('updateSendAmount()', function () { it('should dispatch an action', function () { - mapDispatchToPropsObject.updateSendAmount('mockAmount') - assert(dispatchSpy.calledOnce) - assert(actionSpies.updateSendAmount.calledOnce) + mapDispatchToPropsObject.updateSendAmount('mockAmount'); + assert(dispatchSpy.calledOnce); + assert(actionSpies.updateSendAmount.calledOnce); assert.strictEqual( actionSpies.updateSendAmount.getCall(0).args[0], 'mockAmount', - ) - }) - }) + ); + }); + }); describe('updateGasFeeError()', function () { it('should dispatch an action', function () { - mapDispatchToPropsObject.updateGasFeeError({ some: 'data' }) - assert(dispatchSpy.calledOnce) - assert(duckActionSpies.updateSendErrors.calledOnce) + mapDispatchToPropsObject.updateGasFeeError({ some: 'data' }); + assert(dispatchSpy.calledOnce); + assert(duckActionSpies.updateSendErrors.calledOnce); assert.deepStrictEqual( duckActionSpies.updateSendErrors.getCall(0).args[0], { some: 'data', mockGasFeeErrorChange: true, }, - ) - }) - }) + ); + }); + }); describe('updateSendAmountError()', function () { it('should dispatch an action', function () { - mapDispatchToPropsObject.updateSendAmountError({ some: 'data' }) - assert(dispatchSpy.calledOnce) - assert(duckActionSpies.updateSendErrors.calledOnce) + mapDispatchToPropsObject.updateSendAmountError({ some: 'data' }); + assert(dispatchSpy.calledOnce); + assert(duckActionSpies.updateSendErrors.calledOnce); assert.deepStrictEqual( duckActionSpies.updateSendErrors.getCall(0).args[0], { some: 'data', mockChange: true, }, - ) - }) - }) - }) -}) + ); + }); + }); + }); +}); diff --git a/ui/app/pages/send/send-content/send-asset-row/index.js b/ui/app/pages/send/send-content/send-asset-row/index.js index ba424a083..0d1d45892 100644 --- a/ui/app/pages/send/send-content/send-asset-row/index.js +++ b/ui/app/pages/send/send-content/send-asset-row/index.js @@ -1 +1 @@ -export { default } from './send-asset-row.container' +export { default } from './send-asset-row.container'; diff --git a/ui/app/pages/send/send-content/send-asset-row/send-asset-row.component.js b/ui/app/pages/send/send-content/send-asset-row/send-asset-row.component.js index abd6d1458..870ff79e8 100644 --- a/ui/app/pages/send/send-content/send-asset-row/send-asset-row.component.js +++ b/ui/app/pages/send/send-content/send-asset-row/send-asset-row.component.js @@ -1,10 +1,10 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import SendRowWrapper from '../send-row-wrapper' -import Identicon from '../../../../components/ui/identicon/identicon.component' -import TokenBalance from '../../../../components/ui/token-balance' -import UserPreferencedCurrencyDisplay from '../../../../components/app/user-preferenced-currency-display' -import { PRIMARY } from '../../../../helpers/constants/common' +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import SendRowWrapper from '../send-row-wrapper'; +import Identicon from '../../../../components/ui/identicon/identicon.component'; +import TokenBalance from '../../../../components/ui/token-balance'; +import UserPreferencedCurrencyDisplay from '../../../../components/app/user-preferenced-currency-display'; +import { PRIMARY } from '../../../../helpers/constants/common'; export default class SendAssetRow extends Component { static propTypes = { @@ -19,20 +19,20 @@ export default class SendAssetRow extends Component { selectedAddress: PropTypes.string.isRequired, sendTokenAddress: PropTypes.string, setSendToken: PropTypes.func.isRequired, - } + }; static contextTypes = { t: PropTypes.func, metricsEvent: PropTypes.func, - } + }; state = { isShowingDropdown: false, - } + }; - openDropdown = () => this.setState({ isShowingDropdown: true }) + openDropdown = () => this.setState({ isShowingDropdown: true }); - closeDropdown = () => this.setState({ isShowingDropdown: false }) + closeDropdown = () => this.setState({ isShowingDropdown: false }); selectToken = (token) => { this.setState( @@ -49,14 +49,14 @@ export default class SendAssetRow extends Component { customVariables: { assetSelected: token ? 'ERC20' : 'ETH', }, - }) - this.props.setSendToken(token) + }); + this.props.setSendToken(token); }, - ) - } + ); + }; render() { - const { t } = this.context + const { t } = this.context; return ( @@ -65,14 +65,14 @@ export default class SendAssetRow extends Component { {this.props.tokens.length > 0 ? this.renderAssetDropdown() : null} - ) + ); } renderSendToken() { - const { sendTokenAddress } = this.props + const { sendTokenAddress } = this.props; const token = this.props.tokens.find( ({ address }) => address === sendTokenAddress, - ) + ); return (
    {token ? this.renderAsset(token) : this.renderEth()}
    - ) + ); } renderAssetDropdown() { @@ -97,16 +97,16 @@ export default class SendAssetRow extends Component { ) - ) + ); } renderEth(insideDropdown = false) { - const { t } = this.context - const { accounts, selectedAddress } = this.props + const { t } = this.context; + const { accounts, selectedAddress } = this.props; const balanceValue = accounts[selectedAddress] ? accounts[selectedAddress].balance - : '' + : ''; return (
    )}
    - ) + ); } renderAsset(token, insideDropdown = false) { - const { address, symbol } = token - const { t } = this.context + const { address, symbol } = token; + const { t } = this.context; return (
    )}
    - ) + ); } } diff --git a/ui/app/pages/send/send-content/send-asset-row/send-asset-row.container.js b/ui/app/pages/send/send-content/send-asset-row/send-asset-row.container.js index 1fe7f7bf4..05a2d4a23 100644 --- a/ui/app/pages/send/send-content/send-asset-row/send-asset-row.container.js +++ b/ui/app/pages/send/send-content/send-asset-row/send-asset-row.container.js @@ -1,7 +1,10 @@ -import { connect } from 'react-redux' -import { getMetaMaskAccounts, getSendTokenAddress } from '../../../../selectors' -import { updateSendToken } from '../../../../store/actions' -import SendAssetRow from './send-asset-row.component' +import { connect } from 'react-redux'; +import { + getMetaMaskAccounts, + getSendTokenAddress, +} from '../../../../selectors'; +import { updateSendToken } from '../../../../store/actions'; +import SendAssetRow from './send-asset-row.component'; function mapStateToProps(state) { return { @@ -9,13 +12,13 @@ function mapStateToProps(state) { selectedAddress: state.metamask.selectedAddress, sendTokenAddress: getSendTokenAddress(state), accounts: getMetaMaskAccounts(state), - } + }; } function mapDispatchToProps(dispatch) { return { setSendToken: (token) => dispatch(updateSendToken(token)), - } + }; } -export default connect(mapStateToProps, mapDispatchToProps)(SendAssetRow) +export default connect(mapStateToProps, mapDispatchToProps)(SendAssetRow); diff --git a/ui/app/pages/send/send-content/send-content.component.js b/ui/app/pages/send/send-content/send-content.component.js index 4a4aaad40..2dee77e65 100644 --- a/ui/app/pages/send/send-content/send-content.component.js +++ b/ui/app/pages/send/send-content/send-content.component.js @@ -1,16 +1,16 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import PageContainerContent from '../../../components/ui/page-container/page-container-content.component' -import Dialog from '../../../components/ui/dialog' -import SendAmountRow from './send-amount-row' -import SendGasRow from './send-gas-row' -import SendHexDataRow from './send-hex-data-row' -import SendAssetRow from './send-asset-row' +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import PageContainerContent from '../../../components/ui/page-container/page-container-content.component'; +import Dialog from '../../../components/ui/dialog'; +import SendAmountRow from './send-amount-row'; +import SendGasRow from './send-gas-row'; +import SendHexDataRow from './send-hex-data-row'; +import SendAssetRow from './send-asset-row'; export default class SendContent extends Component { static contextTypes = { t: PropTypes.func, - } + }; static propTypes = { updateGas: PropTypes.func, @@ -19,12 +19,12 @@ export default class SendContent extends Component { contact: PropTypes.object, isOwnedAccount: PropTypes.bool, warning: PropTypes.string, - } + }; - updateGas = (updateData) => this.props.updateGas(updateData) + updateGas = (updateData) => this.props.updateGas(updateData); render() { - const { warning } = this.props + const { warning } = this.props; return (
    @@ -38,19 +38,19 @@ export default class SendContent extends Component { )}
    - ) + ); } maybeRenderAddContact() { - const { t } = this.context + const { t } = this.context; const { isOwnedAccount, showAddToAddressBookModal, contact = {}, - } = this.props + } = this.props; if (isOwnedAccount || contact.name) { - return null + return null; } return ( @@ -61,17 +61,17 @@ export default class SendContent extends Component { > {t('newAccountDetectedDialogMessage')} - ) + ); } renderWarning() { - const { t } = this.context - const { warning } = this.props + const { t } = this.context; + const { warning } = this.props; return ( {t(warning)} - ) + ); } } diff --git a/ui/app/pages/send/send-content/send-content.container.js b/ui/app/pages/send/send-content/send-content.container.js index 6ba44cf0c..42e115b94 100644 --- a/ui/app/pages/send/send-content/send-content.container.js +++ b/ui/app/pages/send/send-content/send-content.container.js @@ -1,16 +1,16 @@ -import { connect } from 'react-redux' +import { connect } from 'react-redux'; import { getSendTo, accountsWithSendEtherInfoSelector, getAddressBookEntry, -} from '../../../selectors' +} from '../../../selectors'; -import * as actions from '../../../store/actions' -import SendContent from './send-content.component' +import * as actions from '../../../store/actions'; +import SendContent from './send-content.component'; function mapStateToProps(state) { - const ownedAccounts = accountsWithSendEtherInfoSelector(state) - const to = getSendTo(state) + const ownedAccounts = accountsWithSendEtherInfoSelector(state); + const to = getSendTo(state); return { isOwnedAccount: Boolean( ownedAccounts.find( @@ -19,7 +19,7 @@ function mapStateToProps(state) { ), contact: getAddressBookEntry(state, to), to, - } + }; } function mapDispatchToProps(dispatch) { @@ -31,21 +31,21 @@ function mapDispatchToProps(dispatch) { recipient, }), ), - } + }; } function mergeProps(stateProps, dispatchProps, ownProps) { - const { to, ...restStateProps } = stateProps + const { to, ...restStateProps } = stateProps; return { ...ownProps, ...restStateProps, showAddToAddressBookModal: () => dispatchProps.showAddToAddressBookModal(to), - } + }; } export default connect( mapStateToProps, mapDispatchToProps, mergeProps, -)(SendContent) +)(SendContent); diff --git a/ui/app/pages/send/send-content/send-gas-row/gas-fee-display/gas-fee-display.component.js b/ui/app/pages/send/send-content/send-gas-row/gas-fee-display/gas-fee-display.component.js index f016b794c..8e61794e6 100644 --- a/ui/app/pages/send/send-content/send-gas-row/gas-fee-display/gas-fee-display.component.js +++ b/ui/app/pages/send/send-content/send-gas-row/gas-fee-display/gas-fee-display.component.js @@ -1,21 +1,21 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import UserPreferencedCurrencyDisplay from '../../../../../components/app/user-preferenced-currency-display' -import { PRIMARY, SECONDARY } from '../../../../../helpers/constants/common' +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import UserPreferencedCurrencyDisplay from '../../../../../components/app/user-preferenced-currency-display'; +import { PRIMARY, SECONDARY } from '../../../../../helpers/constants/common'; export default class GasFeeDisplay extends Component { static propTypes = { gasLoadingError: PropTypes.bool, gasTotal: PropTypes.string, onReset: PropTypes.func, - } + }; static contextTypes = { t: PropTypes.func, - } + }; render() { - const { gasTotal, gasLoadingError, onReset } = this.props + const { gasTotal, gasLoadingError, onReset } = this.props; return (
    @@ -40,6 +40,6 @@ export default class GasFeeDisplay extends Component { {this.context.t('reset')}
    - ) + ); } } diff --git a/ui/app/pages/send/send-content/send-gas-row/gas-fee-display/index.js b/ui/app/pages/send/send-content/send-gas-row/gas-fee-display/index.js index dba0edb7b..e8c5d464f 100644 --- a/ui/app/pages/send/send-content/send-gas-row/gas-fee-display/index.js +++ b/ui/app/pages/send/send-content/send-gas-row/gas-fee-display/index.js @@ -1 +1 @@ -export { default } from './gas-fee-display.component' +export { default } from './gas-fee-display.component'; diff --git a/ui/app/pages/send/send-content/send-gas-row/gas-fee-display/tests/gas-fee-display.component.test.js b/ui/app/pages/send/send-content/send-gas-row/gas-fee-display/tests/gas-fee-display.component.test.js index 817c324ea..15fb6b5a2 100644 --- a/ui/app/pages/send/send-content/send-gas-row/gas-fee-display/tests/gas-fee-display.component.test.js +++ b/ui/app/pages/send/send-content/send-gas-row/gas-fee-display/tests/gas-fee-display.component.test.js @@ -1,17 +1,17 @@ -import assert from 'assert' -import React from 'react' -import { shallow } from 'enzyme' -import sinon from 'sinon' -import GasFeeDisplay from '../gas-fee-display.component' -import UserPreferencedCurrencyDisplay from '../../../../../../components/app/user-preferenced-currency-display' +import assert from 'assert'; +import React from 'react'; +import { shallow } from 'enzyme'; +import sinon from 'sinon'; +import GasFeeDisplay from '../gas-fee-display.component'; +import UserPreferencedCurrencyDisplay from '../../../../../../components/app/user-preferenced-currency-display'; const propsMethodSpies = { showCustomizeGasModal: sinon.spy(), onReset: sinon.spy(), -} +}; describe('GasFeeDisplay Component', function () { - let wrapper + let wrapper; describe('render', function () { beforeEach(function () { @@ -25,36 +25,39 @@ describe('GasFeeDisplay Component', function () { onReset={propsMethodSpies.onReset} />, { context: { t: (str) => `${str}_t` } }, - ) - }) + ); + }); afterEach(function () { - propsMethodSpies.showCustomizeGasModal.resetHistory() - }) + propsMethodSpies.showCustomizeGasModal.resetHistory(); + }); it('should render a CurrencyDisplay component', function () { - assert.strictEqual(wrapper.find(UserPreferencedCurrencyDisplay).length, 2) - }) + assert.strictEqual( + wrapper.find(UserPreferencedCurrencyDisplay).length, + 2, + ); + }); it('should render the CurrencyDisplay with the correct props', function () { const { type, value } = wrapper .find(UserPreferencedCurrencyDisplay) .at(0) - .props() - assert.strictEqual(type, 'PRIMARY') - assert.strictEqual(value, 'mockGasTotal') - }) + .props(); + assert.strictEqual(type, 'PRIMARY'); + assert.strictEqual(value, 'mockGasTotal'); + }); it('should render the reset button with the correct props', function () { - const { onClick, className } = wrapper.find('button').props() - assert.strictEqual(className, 'gas-fee-reset') - assert.strictEqual(propsMethodSpies.onReset.callCount, 0) - onClick() - assert.strictEqual(propsMethodSpies.onReset.callCount, 1) - }) + const { onClick, className } = wrapper.find('button').props(); + assert.strictEqual(className, 'gas-fee-reset'); + assert.strictEqual(propsMethodSpies.onReset.callCount, 0); + onClick(); + assert.strictEqual(propsMethodSpies.onReset.callCount, 1); + }); it('should render the reset button with the correct text', function () { - assert.strictEqual(wrapper.find('button').text(), 'reset_t') - }) - }) -}) + assert.strictEqual(wrapper.find('button').text(), 'reset_t'); + }); + }); +}); diff --git a/ui/app/pages/send/send-content/send-gas-row/index.js b/ui/app/pages/send/send-content/send-gas-row/index.js index 3c7ff1d5f..eb18bf2af 100644 --- a/ui/app/pages/send/send-content/send-gas-row/index.js +++ b/ui/app/pages/send/send-content/send-gas-row/index.js @@ -1 +1 @@ -export { default } from './send-gas-row.container' +export { default } from './send-gas-row.container'; diff --git a/ui/app/pages/send/send-content/send-gas-row/send-gas-row.component.js b/ui/app/pages/send/send-content/send-gas-row/send-gas-row.component.js index 07f7d728a..cf74ee0f3 100644 --- a/ui/app/pages/send/send-content/send-gas-row/send-gas-row.component.js +++ b/ui/app/pages/send/send-content/send-gas-row/send-gas-row.component.js @@ -1,9 +1,9 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import SendRowWrapper from '../send-row-wrapper' -import GasPriceButtonGroup from '../../../../components/app/gas-customization/gas-price-button-group' -import AdvancedGasInputs from '../../../../components/app/gas-customization/advanced-gas-inputs' -import GasFeeDisplay from './gas-fee-display/gas-fee-display.component' +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import SendRowWrapper from '../send-row-wrapper'; +import GasPriceButtonGroup from '../../../../components/app/gas-customization/gas-price-button-group'; +import AdvancedGasInputs from '../../../../components/app/gas-customization/advanced-gas-inputs'; +import GasFeeDisplay from './gas-fee-display/gas-fee-display.component'; export default class SendGasRow extends Component { static propTypes = { @@ -26,19 +26,19 @@ export default class SendGasRow extends Component { gasLimit: PropTypes.string, insufficientBalance: PropTypes.bool, isMainnet: PropTypes.bool, - } + }; static contextTypes = { t: PropTypes.func, metricsEvent: PropTypes.func, - } + }; renderAdvancedOptionsButton() { - const { metricsEvent } = this.context - const { showCustomizeGasModal, isMainnet } = this.props + const { metricsEvent } = this.context; + const { showCustomizeGasModal, isMainnet } = this.props; // Tests should behave in same way as mainnet, but are using Localhost if (!isMainnet && !process.env.IN_TEST) { - return null + return null; } return (
    {this.context.t('advancedOptions')}
    - ) + ); } setMaxAmount() { @@ -66,14 +66,14 @@ export default class SendGasRow extends Component { sendToken, setAmountToMax, tokenBalance, - } = this.props + } = this.props; setAmountToMax({ balance, gasTotal, sendToken, tokenBalance, - }) + }); } renderContent() { @@ -92,8 +92,8 @@ export default class SendGasRow extends Component { gasLimit, insufficientBalance, isMainnet, - } = this.props - const { metricsEvent } = this.context + } = this.props; + const { metricsEvent } = this.context; const gasPriceButtonGroup = (
    @@ -108,28 +108,28 @@ export default class SendGasRow extends Component { action: 'Edit Screen', name: 'Changed Gas Button', }, - }) - await gasPriceButtonGroupProps.handleGasPriceSelection(opts) + }); + await gasPriceButtonGroupProps.handleGasPriceSelection(opts); if (maxModeOn) { - this.setMaxAmount() + this.setMaxAmount(); } }} />
    - ) + ); const gasFeeDisplay = ( { - resetGasButtons() + resetGasButtons(); if (maxModeOn) { - this.setMaxAmount() + this.setMaxAmount(); } }} onClick={() => showCustomizeGasModal()} /> - ) + ); const advancedGasInputs = (
    - ) + ); // Tests should behave in same way as mainnet, but are using Localhost if (advancedInlineGasShown || (!isMainnet && !process.env.IN_TEST)) { - return advancedGasInputs + return advancedGasInputs; } else if (gasButtonGroupShown) { - return gasPriceButtonGroup + return gasPriceButtonGroup; } - return gasFeeDisplay + return gasFeeDisplay; } render() { @@ -161,7 +161,7 @@ export default class SendGasRow extends Component { gasFeeError, gasButtonGroupShown, advancedInlineGasShown, - } = this.props + } = this.props; return ( <> @@ -176,6 +176,6 @@ export default class SendGasRow extends Component { {this.renderAdvancedOptionsButton()} ) : null} - ) + ); } } diff --git a/ui/app/pages/send/send-content/send-gas-row/send-gas-row.container.js b/ui/app/pages/send/send-content/send-gas-row/send-gas-row.container.js index 7387fd93f..210819f07 100644 --- a/ui/app/pages/send/send-content/send-gas-row/send-gas-row.container.js +++ b/ui/app/pages/send/send-content/send-gas-row/send-gas-row.container.js @@ -1,4 +1,4 @@ -import { connect } from 'react-redux' +import { connect } from 'react-redux'; import { getConversionRate, getGasTotal, @@ -18,49 +18,52 @@ import { getRenderableEstimateDataForSmallButtonsFromGWEI, getDefaultActiveButtonIndex, getIsMainnet, -} from '../../../../selectors' -import { isBalanceSufficient, calcGasTotal } from '../../send.utils' -import { calcMaxAmount } from '../send-amount-row/amount-max-button/amount-max-button.utils' +} from '../../../../selectors'; +import { isBalanceSufficient, calcGasTotal } from '../../send.utils'; +import { calcMaxAmount } from '../send-amount-row/amount-max-button/amount-max-button.utils'; import { showGasButtonGroup, updateSendErrors, -} from '../../../../ducks/send/send.duck' +} from '../../../../ducks/send/send.duck'; import { resetCustomData, setCustomGasPrice, setCustomGasLimit, -} from '../../../../ducks/gas/gas.duck' +} from '../../../../ducks/gas/gas.duck'; import { showModal, setGasPrice, setGasLimit, setGasTotal, updateSendAmount, -} from '../../../../store/actions' -import SendGasRow from './send-gas-row.component' +} from '../../../../store/actions'; +import SendGasRow from './send-gas-row.component'; export default connect( mapStateToProps, mapDispatchToProps, mergeProps, -)(SendGasRow) +)(SendGasRow); function mapStateToProps(state) { - const gasButtonInfo = getRenderableEstimateDataForSmallButtonsFromGWEI(state) - const gasPrice = getGasPrice(state) - const gasLimit = getGasLimit(state) - const activeButtonIndex = getDefaultActiveButtonIndex(gasButtonInfo, gasPrice) + const gasButtonInfo = getRenderableEstimateDataForSmallButtonsFromGWEI(state); + const gasPrice = getGasPrice(state); + const gasLimit = getGasLimit(state); + const activeButtonIndex = getDefaultActiveButtonIndex( + gasButtonInfo, + gasPrice, + ); - const gasTotal = getGasTotal(state) - const conversionRate = getConversionRate(state) - const balance = getCurrentEthBalance(state) + const gasTotal = getGasTotal(state); + const conversionRate = getConversionRate(state); + const balance = getCurrentEthBalance(state); const insufficientBalance = !isBalanceSufficient({ amount: getSendToken(state) ? '0x0' : getSendAmount(state), gasTotal, balance, conversionRate, - }) + }); return { balance: getSendFromBalance(state), @@ -82,7 +85,7 @@ function mapStateToProps(state) { sendToken: getSendToken(state), tokenBalance: getTokenBalance(state), isMainnet: getIsMainnet(state), - } + }; } function mapDispatchToProps(dispatch) { @@ -90,37 +93,37 @@ function mapDispatchToProps(dispatch) { showCustomizeGasModal: () => dispatch(showModal({ name: 'CUSTOMIZE_GAS', hideBasic: true })), setGasPrice: ({ gasPrice, gasLimit }) => { - dispatch(setGasPrice(gasPrice)) - dispatch(setCustomGasPrice(gasPrice)) + dispatch(setGasPrice(gasPrice)); + dispatch(setCustomGasPrice(gasPrice)); if (gasLimit) { - dispatch(setGasTotal(calcGasTotal(gasLimit, gasPrice))) + dispatch(setGasTotal(calcGasTotal(gasLimit, gasPrice))); } }, setGasLimit: (newLimit, gasPrice) => { - dispatch(setGasLimit(newLimit)) - dispatch(setCustomGasLimit(newLimit)) + dispatch(setGasLimit(newLimit)); + dispatch(setCustomGasLimit(newLimit)); if (gasPrice) { - dispatch(setGasTotal(calcGasTotal(newLimit, gasPrice))) + dispatch(setGasTotal(calcGasTotal(newLimit, gasPrice))); } }, setAmountToMax: (maxAmountDataObject) => { - dispatch(updateSendErrors({ amount: null })) - dispatch(updateSendAmount(calcMaxAmount(maxAmountDataObject))) + dispatch(updateSendErrors({ amount: null })); + dispatch(updateSendAmount(calcMaxAmount(maxAmountDataObject))); }, showGasButtonGroup: () => dispatch(showGasButtonGroup()), resetCustomData: () => dispatch(resetCustomData()), - } + }; } function mergeProps(stateProps, dispatchProps, ownProps) { - const { gasPriceButtonGroupProps } = stateProps - const { gasButtonInfo } = gasPriceButtonGroupProps + const { gasPriceButtonGroupProps } = stateProps; + const { gasButtonInfo } = gasPriceButtonGroupProps; const { setGasPrice: dispatchSetGasPrice, showGasButtonGroup: dispatchShowGasButtonGroup, resetCustomData: dispatchResetCustomData, ...otherDispatchProps - } = dispatchProps + } = dispatchProps; return { ...stateProps, @@ -131,10 +134,10 @@ function mergeProps(stateProps, dispatchProps, ownProps) { handleGasPriceSelection: dispatchSetGasPrice, }, resetGasButtons: () => { - dispatchResetCustomData() - dispatchSetGasPrice(gasButtonInfo[1].priceInHexWei) - dispatchShowGasButtonGroup() + dispatchResetCustomData(); + dispatchSetGasPrice(gasButtonInfo[1].priceInHexWei); + dispatchShowGasButtonGroup(); }, setGasPrice: dispatchSetGasPrice, - } + }; } diff --git a/ui/app/pages/send/send-content/send-gas-row/tests/send-gas-row-component.test.js b/ui/app/pages/send/send-content/send-gas-row/tests/send-gas-row-component.test.js index 926e9ae02..12bb6d7bf 100644 --- a/ui/app/pages/send/send-content/send-gas-row/tests/send-gas-row-component.test.js +++ b/ui/app/pages/send/send-content/send-gas-row/tests/send-gas-row-component.test.js @@ -1,20 +1,20 @@ -import assert from 'assert' -import React from 'react' -import { shallow } from 'enzyme' -import sinon from 'sinon' -import SendGasRow from '../send-gas-row.component' +import assert from 'assert'; +import React from 'react'; +import { shallow } from 'enzyme'; +import sinon from 'sinon'; +import SendGasRow from '../send-gas-row.component'; -import SendRowWrapper from '../../send-row-wrapper/send-row-wrapper.component' -import GasFeeDisplay from '../gas-fee-display/gas-fee-display.component' -import GasPriceButtonGroup from '../../../../../components/app/gas-customization/gas-price-button-group' +import SendRowWrapper from '../../send-row-wrapper/send-row-wrapper.component'; +import GasFeeDisplay from '../gas-fee-display/gas-fee-display.component'; +import GasPriceButtonGroup from '../../../../../components/app/gas-customization/gas-price-button-group'; const propsMethodSpies = { showCustomizeGasModal: sinon.spy(), resetGasButtons: sinon.spy(), -} +}; describe('SendGasRow Component', function () { - let wrapper + let wrapper; describe('render', function () { beforeEach(function () { @@ -34,77 +34,77 @@ describe('SendGasRow Component', function () { }} />, { context: { t: (str) => `${str}_t`, metricsEvent: () => ({}) } }, - ) - wrapper.setProps({ isMainnet: true }) - }) + ); + wrapper.setProps({ isMainnet: true }); + }); afterEach(function () { - propsMethodSpies.resetGasButtons.resetHistory() - }) + propsMethodSpies.resetGasButtons.resetHistory(); + }); it('should render a SendRowWrapper component', function () { - assert.strictEqual(wrapper.name(), 'Fragment') - assert.strictEqual(wrapper.at(0).find(SendRowWrapper).length, 1) - }) + assert.strictEqual(wrapper.name(), 'Fragment'); + assert.strictEqual(wrapper.at(0).find(SendRowWrapper).length, 1); + }); it('should pass the correct props to SendRowWrapper', function () { const { label, showError, errorType } = wrapper .find(SendRowWrapper) .first() - .props() + .props(); - assert.strictEqual(label, 'transactionFee_t:') - assert.strictEqual(showError, true) - assert.strictEqual(errorType, 'gasFee') - }) + assert.strictEqual(label, 'transactionFee_t:'); + assert.strictEqual(showError, true); + assert.strictEqual(errorType, 'gasFee'); + }); it('should render a GasFeeDisplay as a child of the SendRowWrapper', function () { - assert(wrapper.find(SendRowWrapper).first().childAt(0).is(GasFeeDisplay)) - }) + assert(wrapper.find(SendRowWrapper).first().childAt(0).is(GasFeeDisplay)); + }); it('should render the GasFeeDisplay', function () { const { gasLoadingError, gasTotal, onReset } = wrapper .find(SendRowWrapper) .first() .childAt(0) - .props() - assert.strictEqual(gasLoadingError, false) - assert.strictEqual(gasTotal, 'mockGasTotal') - assert.strictEqual(propsMethodSpies.resetGasButtons.callCount, 0) - onReset() - assert.strictEqual(propsMethodSpies.resetGasButtons.callCount, 1) - }) + .props(); + assert.strictEqual(gasLoadingError, false); + assert.strictEqual(gasTotal, 'mockGasTotal'); + assert.strictEqual(propsMethodSpies.resetGasButtons.callCount, 0); + onReset(); + assert.strictEqual(propsMethodSpies.resetGasButtons.callCount, 1); + }); it('should render the GasPriceButtonGroup if gasButtonGroupShown is true', function () { - wrapper.setProps({ gasButtonGroupShown: true }) - const rendered = wrapper.find(SendRowWrapper).first().childAt(0) - assert.strictEqual(wrapper.children().length, 2) + wrapper.setProps({ gasButtonGroupShown: true }); + const rendered = wrapper.find(SendRowWrapper).first().childAt(0); + assert.strictEqual(wrapper.children().length, 2); - const gasPriceButtonGroup = rendered.childAt(0) - assert(gasPriceButtonGroup.is(GasPriceButtonGroup)) - assert(gasPriceButtonGroup.hasClass('gas-price-button-group--small')) - assert.strictEqual(gasPriceButtonGroup.props().showCheck, false) + const gasPriceButtonGroup = rendered.childAt(0); + assert(gasPriceButtonGroup.is(GasPriceButtonGroup)); + assert(gasPriceButtonGroup.hasClass('gas-price-button-group--small')); + assert.strictEqual(gasPriceButtonGroup.props().showCheck, false); assert.strictEqual( gasPriceButtonGroup.props().someGasPriceButtonGroupProp, 'foo', - ) + ); assert.strictEqual( gasPriceButtonGroup.props().anotherGasPriceButtonGroupProp, 'bar', - ) - }) + ); + }); it('should render an advanced options button if gasButtonGroupShown is true', function () { - wrapper.setProps({ gasButtonGroupShown: true }) - const rendered = wrapper.find(SendRowWrapper).last() - assert.strictEqual(wrapper.children().length, 2) + wrapper.setProps({ gasButtonGroupShown: true }); + const rendered = wrapper.find(SendRowWrapper).last(); + assert.strictEqual(wrapper.children().length, 2); - const advancedOptionsButton = rendered.childAt(0) - assert.strictEqual(advancedOptionsButton.text(), 'advancedOptions_t') + const advancedOptionsButton = rendered.childAt(0); + assert.strictEqual(advancedOptionsButton.text(), 'advancedOptions_t'); - assert.strictEqual(propsMethodSpies.showCustomizeGasModal.callCount, 0) - advancedOptionsButton.props().onClick() - assert.strictEqual(propsMethodSpies.showCustomizeGasModal.callCount, 1) - }) - }) -}) + assert.strictEqual(propsMethodSpies.showCustomizeGasModal.callCount, 0); + advancedOptionsButton.props().onClick(); + assert.strictEqual(propsMethodSpies.showCustomizeGasModal.callCount, 1); + }); + }); +}); diff --git a/ui/app/pages/send/send-content/send-gas-row/tests/send-gas-row-container.test.js b/ui/app/pages/send/send-content/send-gas-row/tests/send-gas-row-container.test.js index ffaa87778..157082f76 100644 --- a/ui/app/pages/send/send-content/send-gas-row/tests/send-gas-row-container.test.js +++ b/ui/app/pages/send/send-content/send-gas-row/tests/send-gas-row-container.test.js @@ -1,33 +1,33 @@ -import assert from 'assert' -import proxyquire from 'proxyquire' -import sinon from 'sinon' +import assert from 'assert'; +import proxyquire from 'proxyquire'; +import sinon from 'sinon'; -let mapDispatchToProps -let mergeProps +let mapDispatchToProps; +let mergeProps; const actionSpies = { showModal: sinon.spy(), setGasPrice: sinon.spy(), setGasTotal: sinon.spy(), setGasLimit: sinon.spy(), -} +}; const sendDuckSpies = { showGasButtonGroup: sinon.spy(), -} +}; const gasDuckSpies = { resetCustomData: sinon.spy(), setCustomGasPrice: sinon.spy(), setCustomGasLimit: sinon.spy(), -} +}; proxyquire('../send-gas-row.container.js', { 'react-redux': { connect: (_, md, mp) => { - mapDispatchToProps = md - mergeProps = mp - return () => ({}) + mapDispatchToProps = md; + mergeProps = mp; + return () => ({}); }, }, '../../../../selectors': { @@ -41,91 +41,91 @@ proxyquire('../send-gas-row.container.js', { '../../../../store/actions': actionSpies, '../../../../ducks/send/send.duck': sendDuckSpies, '../../../../ducks/gas/gas.duck': gasDuckSpies, -}) +}); describe('send-gas-row container', function () { describe('mapDispatchToProps()', function () { - let dispatchSpy - let mapDispatchToPropsObject + let dispatchSpy; + let mapDispatchToPropsObject; beforeEach(function () { - dispatchSpy = sinon.spy() - mapDispatchToPropsObject = mapDispatchToProps(dispatchSpy) - actionSpies.setGasTotal.resetHistory() - }) + dispatchSpy = sinon.spy(); + mapDispatchToPropsObject = mapDispatchToProps(dispatchSpy); + actionSpies.setGasTotal.resetHistory(); + }); describe('showCustomizeGasModal()', function () { it('should dispatch an action', function () { - mapDispatchToPropsObject.showCustomizeGasModal() - assert(dispatchSpy.calledOnce) + mapDispatchToPropsObject.showCustomizeGasModal(); + assert(dispatchSpy.calledOnce); assert.deepStrictEqual(actionSpies.showModal.getCall(0).args[0], { name: 'CUSTOMIZE_GAS', hideBasic: true, - }) - }) - }) + }); + }); + }); describe('setGasPrice()', function () { it('should dispatch an action', function () { mapDispatchToPropsObject.setGasPrice({ gasPrice: 'mockNewPrice', gasLimit: 'mockLimit', - }) - assert(dispatchSpy.calledThrice) - assert(actionSpies.setGasPrice.calledOnce) + }); + assert(dispatchSpy.calledThrice); + assert(actionSpies.setGasPrice.calledOnce); assert.strictEqual( actionSpies.setGasPrice.getCall(0).args[0], 'mockNewPrice', - ) + ); assert.strictEqual( gasDuckSpies.setCustomGasPrice.getCall(0).args[0], 'mockNewPrice', - ) - assert(actionSpies.setGasTotal.calledOnce) + ); + assert(actionSpies.setGasTotal.calledOnce); assert.strictEqual( actionSpies.setGasTotal.getCall(0).args[0], 'mockLimitmockNewPrice', - ) - }) - }) + ); + }); + }); describe('setGasLimit()', function () { it('should dispatch an action', function () { - mapDispatchToPropsObject.setGasLimit('mockNewLimit', 'mockPrice') - assert(dispatchSpy.calledThrice) - assert(actionSpies.setGasLimit.calledOnce) + mapDispatchToPropsObject.setGasLimit('mockNewLimit', 'mockPrice'); + assert(dispatchSpy.calledThrice); + assert(actionSpies.setGasLimit.calledOnce); assert.strictEqual( actionSpies.setGasLimit.getCall(0).args[0], 'mockNewLimit', - ) + ); assert.strictEqual( gasDuckSpies.setCustomGasLimit.getCall(0).args[0], 'mockNewLimit', - ) - assert(actionSpies.setGasTotal.calledOnce) + ); + assert(actionSpies.setGasTotal.calledOnce); assert.strictEqual( actionSpies.setGasTotal.getCall(0).args[0], 'mockNewLimitmockPrice', - ) - }) - }) + ); + }); + }); describe('showGasButtonGroup()', function () { it('should dispatch an action', function () { - mapDispatchToPropsObject.showGasButtonGroup() - assert(dispatchSpy.calledOnce) - assert(sendDuckSpies.showGasButtonGroup.calledOnce) - }) - }) + mapDispatchToPropsObject.showGasButtonGroup(); + assert(dispatchSpy.calledOnce); + assert(sendDuckSpies.showGasButtonGroup.calledOnce); + }); + }); describe('resetCustomData()', function () { it('should dispatch an action', function () { - mapDispatchToPropsObject.resetCustomData() - assert(dispatchSpy.calledOnce) - assert(gasDuckSpies.resetCustomData.calledOnce) - }) - }) - }) + mapDispatchToPropsObject.resetCustomData(); + assert(dispatchSpy.calledOnce); + assert(gasDuckSpies.resetCustomData.calledOnce); + }); + }); + }); describe('mergeProps', function () { it('should return the expected props when isConfirm is true', function () { @@ -135,32 +135,32 @@ describe('send-gas-row container', function () { anotherGasPriceButtonGroupProp: 'bar', }, someOtherStateProp: 'baz', - } + }; const dispatchProps = { setGasPrice: sinon.spy(), someOtherDispatchProp: sinon.spy(), - } - const ownProps = { someOwnProp: 123 } - const result = mergeProps(stateProps, dispatchProps, ownProps) + }; + const ownProps = { someOwnProp: 123 }; + const result = mergeProps(stateProps, dispatchProps, ownProps); - assert.strictEqual(result.someOtherStateProp, 'baz') + assert.strictEqual(result.someOtherStateProp, 'baz'); assert.strictEqual( result.gasPriceButtonGroupProps.someGasPriceButtonGroupProp, 'foo', - ) + ); assert.strictEqual( result.gasPriceButtonGroupProps.anotherGasPriceButtonGroupProp, 'bar', - ) - assert.strictEqual(result.someOwnProp, 123) + ); + assert.strictEqual(result.someOwnProp, 123); - assert.strictEqual(dispatchProps.setGasPrice.callCount, 0) - result.gasPriceButtonGroupProps.handleGasPriceSelection() - assert.strictEqual(dispatchProps.setGasPrice.callCount, 1) + assert.strictEqual(dispatchProps.setGasPrice.callCount, 0); + result.gasPriceButtonGroupProps.handleGasPriceSelection(); + assert.strictEqual(dispatchProps.setGasPrice.callCount, 1); - assert.strictEqual(dispatchProps.someOtherDispatchProp.callCount, 0) - result.someOtherDispatchProp() - assert.strictEqual(dispatchProps.someOtherDispatchProp.callCount, 1) - }) - }) -}) + assert.strictEqual(dispatchProps.someOtherDispatchProp.callCount, 0); + result.someOtherDispatchProp(); + assert.strictEqual(dispatchProps.someOtherDispatchProp.callCount, 1); + }); + }); +}); diff --git a/ui/app/pages/send/send-content/send-hex-data-row/index.js b/ui/app/pages/send/send-content/send-hex-data-row/index.js index 08c341067..9ea3d437a 100644 --- a/ui/app/pages/send/send-content/send-hex-data-row/index.js +++ b/ui/app/pages/send/send-content/send-hex-data-row/index.js @@ -1 +1 @@ -export { default } from './send-hex-data-row.container' +export { default } from './send-hex-data-row.container'; diff --git a/ui/app/pages/send/send-content/send-hex-data-row/send-hex-data-row.component.js b/ui/app/pages/send/send-content/send-hex-data-row/send-hex-data-row.component.js index 2299f33bc..080b97b37 100644 --- a/ui/app/pages/send/send-content/send-hex-data-row/send-hex-data-row.component.js +++ b/ui/app/pages/send/send-content/send-hex-data-row/send-hex-data-row.component.js @@ -1,28 +1,28 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import SendRowWrapper from '../send-row-wrapper' +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import SendRowWrapper from '../send-row-wrapper'; export default class SendHexDataRow extends Component { static propTypes = { inError: PropTypes.bool, updateSendHexData: PropTypes.func.isRequired, updateGas: PropTypes.func.isRequired, - } + }; static contextTypes = { t: PropTypes.func, - } + }; onInput = (event) => { - const { updateSendHexData, updateGas } = this.props - const data = event.target.value.replace(/\n/gu, '') || null - updateSendHexData(data) - updateGas({ data }) - } + const { updateSendHexData, updateGas } = this.props; + const data = event.target.value.replace(/\n/gu, '') || null; + updateSendHexData(data); + updateGas({ data }); + }; render() { - const { inError } = this.props - const { t } = this.context + const { inError } = this.props; + const { t } = this.context; return ( - ) + ); } } diff --git a/ui/app/pages/send/send-content/send-hex-data-row/send-hex-data-row.container.js b/ui/app/pages/send/send-content/send-hex-data-row/send-hex-data-row.container.js index f20d97b51..20a8cad43 100644 --- a/ui/app/pages/send/send-content/send-hex-data-row/send-hex-data-row.container.js +++ b/ui/app/pages/send/send-content/send-hex-data-row/send-hex-data-row.container.js @@ -1,19 +1,19 @@ -import { connect } from 'react-redux' -import { updateSendHexData } from '../../../../store/actions' -import SendHexDataRow from './send-hex-data-row.component' +import { connect } from 'react-redux'; +import { updateSendHexData } from '../../../../store/actions'; +import SendHexDataRow from './send-hex-data-row.component'; -export default connect(mapStateToProps, mapDispatchToProps)(SendHexDataRow) +export default connect(mapStateToProps, mapDispatchToProps)(SendHexDataRow); function mapStateToProps(state) { return { data: state.metamask.send.data, - } + }; } function mapDispatchToProps(dispatch) { return { updateSendHexData(data) { - return dispatch(updateSendHexData(data)) + return dispatch(updateSendHexData(data)); }, - } + }; } diff --git a/ui/app/pages/send/send-content/send-row-wrapper/index.js b/ui/app/pages/send/send-content/send-row-wrapper/index.js index d17545dcc..ceda93d7a 100644 --- a/ui/app/pages/send/send-content/send-row-wrapper/index.js +++ b/ui/app/pages/send/send-content/send-row-wrapper/index.js @@ -1 +1 @@ -export { default } from './send-row-wrapper.component' +export { default } from './send-row-wrapper.component'; diff --git a/ui/app/pages/send/send-content/send-row-wrapper/send-row-error-message/index.js b/ui/app/pages/send/send-content/send-row-wrapper/send-row-error-message/index.js index c00617f83..b66d6bfa7 100644 --- a/ui/app/pages/send/send-content/send-row-wrapper/send-row-error-message/index.js +++ b/ui/app/pages/send/send-content/send-row-wrapper/send-row-error-message/index.js @@ -1 +1 @@ -export { default } from './send-row-error-message.container' +export { default } from './send-row-error-message.container'; diff --git a/ui/app/pages/send/send-content/send-row-wrapper/send-row-error-message/send-row-error-message.component.js b/ui/app/pages/send/send-content/send-row-wrapper/send-row-error-message/send-row-error-message.component.js index bdae808a7..41bf9fadb 100644 --- a/ui/app/pages/send/send-content/send-row-wrapper/send-row-error-message/send-row-error-message.component.js +++ b/ui/app/pages/send/send-content/send-row-wrapper/send-row-error-message/send-row-error-message.component.js @@ -1,21 +1,21 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import classnames from 'classnames' +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; export default class SendRowErrorMessage extends Component { static propTypes = { errors: PropTypes.object, errorType: PropTypes.string, - } + }; static contextTypes = { t: PropTypes.func, - } + }; render() { - const { errors, errorType } = this.props + const { errors, errorType } = this.props; - const errorMessage = errors[errorType] + const errorMessage = errors[errorType]; return errorMessage ? (
    {this.context.t(errorMessage)}
    - ) : null + ) : null; } } diff --git a/ui/app/pages/send/send-content/send-row-wrapper/send-row-error-message/send-row-error-message.container.js b/ui/app/pages/send/send-content/send-row-wrapper/send-row-error-message/send-row-error-message.container.js index b9969c5af..f857183f3 100644 --- a/ui/app/pages/send/send-content/send-row-wrapper/send-row-error-message/send-row-error-message.container.js +++ b/ui/app/pages/send/send-content/send-row-wrapper/send-row-error-message/send-row-error-message.container.js @@ -1,12 +1,12 @@ -import { connect } from 'react-redux' -import { getSendErrors } from '../../../../../selectors' -import SendRowErrorMessage from './send-row-error-message.component' +import { connect } from 'react-redux'; +import { getSendErrors } from '../../../../../selectors'; +import SendRowErrorMessage from './send-row-error-message.component'; -export default connect(mapStateToProps)(SendRowErrorMessage) +export default connect(mapStateToProps)(SendRowErrorMessage); function mapStateToProps(state, ownProps) { return { errors: getSendErrors(state), errorType: ownProps.errorType, - } + }; } diff --git a/ui/app/pages/send/send-content/send-row-wrapper/send-row-error-message/tests/send-row-error-message-component.test.js b/ui/app/pages/send/send-content/send-row-wrapper/send-row-error-message/tests/send-row-error-message-component.test.js index 41d318ffd..c8c0f5c61 100644 --- a/ui/app/pages/send/send-content/send-row-wrapper/send-row-error-message/tests/send-row-error-message-component.test.js +++ b/ui/app/pages/send/send-content/send-row-wrapper/send-row-error-message/tests/send-row-error-message-component.test.js @@ -1,10 +1,10 @@ -import assert from 'assert' -import React from 'react' -import { shallow } from 'enzyme' -import SendRowErrorMessage from '../send-row-error-message.component' +import assert from 'assert'; +import React from 'react'; +import { shallow } from 'enzyme'; +import SendRowErrorMessage from '../send-row-error-message.component'; describe('SendRowErrorMessage Component', function () { - let wrapper + let wrapper; describe('render', function () { beforeEach(function () { @@ -14,20 +14,20 @@ describe('SendRowErrorMessage Component', function () { errorType="error3" />, { context: { t: (str) => `${str}_t` } }, - ) - }) + ); + }); it('should render null if the passed errors do not contain an error of errorType', function () { - assert.strictEqual(wrapper.find('.send-v2__error').length, 0) - assert.strictEqual(wrapper.html(), null) - }) + assert.strictEqual(wrapper.find('.send-v2__error').length, 0); + assert.strictEqual(wrapper.html(), null); + }); it('should render an error message if the passed errors contain an error of errorType', function () { wrapper.setProps({ errors: { error1: 'abc', error2: 'def', error3: 'xyz' }, - }) - assert.strictEqual(wrapper.find('.send-v2__error').length, 1) - assert.strictEqual(wrapper.find('.send-v2__error').text(), 'xyz_t') - }) - }) -}) + }); + assert.strictEqual(wrapper.find('.send-v2__error').length, 1); + assert.strictEqual(wrapper.find('.send-v2__error').text(), 'xyz_t'); + }); + }); +}); diff --git a/ui/app/pages/send/send-content/send-row-wrapper/send-row-error-message/tests/send-row-error-message-container.test.js b/ui/app/pages/send/send-content/send-row-wrapper/send-row-error-message/tests/send-row-error-message-container.test.js index dd3a4da8f..f231b7734 100644 --- a/ui/app/pages/send/send-content/send-row-wrapper/send-row-error-message/tests/send-row-error-message-container.test.js +++ b/ui/app/pages/send/send-content/send-row-wrapper/send-row-error-message/tests/send-row-error-message-container.test.js @@ -1,17 +1,17 @@ -import assert from 'assert' -import proxyquire from 'proxyquire' +import assert from 'assert'; +import proxyquire from 'proxyquire'; -let mapStateToProps +let mapStateToProps; proxyquire('../send-row-error-message.container.js', { 'react-redux': { connect: (ms) => { - mapStateToProps = ms - return () => ({}) + mapStateToProps = ms; + return () => ({}); }, }, '../../../../../selectors': { getSendErrors: (s) => `mockErrors:${s}` }, -}) +}); describe('send-row-error-message container', function () { describe('mapStateToProps()', function () { @@ -22,7 +22,7 @@ describe('send-row-error-message container', function () { errors: 'mockErrors:mockState', errorType: 'someType', }, - ) - }) - }) -}) + ); + }); + }); +}); diff --git a/ui/app/pages/send/send-content/send-row-wrapper/send-row-wrapper.component.js b/ui/app/pages/send/send-content/send-row-wrapper/send-row-wrapper.component.js index e66d726c9..949917171 100644 --- a/ui/app/pages/send/send-content/send-row-wrapper/send-row-wrapper.component.js +++ b/ui/app/pages/send/send-content/send-row-wrapper/send-row-wrapper.component.js @@ -1,6 +1,6 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import SendRowErrorMessage from './send-row-error-message' +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import SendRowErrorMessage from './send-row-error-message'; export default class SendRowWrapper extends Component { static propTypes = { @@ -8,18 +8,18 @@ export default class SendRowWrapper extends Component { errorType: PropTypes.string, label: PropTypes.string, showError: PropTypes.bool, - } + }; static contextTypes = { t: PropTypes.func, - } + }; renderAmountFormRow() { - const { children, errorType = '', label, showError = false } = this.props + const { children, errorType = '', label, showError = false } = this.props; const formField = Array.isArray(children) ? children[1] || children[0] - : children - const customLabelContent = children.length > 1 ? children[0] : null + : children; + const customLabelContent = children.length > 1 ? children[0] : null; return (
    @@ -34,17 +34,17 @@ export default class SendRowWrapper extends Component {
    - ) + ); } renderFormRow() { - const { children, errorType = '', label, showError = false } = this.props + const { children, errorType = '', label, showError = false } = this.props; const formField = Array.isArray(children) ? children[1] || children[0] - : children + : children; const customLabelContent = - (Array.isArray(children) && children.length) > 1 ? children[0] : null + (Array.isArray(children) && children.length) > 1 ? children[0] : null; return (
    @@ -55,14 +55,14 @@ export default class SendRowWrapper extends Component {
    {formField}
    - ) + ); } render() { - const { errorType = '' } = this.props + const { errorType = '' } = this.props; return errorType === 'amount' ? this.renderAmountFormRow() - : this.renderFormRow() + : this.renderFormRow(); } } diff --git a/ui/app/pages/send/send-content/send-row-wrapper/tests/send-row-wrapper-component.test.js b/ui/app/pages/send/send-content/send-row-wrapper/tests/send-row-wrapper-component.test.js index 4a4b3189a..722168698 100644 --- a/ui/app/pages/send/send-content/send-row-wrapper/tests/send-row-wrapper-component.test.js +++ b/ui/app/pages/send/send-content/send-row-wrapper/tests/send-row-wrapper-component.test.js @@ -1,12 +1,12 @@ -import assert from 'assert' -import React from 'react' -import { shallow } from 'enzyme' -import SendRowWrapper from '../send-row-wrapper.component' +import assert from 'assert'; +import React from 'react'; +import { shallow } from 'enzyme'; +import SendRowWrapper from '../send-row-wrapper.component'; -import SendRowErrorMessage from '../send-row-error-message/send-row-error-message.container' +import SendRowErrorMessage from '../send-row-error-message/send-row-error-message.container'; describe('SendContent Component', function () { - let wrapper + let wrapper; describe('render', function () { beforeEach(function () { @@ -18,23 +18,23 @@ describe('SendContent Component', function () { > Mock Form Field , - ) - }) + ); + }); it('should render a div with a send-v2__form-row class', function () { - assert.strictEqual(wrapper.find('div.send-v2__form-row').length, 1) - }) + assert.strictEqual(wrapper.find('div.send-v2__form-row').length, 1); + }); it('should render two children of the root div, with send-v2_form label and field classes', function () { assert.strictEqual( wrapper.find('.send-v2__form-row > .send-v2__form-label').length, 1, - ) + ); assert.strictEqual( wrapper.find('.send-v2__form-row > .send-v2__form-field').length, 1, - ) - }) + ); + }); it('should render the label as a child of the send-v2__form-label', function () { assert.strictEqual( @@ -43,8 +43,8 @@ describe('SendContent Component', function () { .childAt(0) .text(), 'mockLabel', - ) - }) + ); + }); it('should render its first child as a child of the send-v2__form-field', function () { assert.strictEqual( @@ -53,25 +53,25 @@ describe('SendContent Component', function () { .childAt(0) .text(), 'Mock Form Field', - ) - }) + ); + }); it('should not render a SendRowErrorMessage if showError is false', function () { - assert.strictEqual(wrapper.find(SendRowErrorMessage).length, 0) - }) + assert.strictEqual(wrapper.find(SendRowErrorMessage).length, 0); + }); it('should render a SendRowErrorMessage with and errorType props if showError is true', function () { - wrapper.setProps({ showError: true }) - assert.strictEqual(wrapper.find(SendRowErrorMessage).length, 1) + wrapper.setProps({ showError: true }); + assert.strictEqual(wrapper.find(SendRowErrorMessage).length, 1); const expectedSendRowErrorMessage = wrapper .find('.send-v2__form-row > .send-v2__form-label') - .childAt(1) - assert(expectedSendRowErrorMessage.is(SendRowErrorMessage)) + .childAt(1); + assert(expectedSendRowErrorMessage.is(SendRowErrorMessage)); assert.deepStrictEqual(expectedSendRowErrorMessage.props(), { errorType: 'mockErrorType', - }) - }) + }); + }); it('should render its second child as a child of the send-v2__form-field, if it has two children', function () { wrapper = shallow( @@ -83,15 +83,15 @@ describe('SendContent Component', function () { Mock Custom Label Content Mock Form Field , - ) + ); assert.strictEqual( wrapper .find('.send-v2__form-row > .send-v2__form-field') .childAt(0) .text(), 'Mock Form Field', - ) - }) + ); + }); it('should render its first child as the last child of the send-v2__form-label, if it has two children', function () { wrapper = shallow( @@ -103,14 +103,14 @@ describe('SendContent Component', function () { Mock Custom Label Content Mock Form Field , - ) + ); assert.strictEqual( wrapper .find('.send-v2__form-row > .send-v2__form-label') .childAt(1) .text(), 'Mock Custom Label Content', - ) - }) - }) -}) + ); + }); + }); +}); diff --git a/ui/app/pages/send/send-content/tests/send-content-component.test.js b/ui/app/pages/send/send-content/tests/send-content-component.test.js index 2628c516a..b652d369f 100644 --- a/ui/app/pages/send/send-content/tests/send-content-component.test.js +++ b/ui/app/pages/send/send-content/tests/send-content-component.test.js @@ -1,157 +1,157 @@ -import assert from 'assert' -import React from 'react' -import { shallow } from 'enzyme' -import SendContent from '../send-content.component' +import assert from 'assert'; +import React from 'react'; +import { shallow } from 'enzyme'; +import SendContent from '../send-content.component'; -import PageContainerContent from '../../../../components/ui/page-container/page-container-content.component' -import SendAmountRow from '../send-amount-row/send-amount-row.container' -import SendGasRow from '../send-gas-row/send-gas-row.container' -import SendHexDataRow from '../send-hex-data-row/send-hex-data-row.container' -import SendAssetRow from '../send-asset-row/send-asset-row.container' -import Dialog from '../../../../components/ui/dialog' +import PageContainerContent from '../../../../components/ui/page-container/page-container-content.component'; +import SendAmountRow from '../send-amount-row/send-amount-row.container'; +import SendGasRow from '../send-gas-row/send-gas-row.container'; +import SendHexDataRow from '../send-hex-data-row/send-hex-data-row.container'; +import SendAssetRow from '../send-asset-row/send-asset-row.container'; +import Dialog from '../../../../components/ui/dialog'; describe('SendContent Component', function () { - let wrapper + let wrapper; beforeEach(function () { wrapper = shallow(, { context: { t: (str) => `${str}_t` }, - }) - }) + }); + }); describe('render', function () { it('should render a PageContainerContent component', function () { - assert.strictEqual(wrapper.find(PageContainerContent).length, 1) - }) + assert.strictEqual(wrapper.find(PageContainerContent).length, 1); + }); it('should render a div with a .send-v2__form class as a child of PageContainerContent', function () { const PageContainerContentChild = wrapper .find(PageContainerContent) - .children() - PageContainerContentChild.is('div') - PageContainerContentChild.is('.send-v2__form') - }) + .children(); + PageContainerContentChild.is('div'); + PageContainerContentChild.is('.send-v2__form'); + }); it('should render the correct row components as grandchildren of the PageContainerContent component', function () { const PageContainerContentChild = wrapper .find(PageContainerContent) - .children() + .children(); assert( PageContainerContentChild.childAt(0).is(Dialog), 'row[0] should be Dialog', - ) + ); assert( PageContainerContentChild.childAt(1).is(SendAssetRow), 'row[1] should be SendAssetRow', - ) + ); assert( PageContainerContentChild.childAt(2).is(SendAmountRow), 'row[2] should be SendAmountRow', - ) + ); assert( PageContainerContentChild.childAt(3).is(SendGasRow), 'row[3] should be SendGasRow', - ) + ); assert( PageContainerContentChild.childAt(4).is(SendHexDataRow), 'row[4] should be SendHexDataRow', - ) - }) + ); + }); it('should not render the SendHexDataRow if props.showHexData is false', function () { - wrapper.setProps({ showHexData: false }) + wrapper.setProps({ showHexData: false }); const PageContainerContentChild = wrapper .find(PageContainerContent) - .children() + .children(); assert( PageContainerContentChild.childAt(0).is(Dialog), 'row[0] should be Dialog', - ) + ); assert( PageContainerContentChild.childAt(1).is(SendAssetRow), 'row[1] should be SendAssetRow', - ) + ); assert( PageContainerContentChild.childAt(2).is(SendAmountRow), 'row[2] should be SendAmountRow', - ) + ); assert( PageContainerContentChild.childAt(3).is(SendGasRow), 'row[3] should be SendGasRow', - ) - assert.strictEqual(PageContainerContentChild.childAt(4).exists(), false) - }) + ); + assert.strictEqual(PageContainerContentChild.childAt(4).exists(), false); + }); it('should not render the Dialog if contact has a name', function () { wrapper.setProps({ showHexData: false, contact: { name: 'testName' }, - }) + }); const PageContainerContentChild = wrapper .find(PageContainerContent) - .children() + .children(); assert( PageContainerContentChild.childAt(0).is(SendAssetRow), 'row[1] should be SendAssetRow', - ) + ); assert( PageContainerContentChild.childAt(1).is(SendAmountRow), 'row[2] should be SendAmountRow', - ) + ); assert( PageContainerContentChild.childAt(2).is(SendGasRow), 'row[3] should be SendGasRow', - ) - assert.strictEqual(PageContainerContentChild.childAt(3).exists(), false) - }) + ); + assert.strictEqual(PageContainerContentChild.childAt(3).exists(), false); + }); it('should not render the Dialog if it is an ownedAccount', function () { wrapper.setProps({ showHexData: false, isOwnedAccount: true, - }) + }); const PageContainerContentChild = wrapper .find(PageContainerContent) - .children() + .children(); assert( PageContainerContentChild.childAt(0).is(SendAssetRow), 'row[1] should be SendAssetRow', - ) + ); assert( PageContainerContentChild.childAt(1).is(SendAmountRow), 'row[2] should be SendAmountRow', - ) + ); assert( PageContainerContentChild.childAt(2).is(SendGasRow), 'row[3] should be SendGasRow', - ) - assert.strictEqual(PageContainerContentChild.childAt(3).exists(), false) - }) - }) + ); + assert.strictEqual(PageContainerContentChild.childAt(3).exists(), false); + }); + }); it('should not render the asset dropdown if token length is 0 ', function () { - wrapper.setProps({ tokens: [] }) + wrapper.setProps({ tokens: [] }); const PageContainerContentChild = wrapper .find(PageContainerContent) - .children() - assert(PageContainerContentChild.childAt(1).is(SendAssetRow)) + .children(); + assert(PageContainerContentChild.childAt(1).is(SendAssetRow)); assert( PageContainerContentChild.childAt(1).find( 'send-v2__asset-dropdown__single-asset', ), true, - ) - }) + ); + }); it('should render warning', function () { wrapper.setProps({ warning: 'watchout', - }) + }); - const dialog = wrapper.find(Dialog).at(0) + const dialog = wrapper.find(Dialog).at(0); - assert.strictEqual(dialog.props().type, 'warning') - assert.strictEqual(dialog.props().children, 'watchout_t') - assert.strictEqual(dialog.length, 1) - }) -}) + assert.strictEqual(dialog.props().type, 'warning'); + assert.strictEqual(dialog.props().children, 'watchout_t'); + assert.strictEqual(dialog.length, 1); + }); +}); diff --git a/ui/app/pages/send/send-footer/index.js b/ui/app/pages/send/send-footer/index.js index 58e91d622..cbada59c0 100644 --- a/ui/app/pages/send/send-footer/index.js +++ b/ui/app/pages/send/send-footer/index.js @@ -1 +1 @@ -export { default } from './send-footer.container' +export { default } from './send-footer.container'; diff --git a/ui/app/pages/send/send-footer/send-footer.component.js b/ui/app/pages/send/send-footer/send-footer.component.js index 938b7ce5a..425c76086 100644 --- a/ui/app/pages/send/send-footer/send-footer.component.js +++ b/ui/app/pages/send/send-footer/send-footer.component.js @@ -1,7 +1,7 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import PageContainerFooter from '../../../components/ui/page-container/page-container-footer' -import { CONFIRM_TRANSACTION_ROUTE } from '../../../helpers/constants/routes' +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import PageContainerFooter from '../../../components/ui/page-container/page-container-footer'; +import { CONFIRM_TRANSACTION_ROUTE } from '../../../helpers/constants/routes'; export default class SendFooter extends Component { static propTypes = { @@ -27,21 +27,21 @@ export default class SendFooter extends Component { gasEstimateType: PropTypes.string, gasIsLoading: PropTypes.bool, mostRecentOverviewPage: PropTypes.string.isRequired, - } + }; static contextTypes = { t: PropTypes.func, metricsEvent: PropTypes.func, - } + }; onCancel() { - const { clearSend, history, mostRecentOverviewPage } = this.props - clearSend() - history.push(mostRecentOverviewPage) + const { clearSend, history, mostRecentOverviewPage } = this.props; + clearSend(); + history.push(mostRecentOverviewPage); } async onSubmit(event) { - event.preventDefault() + event.preventDefault(); const { addToAddressBookIfNew, amount, @@ -59,8 +59,8 @@ export default class SendFooter extends Component { toAccounts, history, gasEstimateType, - } = this.props - const { metricsEvent } = this.context + } = this.props; + const { metricsEvent } = this.context; // Should not be needed because submit should be disabled if there are errors. // const noErrors = !amountError && toError === null @@ -70,7 +70,7 @@ export default class SendFooter extends Component { // } // TODO: add nickname functionality - await addToAddressBookIfNew(to, toAccounts) + await addToAddressBookIfNew(to, toAccounts); const promise = editingTransactionId ? update({ amount, @@ -83,7 +83,7 @@ export default class SendFooter extends Component { to, unapprovedTxs, }) - : sign({ data, sendToken, to, amount, from, gas, gasPrice }) + : sign({ data, sendToken, to, amount, from, gas, gasPrice }); Promise.resolve(promise).then(() => { metricsEvent({ @@ -95,9 +95,9 @@ export default class SendFooter extends Component { customVariables: { gasChanged: gasEstimateType, }, - }) - history.push(CONFIRM_TRANSACTION_ROUTE) - }) + }); + history.push(CONFIRM_TRANSACTION_ROUTE); + }); } formShouldBeDisabled() { @@ -110,25 +110,25 @@ export default class SendFooter extends Component { to, gasLimit, gasIsLoading, - } = this.props - const missingTokenBalance = sendToken && !tokenBalance - const gasLimitTooLow = gasLimit < 5208 // 5208 is hex value of 21000, minimum gas limit + } = this.props; + const missingTokenBalance = sendToken && !tokenBalance; + const gasLimitTooLow = gasLimit < 5208; // 5208 is hex value of 21000, minimum gas limit const shouldBeDisabled = inError || !gasTotal || missingTokenBalance || !(data || to) || gasLimitTooLow || - gasIsLoading - return shouldBeDisabled + gasIsLoading; + return shouldBeDisabled; } componentDidUpdate(prevProps) { - const { inError, sendErrors } = this.props - const { metricsEvent } = this.context + const { inError, sendErrors } = this.props; + const { metricsEvent } = this.context; if (!prevProps.inError && inError) { - const errorField = Object.keys(sendErrors).find((key) => sendErrors[key]) - const errorMessage = sendErrors[errorField] + const errorField = Object.keys(sendErrors).find((key) => sendErrors[key]); + const errorMessage = sendErrors[errorField]; metricsEvent({ eventOpts: { @@ -140,7 +140,7 @@ export default class SendFooter extends Component { errorField, errorMessage, }, - }) + }); } } @@ -151,6 +151,6 @@ export default class SendFooter extends Component { onSubmit={(e) => this.onSubmit(e)} disabled={this.formShouldBeDisabled()} /> - ) + ); } } diff --git a/ui/app/pages/send/send-footer/send-footer.container.js b/ui/app/pages/send/send-footer/send-footer.container.js index e03af3228..ff7b475bc 100644 --- a/ui/app/pages/send/send-footer/send-footer.container.js +++ b/ui/app/pages/send/send-footer/send-footer.container.js @@ -1,11 +1,11 @@ -import { connect } from 'react-redux' +import { connect } from 'react-redux'; import { addToAddressBook, clearSend, signTokenTx, signTx, updateTransaction, -} from '../../../store/actions' +} from '../../../store/actions'; import { getGasLimit, getGasPrice, @@ -24,27 +24,30 @@ import { getGasIsLoading, getRenderableEstimateDataForSmallButtonsFromGWEI, getDefaultActiveButtonIndex, -} from '../../../selectors' -import { getMostRecentOverviewPage } from '../../../ducks/history/history' -import { addHexPrefix } from '../../../../../app/scripts/lib/util' -import SendFooter from './send-footer.component' +} from '../../../selectors'; +import { getMostRecentOverviewPage } from '../../../ducks/history/history'; +import { addHexPrefix } from '../../../../../app/scripts/lib/util'; +import SendFooter from './send-footer.component'; import { addressIsNew, constructTxParams, constructUpdatedTx, -} from './send-footer.utils' +} from './send-footer.utils'; -export default connect(mapStateToProps, mapDispatchToProps)(SendFooter) +export default connect(mapStateToProps, mapDispatchToProps)(SendFooter); function mapStateToProps(state) { - const gasButtonInfo = getRenderableEstimateDataForSmallButtonsFromGWEI(state) - const gasPrice = getGasPrice(state) - const activeButtonIndex = getDefaultActiveButtonIndex(gasButtonInfo, gasPrice) + const gasButtonInfo = getRenderableEstimateDataForSmallButtonsFromGWEI(state); + const gasPrice = getGasPrice(state); + const activeButtonIndex = getDefaultActiveButtonIndex( + gasButtonInfo, + gasPrice, + ); const gasEstimateType = activeButtonIndex >= 0 ? gasButtonInfo[activeButtonIndex].gasEstimateType - : 'custom' - const editingTransactionId = getSendEditingTransactionId(state) + : 'custom'; + const editingTransactionId = getSendEditingTransactionId(state); return { amount: getSendAmount(state), @@ -64,7 +67,7 @@ function mapStateToProps(state) { gasEstimateType, gasIsLoading: getGasIsLoading(state), mostRecentOverviewPage: getMostRecentOverviewPage(state), - } + }; } function mapDispatchToProps(dispatch) { @@ -79,11 +82,11 @@ function mapDispatchToProps(dispatch) { gasPrice, sendToken, to, - }) + }); sendToken ? dispatch(signTokenTx(sendToken.address, to, amount, txParams)) - : dispatch(signTx(txParams)) + : dispatch(signTx(txParams)); }, update: ({ amount, @@ -106,17 +109,17 @@ function mapDispatchToProps(dispatch) { sendToken, to, unapprovedTxs, - }) + }); - return dispatch(updateTransaction(editingTx)) + return dispatch(updateTransaction(editingTx)); }, addToAddressBookIfNew: (newAddress, toAccounts, nickname = '') => { - const hexPrefixedAddress = addHexPrefix(newAddress) + const hexPrefixedAddress = addHexPrefix(newAddress); if (addressIsNew(toAccounts, hexPrefixedAddress)) { // TODO: nickname, i.e. addToAddressBook(recipient, nickname) - dispatch(addToAddressBook(hexPrefixedAddress, nickname)) + dispatch(addToAddressBook(hexPrefixedAddress, nickname)); } }, - } + }; } diff --git a/ui/app/pages/send/send-footer/send-footer.utils.js b/ui/app/pages/send/send-footer/send-footer.utils.js index a09331da7..52be9143f 100644 --- a/ui/app/pages/send/send-footer/send-footer.utils.js +++ b/ui/app/pages/send/send-footer/send-footer.utils.js @@ -1,7 +1,7 @@ -import ethAbi from 'ethereumjs-abi' -import { TOKEN_TRANSFER_FUNCTION_SIGNATURE } from '../send.constants' -import { addHexPrefix } from '../../../../../app/scripts/lib/util' -import { addHexPrefixToObjectValues } from '../../../helpers/utils/util' +import ethAbi from 'ethereumjs-abi'; +import { TOKEN_TRANSFER_FUNCTION_SIGNATURE } from '../send.constants'; +import { addHexPrefix } from '../../../../../app/scripts/lib/util'; +import { addHexPrefixToObjectValues } from '../../../helpers/utils/util'; export function constructTxParams({ sendToken, @@ -18,14 +18,14 @@ export function constructTxParams({ value: '0', gas, gasPrice, - } + }; if (!sendToken) { - txParams.value = amount - txParams.to = to + txParams.value = amount; + txParams.to = to; } - return addHexPrefixToObjectValues(txParams) + return addHexPrefixToObjectValues(txParams); } export function constructUpdatedTx({ @@ -39,10 +39,10 @@ export function constructUpdatedTx({ to, unapprovedTxs, }) { - const unapprovedTx = unapprovedTxs[editingTransactionId] + const unapprovedTx = unapprovedTxs[editingTransactionId]; const txParamsData = unapprovedTx.txParams.data ? unapprovedTx.txParams.data - : data + : data; const editingTx = { ...unapprovedTx, @@ -57,7 +57,7 @@ export function constructUpdatedTx({ value: amount, }), ), - } + }; if (sendToken) { Object.assign( @@ -77,20 +77,20 @@ export function constructUpdatedTx({ ) .join(''), }), - ) + ); } if (typeof editingTx.txParams.data === 'undefined') { - delete editingTx.txParams.data + delete editingTx.txParams.data; } - return editingTx + return editingTx; } export function addressIsNew(toAccounts, newAddress) { - const newAddressNormalized = newAddress.toLowerCase() + const newAddressNormalized = newAddress.toLowerCase(); const foundMatching = toAccounts.some( ({ address }) => address.toLowerCase() === newAddressNormalized, - ) - return !foundMatching + ); + return !foundMatching; } diff --git a/ui/app/pages/send/send-footer/tests/send-footer-component.test.js b/ui/app/pages/send/send-footer/tests/send-footer-component.test.js index d77b7fe87..a1f5a6ccd 100644 --- a/ui/app/pages/send/send-footer/tests/send-footer-component.test.js +++ b/ui/app/pages/send/send-footer/tests/send-footer-component.test.js @@ -1,29 +1,29 @@ -import assert from 'assert' -import React from 'react' -import { shallow } from 'enzyme' -import sinon from 'sinon' -import { CONFIRM_TRANSACTION_ROUTE } from '../../../../helpers/constants/routes' -import SendFooter from '../send-footer.component' -import PageContainerFooter from '../../../../components/ui/page-container/page-container-footer' +import assert from 'assert'; +import React from 'react'; +import { shallow } from 'enzyme'; +import sinon from 'sinon'; +import { CONFIRM_TRANSACTION_ROUTE } from '../../../../helpers/constants/routes'; +import SendFooter from '../send-footer.component'; +import PageContainerFooter from '../../../../components/ui/page-container/page-container-footer'; describe('SendFooter Component', function () { - let wrapper + let wrapper; const propsMethodSpies = { addToAddressBookIfNew: sinon.spy(), clearSend: sinon.spy(), sign: sinon.spy(), update: sinon.spy(), - } + }; const historySpies = { push: sinon.spy(), - } - const MOCK_EVENT = { preventDefault: () => undefined } + }; + const MOCK_EVENT = { preventDefault: () => undefined }; before(function () { - sinon.spy(SendFooter.prototype, 'onCancel') - sinon.spy(SendFooter.prototype, 'onSubmit') - }) + sinon.spy(SendFooter.prototype, 'onCancel'); + sinon.spy(SendFooter.prototype, 'onSubmit'); + }); beforeEach(function () { wrapper = shallow( @@ -51,41 +51,41 @@ describe('SendFooter Component', function () { mostRecentOverviewPage="mostRecentOverviewPage" />, { context: { t: (str) => str, metricsEvent: () => ({}) } }, - ) - }) + ); + }); afterEach(function () { - propsMethodSpies.clearSend.resetHistory() - propsMethodSpies.addToAddressBookIfNew.resetHistory() - propsMethodSpies.clearSend.resetHistory() - propsMethodSpies.sign.resetHistory() - propsMethodSpies.update.resetHistory() - historySpies.push.resetHistory() - SendFooter.prototype.onCancel.resetHistory() - SendFooter.prototype.onSubmit.resetHistory() - }) + propsMethodSpies.clearSend.resetHistory(); + propsMethodSpies.addToAddressBookIfNew.resetHistory(); + propsMethodSpies.clearSend.resetHistory(); + propsMethodSpies.sign.resetHistory(); + propsMethodSpies.update.resetHistory(); + historySpies.push.resetHistory(); + SendFooter.prototype.onCancel.resetHistory(); + SendFooter.prototype.onSubmit.resetHistory(); + }); after(function () { - sinon.restore() - }) + sinon.restore(); + }); describe('onCancel', function () { it('should call clearSend', function () { - assert.strictEqual(propsMethodSpies.clearSend.callCount, 0) - wrapper.instance().onCancel() - assert.strictEqual(propsMethodSpies.clearSend.callCount, 1) - }) + assert.strictEqual(propsMethodSpies.clearSend.callCount, 0); + wrapper.instance().onCancel(); + assert.strictEqual(propsMethodSpies.clearSend.callCount, 1); + }); it('should call history.push', function () { - assert.strictEqual(historySpies.push.callCount, 0) - wrapper.instance().onCancel() - assert.strictEqual(historySpies.push.callCount, 1) + assert.strictEqual(historySpies.push.callCount, 0); + wrapper.instance().onCancel(); + assert.strictEqual(historySpies.push.callCount, 1); assert.strictEqual( historySpies.push.getCall(0).args[0], 'mostRecentOverviewPage', - ) - }) - }) + ); + }); + }); describe('formShouldBeDisabled()', function () { const config = { @@ -129,31 +129,31 @@ describe('SendFooter Component', function () { expectedResult: false, gasIsLoading: false, }, - } + }; Object.entries(config).forEach(([description, obj]) => { it(description, function () { - wrapper.setProps(obj) + wrapper.setProps(obj); assert.strictEqual( wrapper.instance().formShouldBeDisabled(), obj.expectedResult, - ) - }) - }) - }) + ); + }); + }); + }); describe('onSubmit', function () { it('should call addToAddressBookIfNew with the correct params', function () { - wrapper.instance().onSubmit(MOCK_EVENT) - assert(propsMethodSpies.addToAddressBookIfNew.calledOnce) + wrapper.instance().onSubmit(MOCK_EVENT); + assert(propsMethodSpies.addToAddressBookIfNew.calledOnce); assert.deepStrictEqual( propsMethodSpies.addToAddressBookIfNew.getCall(0).args, ['mockTo', ['mockAccount']], - ) - }) + ); + }); it('should call props.update if editingTransactionId is truthy', async function () { - await wrapper.instance().onSubmit(MOCK_EVENT) - assert(propsMethodSpies.update.calledOnce) + await wrapper.instance().onSubmit(MOCK_EVENT); + assert(propsMethodSpies.update.calledOnce); assert.deepStrictEqual(propsMethodSpies.update.getCall(0).args[0], { data: undefined, amount: 'mockAmount', @@ -164,17 +164,17 @@ describe('SendFooter Component', function () { sendToken: { mockProp: 'mockSendTokenProp' }, to: 'mockTo', unapprovedTxs: {}, - }) - }) + }); + }); it('should not call props.sign if editingTransactionId is truthy', function () { - assert.strictEqual(propsMethodSpies.sign.callCount, 0) - }) + assert.strictEqual(propsMethodSpies.sign.callCount, 0); + }); it('should call props.sign if editingTransactionId is falsy', async function () { - wrapper.setProps({ editingTransactionId: null }) - await wrapper.instance().onSubmit(MOCK_EVENT) - assert(propsMethodSpies.sign.calledOnce) + wrapper.setProps({ editingTransactionId: null }); + await wrapper.instance().onSubmit(MOCK_EVENT); + assert(propsMethodSpies.sign.calledOnce); assert.deepStrictEqual(propsMethodSpies.sign.getCall(0).args[0], { data: undefined, amount: 'mockAmount', @@ -183,26 +183,26 @@ describe('SendFooter Component', function () { gasPrice: 'mockGasPrice', sendToken: { mockProp: 'mockSendTokenProp' }, to: 'mockTo', - }) - }) + }); + }); it('should not call props.update if editingTransactionId is falsy', function () { - assert.strictEqual(propsMethodSpies.update.callCount, 0) - }) + assert.strictEqual(propsMethodSpies.update.callCount, 0); + }); it('should call history.push', async function () { - await wrapper.instance().onSubmit(MOCK_EVENT) - assert.strictEqual(historySpies.push.callCount, 1) + await wrapper.instance().onSubmit(MOCK_EVENT); + assert.strictEqual(historySpies.push.callCount, 1); assert.strictEqual( historySpies.push.getCall(0).args[0], CONFIRM_TRANSACTION_ROUTE, - ) - }) - }) + ); + }); + }); describe('render', function () { beforeEach(function () { - sinon.stub(SendFooter.prototype, 'formShouldBeDisabled').returns(true) + sinon.stub(SendFooter.prototype, 'formShouldBeDisabled').returns(true); wrapper = shallow( , { context: { t: (str) => str, metricsEvent: () => ({}) } }, - ) - }) + ); + }); afterEach(function () { - SendFooter.prototype.formShouldBeDisabled.restore() - }) + SendFooter.prototype.formShouldBeDisabled.restore(); + }); it('should render a PageContainerFooter component', function () { - assert.strictEqual(wrapper.find(PageContainerFooter).length, 1) - }) + assert.strictEqual(wrapper.find(PageContainerFooter).length, 1); + }); it('should pass the correct props to PageContainerFooter', function () { const { onCancel, onSubmit, disabled } = wrapper .find(PageContainerFooter) - .props() - assert.strictEqual(disabled, true) + .props(); + assert.strictEqual(disabled, true); - assert.strictEqual(SendFooter.prototype.onSubmit.callCount, 0) - onSubmit(MOCK_EVENT) - assert.strictEqual(SendFooter.prototype.onSubmit.callCount, 1) + assert.strictEqual(SendFooter.prototype.onSubmit.callCount, 0); + onSubmit(MOCK_EVENT); + assert.strictEqual(SendFooter.prototype.onSubmit.callCount, 1); - assert.strictEqual(SendFooter.prototype.onCancel.callCount, 0) - onCancel() - assert.strictEqual(SendFooter.prototype.onCancel.callCount, 1) - }) - }) -}) + assert.strictEqual(SendFooter.prototype.onCancel.callCount, 0); + onCancel(); + assert.strictEqual(SendFooter.prototype.onCancel.callCount, 1); + }); + }); +}); diff --git a/ui/app/pages/send/send-footer/tests/send-footer-container.test.js b/ui/app/pages/send/send-footer/tests/send-footer-container.test.js index e037fe7cc..88523ee27 100644 --- a/ui/app/pages/send/send-footer/tests/send-footer-container.test.js +++ b/ui/app/pages/send/send-footer/tests/send-footer-container.test.js @@ -1,8 +1,8 @@ -import assert from 'assert' -import proxyquire from 'proxyquire' -import sinon from 'sinon' +import assert from 'assert'; +import proxyquire from 'proxyquire'; +import sinon from 'sinon'; -let mapDispatchToProps +let mapDispatchToProps; const actionSpies = { addToAddressBook: sinon.spy(), @@ -10,20 +10,20 @@ const actionSpies = { signTokenTx: sinon.spy(), signTx: sinon.spy(), updateTransaction: sinon.spy(), -} +}; const utilsStubs = { addressIsNew: sinon.stub().returns(true), constructTxParams: sinon.stub().returns({ value: 'mockAmount', }), constructUpdatedTx: sinon.stub().returns('mockConstructedUpdatedTxParams'), -} +}; proxyquire('../send-footer.container.js', { 'react-redux': { connect: (_, md) => { - mapDispatchToProps = md - return () => ({}) + mapDispatchToProps = md; + return () => ({}); }, }, '../../../store/actions': actionSpies, @@ -49,25 +49,25 @@ proxyquire('../send-footer.container.js', { getDefaultActiveButtonIndex: () => 0, }, './send-footer.utils': utilsStubs, -}) +}); describe('send-footer container', function () { describe('mapDispatchToProps()', function () { - let dispatchSpy - let mapDispatchToPropsObject + let dispatchSpy; + let mapDispatchToPropsObject; beforeEach(function () { - dispatchSpy = sinon.spy() - mapDispatchToPropsObject = mapDispatchToProps(dispatchSpy) - }) + dispatchSpy = sinon.spy(); + mapDispatchToPropsObject = mapDispatchToProps(dispatchSpy); + }); describe('clearSend()', function () { it('should dispatch an action', function () { - mapDispatchToPropsObject.clearSend() - assert(dispatchSpy.calledOnce) - assert(actionSpies.clearSend.calledOnce) - }) - }) + mapDispatchToPropsObject.clearSend(); + assert(dispatchSpy.calledOnce); + assert(actionSpies.clearSend.calledOnce); + }); + }); describe('sign()', function () { it('should dispatch a signTokenTx action if sendToken is defined', function () { @@ -80,8 +80,8 @@ describe('send-footer container', function () { from: 'mockFrom', gas: 'mockGas', gasPrice: 'mockGasPrice', - }) - assert(dispatchSpy.calledOnce) + }); + assert(dispatchSpy.calledOnce); assert.deepStrictEqual( utilsStubs.constructTxParams.getCall(0).args[0], { @@ -95,25 +95,25 @@ describe('send-footer container', function () { gas: 'mockGas', gasPrice: 'mockGasPrice', }, - ) + ); assert.deepStrictEqual(actionSpies.signTokenTx.getCall(0).args, [ '0xabc', 'mockTo', 'mockAmount', { value: 'mockAmount' }, - ]) - }) + ]); + }); it('should dispatch a sign action if sendToken is not defined', function () { - utilsStubs.constructTxParams.resetHistory() + utilsStubs.constructTxParams.resetHistory(); mapDispatchToPropsObject.sign({ to: 'mockTo', amount: 'mockAmount', from: 'mockFrom', gas: 'mockGas', gasPrice: 'mockGasPrice', - }) - assert(dispatchSpy.calledOnce) + }); + assert(dispatchSpy.calledOnce); assert.deepStrictEqual( utilsStubs.constructTxParams.getCall(0).args[0], { @@ -125,12 +125,12 @@ describe('send-footer container', function () { gas: 'mockGas', gasPrice: 'mockGasPrice', }, - ) + ); assert.deepStrictEqual(actionSpies.signTx.getCall(0).args, [ { value: 'mockAmount' }, - ]) - }) - }) + ]); + }); + }); describe('update()', function () { it('should dispatch an updateTransaction action', function () { @@ -143,8 +143,8 @@ describe('send-footer container', function () { editingTransactionId: 'mockEditingTransactionId', sendToken: { address: 'mockAddress' }, unapprovedTxs: 'mockUnapprovedTxs', - }) - assert(dispatchSpy.calledOnce) + }); + assert(dispatchSpy.calledOnce); assert.deepStrictEqual( utilsStubs.constructUpdatedTx.getCall(0).args[0], { @@ -158,13 +158,13 @@ describe('send-footer container', function () { sendToken: { address: 'mockAddress' }, unapprovedTxs: 'mockUnapprovedTxs', }, - ) + ); assert.strictEqual( actionSpies.updateTransaction.getCall(0).args[0], 'mockConstructedUpdatedTxParams', - ) - }) - }) + ); + }); + }); describe('addToAddressBookIfNew()', function () { it('should dispatch an action', function () { @@ -172,17 +172,17 @@ describe('send-footer container', function () { 'mockNewAddress', 'mockToAccounts', 'mockNickname', - ) - assert(dispatchSpy.calledOnce) + ); + assert(dispatchSpy.calledOnce); assert.strictEqual( utilsStubs.addressIsNew.getCall(0).args[0], 'mockToAccounts', - ) + ); assert.deepStrictEqual(actionSpies.addToAddressBook.getCall(0).args, [ '0xmockNewAddress', 'mockNickname', - ]) - }) - }) - }) -}) + ]); + }); + }); + }); +}); diff --git a/ui/app/pages/send/send-footer/tests/send-footer-utils.test.js b/ui/app/pages/send/send-footer/tests/send-footer-utils.test.js index 52a84a993..9d7507f57 100644 --- a/ui/app/pages/send/send-footer/tests/send-footer-utils.test.js +++ b/ui/app/pages/send/send-footer/tests/send-footer-utils.test.js @@ -1,20 +1,20 @@ -import assert from 'assert' -import proxyquire from 'proxyquire' -import sinon from 'sinon' -import { TOKEN_TRANSFER_FUNCTION_SIGNATURE } from '../../send.constants' +import assert from 'assert'; +import proxyquire from 'proxyquire'; +import sinon from 'sinon'; +import { TOKEN_TRANSFER_FUNCTION_SIGNATURE } from '../../send.constants'; const stubs = { rawEncode: sinon.stub().callsFake((arr1, arr2) => { - return [...arr1, ...arr2] + return [...arr1, ...arr2]; }), -} +}; const sendUtils = proxyquire('../send-footer.utils.js', { 'ethereumjs-abi': { rawEncode: stubs.rawEncode, }, -}) -const { addressIsNew, constructTxParams, constructUpdatedTx } = sendUtils +}); +const { addressIsNew, constructTxParams, constructUpdatedTx } = sendUtils; describe('send-footer utils', function () { describe('addressIsNew()', function () { @@ -25,8 +25,8 @@ describe('send-footer utils', function () { '0xdef', ), false, - ) - }) + ); + }); it('should return true if the address does not exists in toAccounts', function () { assert.strictEqual( @@ -35,9 +35,9 @@ describe('send-footer utils', function () { '0xxyz', ), true, - ) - }) - }) + ); + }); + }); describe('constructTxParams()', function () { it('should return a new txParams object with data if there data is given', function () { @@ -59,8 +59,8 @@ describe('send-footer utils', function () { gas: '0xmockGas', gasPrice: '0xmockGasPrice', }, - ) - }) + ); + }); it('should return a new txParams object with value and to properties if there is no sendToken', function () { assert.deepStrictEqual( @@ -80,8 +80,8 @@ describe('send-footer utils', function () { gas: '0xmockGas', gasPrice: '0xmockGasPrice', }, - ) - }) + ); + }); it('should return a new txParams object without a to property and a 0 value if there is a sendToken', function () { assert.deepStrictEqual( @@ -100,9 +100,9 @@ describe('send-footer utils', function () { gas: '0xmockGas', gasPrice: '0xmockGasPrice', }, - ) - }) - }) + ); + }); + }); describe('constructUpdatedTx()', function () { it('should return a new object with an updated txParams', function () { @@ -123,7 +123,7 @@ describe('send-footer utils', function () { }, }, }, - }) + }); assert.deepStrictEqual(result, { unapprovedTxParam: 'someOtherParam', txParams: { @@ -134,8 +134,8 @@ describe('send-footer utils', function () { to: '0xmockTo', data: '0xsomeData', }, - }) - }) + }); + }); it('should not have data property if there is non in the original tx', function () { const result = constructUpdatedTx({ @@ -157,7 +157,7 @@ describe('send-footer utils', function () { }, }, }, - }) + }); assert.deepStrictEqual(result, { unapprovedTxParam: 'someOtherParam', @@ -168,8 +168,8 @@ describe('send-footer utils', function () { value: '0xmockAmount', to: '0xmockTo', }, - }) - }) + }); + }); it('should have token property values if sendToken is truthy', function () { const result = constructUpdatedTx({ @@ -189,7 +189,7 @@ describe('send-footer utils', function () { txParams: {}, }, }, - }) + }); assert.deepStrictEqual(result, { unapprovedTxParam: 'someOtherParam', @@ -201,7 +201,7 @@ describe('send-footer utils', function () { to: '0xmockTokenAddress', data: `${TOKEN_TRANSFER_FUNCTION_SIGNATURE}ss56Tont`, }, - }) - }) - }) -}) + }); + }); + }); +}); diff --git a/ui/app/pages/send/send-header/index.js b/ui/app/pages/send/send-header/index.js index 0b17f0b7d..cfb482303 100644 --- a/ui/app/pages/send/send-header/index.js +++ b/ui/app/pages/send/send-header/index.js @@ -1 +1 @@ -export { default } from './send-header.container' +export { default } from './send-header.container'; diff --git a/ui/app/pages/send/send-header/send-header.component.js b/ui/app/pages/send/send-header/send-header.component.js index 2f69883c5..303ef4c7a 100644 --- a/ui/app/pages/send/send-header/send-header.component.js +++ b/ui/app/pages/send/send-header/send-header.component.js @@ -1,6 +1,6 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import PageContainerHeader from '../../../components/ui/page-container/page-container-header' +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import PageContainerHeader from '../../../components/ui/page-container/page-container-header'; export default class SendHeader extends Component { static propTypes = { @@ -8,16 +8,16 @@ export default class SendHeader extends Component { history: PropTypes.object, mostRecentOverviewPage: PropTypes.string, titleKey: PropTypes.string, - } + }; static contextTypes = { t: PropTypes.func, - } + }; onClose() { - const { clearSend, history, mostRecentOverviewPage } = this.props - clearSend() - history.push(mostRecentOverviewPage) + const { clearSend, history, mostRecentOverviewPage } = this.props; + clearSend(); + history.push(mostRecentOverviewPage); } render() { @@ -28,6 +28,6 @@ export default class SendHeader extends Component { title={this.context.t(this.props.titleKey)} headerCloseText={this.context.t('cancel')} /> - ) + ); } } diff --git a/ui/app/pages/send/send-header/send-header.container.js b/ui/app/pages/send/send-header/send-header.container.js index be805b55a..9f67cb2af 100644 --- a/ui/app/pages/send/send-header/send-header.container.js +++ b/ui/app/pages/send/send-header/send-header.container.js @@ -1,20 +1,20 @@ -import { connect } from 'react-redux' -import { clearSend } from '../../../store/actions' -import { getTitleKey } from '../../../selectors' -import { getMostRecentOverviewPage } from '../../../ducks/history/history' -import SendHeader from './send-header.component' +import { connect } from 'react-redux'; +import { clearSend } from '../../../store/actions'; +import { getTitleKey } from '../../../selectors'; +import { getMostRecentOverviewPage } from '../../../ducks/history/history'; +import SendHeader from './send-header.component'; -export default connect(mapStateToProps, mapDispatchToProps)(SendHeader) +export default connect(mapStateToProps, mapDispatchToProps)(SendHeader); function mapStateToProps(state) { return { mostRecentOverviewPage: getMostRecentOverviewPage(state), titleKey: getTitleKey(state), - } + }; } function mapDispatchToProps(dispatch) { return { clearSend: () => dispatch(clearSend()), - } + }; } diff --git a/ui/app/pages/send/send-header/tests/send-header-component.test.js b/ui/app/pages/send/send-header/tests/send-header-component.test.js index 03168bed1..14cde996a 100644 --- a/ui/app/pages/send/send-header/tests/send-header-component.test.js +++ b/ui/app/pages/send/send-header/tests/send-header-component.test.js @@ -1,23 +1,23 @@ -import assert from 'assert' -import React from 'react' -import { shallow } from 'enzyme' -import sinon from 'sinon' -import SendHeader from '../send-header.component' -import PageContainerHeader from '../../../../components/ui/page-container/page-container-header' +import assert from 'assert'; +import React from 'react'; +import { shallow } from 'enzyme'; +import sinon from 'sinon'; +import SendHeader from '../send-header.component'; +import PageContainerHeader from '../../../../components/ui/page-container/page-container-header'; describe('SendHeader Component', function () { - let wrapper + let wrapper; const propsMethodSpies = { clearSend: sinon.spy(), - } + }; const historySpies = { push: sinon.spy(), - } + }; before(function () { - sinon.spy(SendHeader.prototype, 'onClose') - }) + sinon.spy(SendHeader.prototype, 'onClose'); + }); beforeEach(function () { wrapper = shallow( @@ -28,48 +28,48 @@ describe('SendHeader Component', function () { titleKey="mockTitleKey" />, { context: { t: (str1, str2) => (str2 ? str1 + str2 : str1) } }, - ) - }) + ); + }); afterEach(function () { - propsMethodSpies.clearSend.resetHistory() - historySpies.push.resetHistory() - SendHeader.prototype.onClose.resetHistory() - }) + propsMethodSpies.clearSend.resetHistory(); + historySpies.push.resetHistory(); + SendHeader.prototype.onClose.resetHistory(); + }); after(function () { - sinon.restore() - }) + sinon.restore(); + }); describe('onClose', function () { it('should call clearSend', function () { - assert.strictEqual(propsMethodSpies.clearSend.callCount, 0) - wrapper.instance().onClose() - assert.strictEqual(propsMethodSpies.clearSend.callCount, 1) - }) + assert.strictEqual(propsMethodSpies.clearSend.callCount, 0); + wrapper.instance().onClose(); + assert.strictEqual(propsMethodSpies.clearSend.callCount, 1); + }); it('should call history.push', function () { - assert.strictEqual(historySpies.push.callCount, 0) - wrapper.instance().onClose() - assert.strictEqual(historySpies.push.callCount, 1) + assert.strictEqual(historySpies.push.callCount, 0); + wrapper.instance().onClose(); + assert.strictEqual(historySpies.push.callCount, 1); assert.strictEqual( historySpies.push.getCall(0).args[0], 'mostRecentOverviewPage', - ) - }) - }) + ); + }); + }); describe('render', function () { it('should render a PageContainerHeader component', function () { - assert.strictEqual(wrapper.find(PageContainerHeader).length, 1) - }) + assert.strictEqual(wrapper.find(PageContainerHeader).length, 1); + }); it('should pass the correct props to PageContainerHeader', function () { - const { onClose, title } = wrapper.find(PageContainerHeader).props() - assert.strictEqual(title, 'mockTitleKey') - assert.strictEqual(SendHeader.prototype.onClose.callCount, 0) - onClose() - assert.strictEqual(SendHeader.prototype.onClose.callCount, 1) - }) - }) -}) + const { onClose, title } = wrapper.find(PageContainerHeader).props(); + assert.strictEqual(title, 'mockTitleKey'); + assert.strictEqual(SendHeader.prototype.onClose.callCount, 0); + onClose(); + assert.strictEqual(SendHeader.prototype.onClose.callCount, 1); + }); + }); +}); diff --git a/ui/app/pages/send/send.component.js b/ui/app/pages/send/send.component.js index 31540e312..74d4f86f4 100644 --- a/ui/app/pages/send/send.component.js +++ b/ui/app/pages/send/send.component.js @@ -1,23 +1,23 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import ethUtil from 'ethereumjs-util' -import { debounce } from 'lodash' +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import ethUtil from 'ethereumjs-util'; +import { debounce } from 'lodash'; import { getAmountErrorObject, getGasFeeErrorObject, getToAddressForGasUpdate, doesAmountErrorRequireUpdate, -} from './send.utils' +} from './send.utils'; import { getToWarningObject, getToErrorObject, -} from './send-content/add-recipient/add-recipient' -import SendHeader from './send-header' -import AddRecipient from './send-content/add-recipient' -import SendContent from './send-content' -import SendFooter from './send-footer' -import EnsInput from './send-content/add-recipient/ens-input' -import { INVALID_RECIPIENT_ADDRESS_ERROR } from './send.constants' +} from './send-content/add-recipient/add-recipient'; +import SendHeader from './send-header'; +import AddRecipient from './send-content/add-recipient'; +import SendContent from './send-content'; +import SendFooter from './send-footer'; +import EnsInput from './send-content/add-recipient/ens-input'; +import { INVALID_RECIPIENT_ADDRESS_ERROR } from './send.constants'; export default class SendTransactionScreen extends Component { static propTypes = { @@ -54,23 +54,23 @@ export default class SendTransactionScreen extends Component { scanQrCode: PropTypes.func.isRequired, qrCodeDetected: PropTypes.func.isRequired, qrCodeData: PropTypes.object, - } + }; static contextTypes = { t: PropTypes.func, metricsEvent: PropTypes.func, - } + }; state = { query: '', toError: null, toWarning: null, internalSearch: false, - } + }; constructor(props) { - super(props) - this.dValidate = debounce(this.validate, 1000) + super(props); + this.dValidate = debounce(this.validate, 1000); } componentDidUpdate(prevProps) { @@ -93,9 +93,9 @@ export default class SendTransactionScreen extends Component { updateToNicknameIfNecessary, qrCodeData, qrCodeDetected, - } = this.props + } = this.props; - let updateGas = false + let updateGas = false; const { from: { balance: prevBalance }, gasTotal: prevGasTotal, @@ -103,9 +103,9 @@ export default class SendTransactionScreen extends Component { network: prevNetwork, sendToken: prevSendToken, to: prevTo, - } = prevProps + } = prevProps; - const uninitialized = [prevBalance, prevGasTotal].every((n) => n === null) + const uninitialized = [prevBalance, prevGasTotal].every((n) => n === null); const amountErrorRequiresUpdate = doesAmountErrorRequireUpdate({ balance, @@ -115,7 +115,7 @@ export default class SendTransactionScreen extends Component { prevTokenBalance, sendToken, tokenBalance, - }) + }); if (amountErrorRequiresUpdate) { const amountErrorObject = getAmountErrorObject({ @@ -126,7 +126,7 @@ export default class SendTransactionScreen extends Component { primaryCurrency, sendToken, tokenBalance, - }) + }); const gasFeeErrorObject = sendToken ? getGasFeeErrorObject({ balance, @@ -135,8 +135,8 @@ export default class SendTransactionScreen extends Component { primaryCurrency, sendToken, }) - : { gasFee: null } - updateSendErrors(Object.assign(amountErrorObject, gasFeeErrorObject)) + : { gasFee: null }; + updateSendErrors(Object.assign(amountErrorObject, gasFeeErrorObject)); } if (!uninitialized) { @@ -145,110 +145,110 @@ export default class SendTransactionScreen extends Component { sendToken, tokenContract, address, - }) - updateToNicknameIfNecessary(to, toNickname, addressBook) - updateGas = true + }); + updateToNicknameIfNecessary(to, toNickname, addressBook); + updateGas = true; } } - const prevTokenAddress = prevSendToken && prevSendToken.address - const sendTokenAddress = sendToken && sendToken.address + const prevTokenAddress = prevSendToken && prevSendToken.address; + const sendTokenAddress = sendToken && sendToken.address; if (sendTokenAddress && prevTokenAddress !== sendTokenAddress) { - this.updateSendToken() - this.validate(this.state.query) - updateGas = true + this.updateSendToken(); + this.validate(this.state.query); + updateGas = true; } - let scannedAddress + let scannedAddress; if (qrCodeData) { if (qrCodeData.type === 'address') { - scannedAddress = qrCodeData.values.address.toLowerCase() + scannedAddress = qrCodeData.values.address.toLowerCase(); if (ethUtil.isValidAddress(scannedAddress)) { - const currentAddress = prevTo?.toLowerCase() + const currentAddress = prevTo?.toLowerCase(); if (currentAddress !== scannedAddress) { - updateSendTo(scannedAddress) - updateGas = true + updateSendTo(scannedAddress); + updateGas = true; // Clean up QR code data after handling - qrCodeDetected(null) + qrCodeDetected(null); } } else { - scannedAddress = null - qrCodeDetected(null) - this.setState({ toError: INVALID_RECIPIENT_ADDRESS_ERROR }) + scannedAddress = null; + qrCodeDetected(null); + this.setState({ toError: INVALID_RECIPIENT_ADDRESS_ERROR }); } } } if (updateGas) { if (scannedAddress) { - this.updateGas({ to: scannedAddress }) + this.updateGas({ to: scannedAddress }); } else { - this.updateGas() + this.updateGas(); } } } componentDidMount() { this.props.fetchBasicGasEstimates().then(() => { - this.updateGas() - }) + this.updateGas(); + }); } UNSAFE_componentWillMount() { - this.updateSendToken() + this.updateSendToken(); // Show QR Scanner modal if ?scan=true if (window.location.search === '?scan=true') { - this.props.scanQrCode() + this.props.scanQrCode(); // Clear the queryString param after showing the modal - const cleanUrl = window.location.href.split('?')[0] - window.history.pushState({}, null, `${cleanUrl}`) - window.location.hash = '#send' + const cleanUrl = window.location.href.split('?')[0]; + window.history.pushState({}, null, `${cleanUrl}`); + window.location.hash = '#send'; } } componentWillUnmount() { - this.props.resetSendState() + this.props.resetSendState(); } onRecipientInputChange = (query) => { - const { internalSearch } = this.state + const { internalSearch } = this.state; if (!internalSearch) { if (query) { - this.dValidate(query) + this.dValidate(query); } else { - this.dValidate.cancel() - this.validate(query) + this.dValidate.cancel(); + this.validate(query); } } - this.setState({ query }) - } + this.setState({ query }); + }; setInternalSearch(internalSearch) { - this.setState({ query: '', internalSearch }) + this.setState({ query: '', internalSearch }); } validate(query) { - const { hasHexData, tokens, sendToken, network } = this.props + const { hasHexData, tokens, sendToken, network } = this.props; - const { internalSearch } = this.state + const { internalSearch } = this.state; if (!query || internalSearch) { - this.setState({ toError: '', toWarning: '' }) - return + this.setState({ toError: '', toWarning: '' }); + return; } - const toErrorObject = getToErrorObject(query, hasHexData, network) - const toWarningObject = getToWarningObject(query, tokens, sendToken) + const toErrorObject = getToErrorObject(query, hasHexData, network); + const toWarningObject = getToWarningObject(query, tokens, sendToken); this.setState({ toError: toErrorObject.to, toWarning: toWarningObject.to, - }) + }); } updateSendToken() { @@ -257,13 +257,13 @@ export default class SendTransactionScreen extends Component { sendToken, tokenContract, updateSendTokenBalance, - } = this.props + } = this.props; updateSendTokenBalance({ sendToken, tokenContract, address, - }) + }); } updateGas({ to: updatedToAddress, amount: value, data } = {}) { @@ -277,7 +277,7 @@ export default class SendTransactionScreen extends Component { sendToken, to: currentToAddress, updateAndSetGasLimit, - } = this.props + } = this.props; updateAndSetGasLimit({ blockGasLimit, @@ -289,17 +289,17 @@ export default class SendTransactionScreen extends Component { to: getToAddressForGasUpdate(updatedToAddress, currentToAddress), value: value || amount, data, - }) + }); } render() { - const { history, to } = this.props - let content + const { history, to } = this.props; + let content; if (to) { - content = this.renderSendContent() + content = this.renderSendContent(); } else { - content = this.renderAddRecipient() + content = this.renderAddRecipient(); } return ( @@ -308,11 +308,11 @@ export default class SendTransactionScreen extends Component { {this.renderInput()} {content} - ) + ); } renderInput() { - const { internalSearch } = this.state + const { internalSearch } = this.state; return ( this.props.updateSendTo(address, '')} onPaste={(text) => { - this.props.updateSendTo(text) && this.updateGas() + this.props.updateSendTo(text) && this.updateGas(); }} onReset={() => this.props.updateSendTo('', '')} updateEnsResolution={this.props.updateSendEnsResolution} updateEnsResolutionError={this.props.updateSendEnsResolutionError} internalSearch={internalSearch} /> - ) + ); } renderAddRecipient() { - const { toError } = this.state + const { toError } = this.state; return ( @@ -352,12 +352,12 @@ export default class SendTransactionScreen extends Component { this.setInternalSearch(internalSearch) } /> - ) + ); } renderSendContent() { - const { history, showHexData } = this.props - const { toWarning } = this.state + const { history, showHexData } = this.props; + const { toWarning } = this.state; return [ , , - ] + ]; } } diff --git a/ui/app/pages/send/send.constants.js b/ui/app/pages/send/send.constants.js index 2f989bc37..7b1a1f1a3 100644 --- a/ui/app/pages/send/send.constants.js +++ b/ui/app/pages/send/send.constants.js @@ -1,13 +1,13 @@ import { conversionUtil, multiplyCurrencies, -} from '../../helpers/utils/conversion-util' -import { addHexPrefix } from '../../../../app/scripts/lib/util' +} from '../../helpers/utils/conversion-util'; +import { addHexPrefix } from '../../../../app/scripts/lib/util'; -const MIN_GAS_PRICE_DEC = '0' -const MIN_GAS_PRICE_HEX = parseInt(MIN_GAS_PRICE_DEC, 10).toString(16) -const MIN_GAS_LIMIT_DEC = '21000' -const MIN_GAS_LIMIT_HEX = parseInt(MIN_GAS_LIMIT_DEC, 10).toString(16) +const MIN_GAS_PRICE_DEC = '0'; +const MIN_GAS_PRICE_HEX = parseInt(MIN_GAS_PRICE_DEC, 10).toString(16); +const MIN_GAS_LIMIT_DEC = '21000'; +const MIN_GAS_LIMIT_HEX = parseInt(MIN_GAS_LIMIT_DEC, 10).toString(16); const MIN_GAS_PRICE_GWEI = addHexPrefix( conversionUtil(MIN_GAS_PRICE_HEX, { @@ -17,27 +17,27 @@ const MIN_GAS_PRICE_GWEI = addHexPrefix( toNumericBase: 'hex', numberOfDecimals: 1, }), -) +); const MIN_GAS_TOTAL = multiplyCurrencies(MIN_GAS_LIMIT_HEX, MIN_GAS_PRICE_HEX, { toNumericBase: 'hex', multiplicandBase: 16, multiplierBase: 16, -}) +}); -const TOKEN_TRANSFER_FUNCTION_SIGNATURE = '0xa9059cbb' +const TOKEN_TRANSFER_FUNCTION_SIGNATURE = '0xa9059cbb'; -const INSUFFICIENT_FUNDS_ERROR = 'insufficientFunds' -const INSUFFICIENT_TOKENS_ERROR = 'insufficientTokens' -const NEGATIVE_ETH_ERROR = 'negativeETH' -const INVALID_RECIPIENT_ADDRESS_ERROR = 'invalidAddressRecipient' +const INSUFFICIENT_FUNDS_ERROR = 'insufficientFunds'; +const INSUFFICIENT_TOKENS_ERROR = 'insufficientTokens'; +const NEGATIVE_ETH_ERROR = 'negativeETH'; +const INVALID_RECIPIENT_ADDRESS_ERROR = 'invalidAddressRecipient'; const INVALID_RECIPIENT_ADDRESS_NOT_ETH_NETWORK_ERROR = - 'invalidAddressRecipientNotEthNetwork' -const REQUIRED_ERROR = 'required' -const KNOWN_RECIPIENT_ADDRESS_ERROR = 'knownAddressRecipient' + 'invalidAddressRecipientNotEthNetwork'; +const REQUIRED_ERROR = 'required'; +const KNOWN_RECIPIENT_ADDRESS_ERROR = 'knownAddressRecipient'; -const SIMPLE_GAS_COST = '0x5208' // Hex for 21000, cost of a simple send. -const BASE_TOKEN_GAS_COST = '0x186a0' // Hex for 100000, a base estimate for token transfers. +const SIMPLE_GAS_COST = '0x5208'; // Hex for 21000, cost of a simple send. +const BASE_TOKEN_GAS_COST = '0x186a0'; // Hex for 100000, a base estimate for token transfers. export { INSUFFICIENT_FUNDS_ERROR, @@ -56,4 +56,4 @@ export { SIMPLE_GAS_COST, TOKEN_TRANSFER_FUNCTION_SIGNATURE, BASE_TOKEN_GAS_COST, -} +}; diff --git a/ui/app/pages/send/send.container.js b/ui/app/pages/send/send.container.js index 0d9fe9219..c460b4526 100644 --- a/ui/app/pages/send/send.container.js +++ b/ui/app/pages/send/send.container.js @@ -1,6 +1,6 @@ -import { connect } from 'react-redux' -import { withRouter } from 'react-router-dom' -import { compose } from 'redux' +import { connect } from 'react-redux'; +import { withRouter } from 'react-router-dom'; +import { compose } from 'redux'; import { getBlockGasLimit, @@ -22,7 +22,7 @@ import { getQrCodeData, getSelectedAddress, getAddressBook, -} from '../../selectors' +} from '../../selectors'; import { updateSendTo, @@ -33,16 +33,16 @@ import { qrCodeDetected, updateSendEnsResolution, updateSendEnsResolutionError, -} from '../../store/actions' -import { resetSendState, updateSendErrors } from '../../ducks/send/send.duck' -import { fetchBasicGasEstimates } from '../../ducks/gas/gas.duck' -import { getTokens } from '../../ducks/metamask/metamask' -import { isValidDomainName } from '../../helpers/utils/util' -import { calcGasTotal } from './send.utils' -import SendEther from './send.component' +} from '../../store/actions'; +import { resetSendState, updateSendErrors } from '../../ducks/send/send.duck'; +import { fetchBasicGasEstimates } from '../../ducks/gas/gas.duck'; +import { getTokens } from '../../ducks/metamask/metamask'; +import { isValidDomainName } from '../../helpers/utils/util'; +import { calcGasTotal } from './send.utils'; +import SendEther from './send.component'; function mapStateToProps(state) { - const editingTransactionId = getSendEditingTransactionId(state) + const editingTransactionId = getSendEditingTransactionId(state); return { addressBook: getAddressBook(state), @@ -65,7 +65,7 @@ function mapStateToProps(state) { tokens: getTokens(state), tokenBalance: getTokenBalance(state), tokenContract: getSendTokenContract(state), - } + }; } function mapDispatchToProps(dispatch) { @@ -93,7 +93,7 @@ function mapDispatchToProps(dispatch) { value, data, }), - ) + ); }, updateSendTokenBalance: ({ sendToken, tokenContract, address }) => { dispatch( @@ -102,7 +102,7 @@ function mapDispatchToProps(dispatch) { tokenContract, address, }), - ) + ); }, updateSendErrors: (newError) => dispatch(updateSendErrors(newError)), resetSendState: () => dispatch(resetSendState()), @@ -117,16 +117,16 @@ function mapDispatchToProps(dispatch) { updateToNicknameIfNecessary: (to, toNickname, addressBook) => { if (isValidDomainName(toNickname)) { const addressBookEntry = - addressBook.find(({ address }) => to === address) || {} + addressBook.find(({ address }) => to === address) || {}; if (!addressBookEntry.name !== toNickname) { - dispatch(updateSendTo(to, addressBookEntry.name || '')) + dispatch(updateSendTo(to, addressBookEntry.name || '')); } } }, - } + }; } export default compose( withRouter, connect(mapStateToProps, mapDispatchToProps), -)(SendEther) +)(SendEther); diff --git a/ui/app/pages/send/send.utils.js b/ui/app/pages/send/send.utils.js index 08daeb6ab..ffe76241d 100644 --- a/ui/app/pages/send/send.utils.js +++ b/ui/app/pages/send/send.utils.js @@ -1,4 +1,4 @@ -import abi from 'ethereumjs-abi' +import abi from 'ethereumjs-abi'; import { addCurrencies, conversionUtil, @@ -6,10 +6,10 @@ import { multiplyCurrencies, conversionGreaterThan, conversionLessThan, -} from '../../helpers/utils/conversion-util' +} from '../../helpers/utils/conversion-util'; -import { calcTokenAmount } from '../../helpers/utils/token-util' -import { addHexPrefix } from '../../../../app/scripts/lib/util' +import { calcTokenAmount } from '../../helpers/utils/token-util'; +import { addHexPrefix } from '../../../../app/scripts/lib/util'; import { BASE_TOKEN_GAS_COST, @@ -19,7 +19,7 @@ import { NEGATIVE_ETH_ERROR, SIMPLE_GAS_COST, TOKEN_TRANSFER_FUNCTION_SIGNATURE, -} from './send.constants' +} from './send.constants'; export { addGasBuffer, @@ -35,14 +35,14 @@ export { isTokenBalanceSufficient, removeLeadingZeroes, ellipsify, -} +}; function calcGasTotal(gasLimit = '0', gasPrice = '0') { return multiplyCurrencies(gasLimit, gasPrice, { toNumericBase: 'hex', multiplicandBase: 16, multiplierBase: 16, - }) + }); } function isBalanceSufficient({ @@ -56,7 +56,7 @@ function isBalanceSufficient({ aBase: 16, bBase: 16, toNumericBase: 'hex', - }) + }); const balanceIsSufficient = conversionGTE( { @@ -71,15 +71,15 @@ function isBalanceSufficient({ conversionRate, fromCurrency: primaryCurrency, }, - ) + ); - return balanceIsSufficient + return balanceIsSufficient; } function isTokenBalanceSufficient({ amount = '0x0', tokenBalance, decimals }) { const amountInDec = conversionUtil(amount, { fromNumericBase: 'hex', - }) + }); const tokenBalanceIsSufficient = conversionGTE( { @@ -89,9 +89,9 @@ function isTokenBalanceSufficient({ amount = '0x0', tokenBalance, decimals }) { { value: calcTokenAmount(amountInDec, decimals), }, - ) + ); - return tokenBalanceIsSufficient + return tokenBalanceIsSufficient; } function getAmountErrorObject({ @@ -103,7 +103,7 @@ function getAmountErrorObject({ sendToken, tokenBalance, }) { - let insufficientFunds = false + let insufficientFunds = false; if (gasTotal && conversionRate && !sendToken) { insufficientFunds = !isBalanceSufficient({ amount, @@ -111,35 +111,35 @@ function getAmountErrorObject({ conversionRate, gasTotal, primaryCurrency, - }) + }); } - let inSufficientTokens = false + let inSufficientTokens = false; if (sendToken && tokenBalance !== null) { - const { decimals } = sendToken + const { decimals } = sendToken; inSufficientTokens = !isTokenBalanceSufficient({ tokenBalance, amount, decimals, - }) + }); } const amountLessThanZero = conversionGreaterThan( { value: 0, fromNumericBase: 'dec' }, { value: amount, fromNumericBase: 'hex' }, - ) + ); - let amountError = null + let amountError = null; if (insufficientFunds) { - amountError = INSUFFICIENT_FUNDS_ERROR + amountError = INSUFFICIENT_FUNDS_ERROR; } else if (inSufficientTokens) { - amountError = INSUFFICIENT_TOKENS_ERROR + amountError = INSUFFICIENT_TOKENS_ERROR; } else if (amountLessThanZero) { - amountError = NEGATIVE_ETH_ERROR + amountError = NEGATIVE_ETH_ERROR; } - return { amount: amountError } + return { amount: amountError }; } function getGasFeeErrorObject({ @@ -148,7 +148,7 @@ function getGasFeeErrorObject({ gasTotal, primaryCurrency, }) { - let gasFeeError = null + let gasFeeError = null; if (gasTotal && conversionRate) { const insufficientFunds = !isBalanceSufficient({ @@ -157,19 +157,19 @@ function getGasFeeErrorObject({ conversionRate, gasTotal, primaryCurrency, - }) + }); if (insufficientFunds) { - gasFeeError = INSUFFICIENT_FUNDS_ERROR + gasFeeError = INSUFFICIENT_FUNDS_ERROR; } } - return { gasFee: gasFeeError } + return { gasFee: gasFeeError }; } function calcTokenBalance({ sendToken, usersToken }) { - const { decimals } = sendToken || {} - return calcTokenAmount(usersToken.balance.toString(), decimals).toString(16) + const { decimals } = sendToken || {}; + return calcTokenAmount(usersToken.balance.toString(), decimals).toString(16); } function doesAmountErrorRequireUpdate({ @@ -181,13 +181,13 @@ function doesAmountErrorRequireUpdate({ sendToken, tokenBalance, }) { - const balanceHasChanged = balance !== prevBalance - const gasTotalHasChange = gasTotal !== prevGasTotal - const tokenBalanceHasChanged = sendToken && tokenBalance !== prevTokenBalance + const balanceHasChanged = balance !== prevBalance; + const gasTotalHasChange = gasTotal !== prevGasTotal; + const tokenBalanceHasChanged = sendToken && tokenBalance !== prevTokenBalance; const amountErrorRequiresUpdate = - balanceHasChanged || gasTotalHasChange || tokenBalanceHasChanged + balanceHasChanged || gasTotalHasChange || tokenBalanceHasChanged; - return amountErrorRequiresUpdate + return amountErrorRequiresUpdate; } async function estimateGasForSend({ @@ -200,46 +200,46 @@ async function estimateGasForSend({ gasPrice, estimateGasMethod, }) { - const paramsForGasEstimate = { from: selectedAddress, value, gasPrice } + const paramsForGasEstimate = { from: selectedAddress, value, gasPrice }; // if recipient has no code, gas is 21k max: if (!sendToken && !data) { - const code = Boolean(to) && (await global.eth.getCode(to)) + const code = Boolean(to) && (await global.eth.getCode(to)); // Geth will return '0x', and ganache-core v2.2.1 will return '0x0' - const codeIsEmpty = !code || code === '0x' || code === '0x0' + const codeIsEmpty = !code || code === '0x' || code === '0x0'; if (codeIsEmpty) { - return SIMPLE_GAS_COST + return SIMPLE_GAS_COST; } } else if (sendToken && !to) { - return BASE_TOKEN_GAS_COST + return BASE_TOKEN_GAS_COST; } if (sendToken) { - paramsForGasEstimate.value = '0x0' + paramsForGasEstimate.value = '0x0'; paramsForGasEstimate.data = generateTokenTransferData({ toAddress: to, amount: value, sendToken, - }) - paramsForGasEstimate.to = sendToken.address + }); + paramsForGasEstimate.to = sendToken.address; } else { if (data) { - paramsForGasEstimate.data = data + paramsForGasEstimate.data = data; } if (to) { - paramsForGasEstimate.to = to + paramsForGasEstimate.to = to; } if (!value || value === '0') { - paramsForGasEstimate.value = '0xff' + paramsForGasEstimate.value = '0xff'; } } // if not, fall back to block gasLimit if (!blockGasLimit) { // eslint-disable-next-line no-param-reassign - blockGasLimit = MIN_GAS_LIMIT_HEX + blockGasLimit = MIN_GAS_LIMIT_HEX; } paramsForGasEstimate.gas = addHexPrefix( @@ -249,32 +249,32 @@ async function estimateGasForSend({ roundDown: '0', toNumericBase: 'hex', }), - ) + ); // run tx try { - const estimatedGas = await estimateGasMethod(paramsForGasEstimate) + const estimatedGas = await estimateGasMethod(paramsForGasEstimate); const estimateWithBuffer = addGasBuffer( estimatedGas.toString(16), blockGasLimit, 1.5, - ) - return addHexPrefix(estimateWithBuffer) + ); + return addHexPrefix(estimateWithBuffer); } catch (error) { const simulationFailed = error.message.includes('Transaction execution error.') || error.message.includes( 'gas required exceeds allowance or always failing transaction', - ) + ); if (simulationFailed) { const estimateWithBuffer = addGasBuffer( paramsForGasEstimate.gas, blockGasLimit, 1.5, - ) - return addHexPrefix(estimateWithBuffer) + ); + return addHexPrefix(estimateWithBuffer); } - throw error + throw error; } } @@ -288,7 +288,7 @@ function addGasBuffer( multiplicandBase: 16, multiplierBase: 10, numberOfDecimals: '0', - }) + }); const bufferedGasLimit = multiplyCurrencies( initialGasLimitHex, bufferMultiplier, @@ -298,7 +298,7 @@ function addGasBuffer( multiplierBase: 10, numberOfDecimals: '0', }, - ) + ); // if initialGasLimit is above blockGasLimit, dont modify it if ( @@ -307,7 +307,7 @@ function addGasBuffer( { value: upperGasLimit, fromNumericBase: 'hex' }, ) ) { - return initialGasLimitHex + return initialGasLimitHex; } // if bufferedGasLimit is below blockGasLimit, use bufferedGasLimit if ( @@ -316,10 +316,10 @@ function addGasBuffer( { value: upperGasLimit, fromNumericBase: 'hex' }, ) ) { - return bufferedGasLimit + return bufferedGasLimit; } // otherwise use blockGasLimit - return upperGasLimit + return upperGasLimit; } function generateTokenTransferData({ @@ -328,7 +328,7 @@ function generateTokenTransferData({ sendToken, }) { if (!sendToken) { - return undefined + return undefined; } return ( TOKEN_TRANSFER_FUNCTION_SIGNATURE + @@ -341,19 +341,19 @@ function generateTokenTransferData({ (x) => `00${x.toString(16)}`.slice(-2), ) .join('') - ) + ); } function getToAddressForGasUpdate(...addresses) { return [...addresses, ''] .find((str) => str !== undefined && str !== null) - .toLowerCase() + .toLowerCase(); } function removeLeadingZeroes(str) { - return str.replace(/^0*(?=\d)/u, '') + return str.replace(/^0*(?=\d)/u, ''); } function ellipsify(text, first = 6, last = 4) { - return `${text.slice(0, first)}...${text.slice(-last)}` + return `${text.slice(0, first)}...${text.slice(-last)}`; } diff --git a/ui/app/pages/send/tests/send-component.test.js b/ui/app/pages/send/tests/send-component.test.js index 458082e7d..9a529d480 100644 --- a/ui/app/pages/send/tests/send-component.test.js +++ b/ui/app/pages/send/tests/send-component.test.js @@ -1,21 +1,21 @@ -import assert from 'assert' -import React from 'react' -import proxyquire from 'proxyquire' -import { shallow } from 'enzyme' -import sinon from 'sinon' -import timeout from '../../../../lib/test-timeout' +import assert from 'assert'; +import React from 'react'; +import proxyquire from 'proxyquire'; +import { shallow } from 'enzyme'; +import sinon from 'sinon'; +import timeout from '../../../../lib/test-timeout'; -import AddRecipient from '../send-content/add-recipient/add-recipient.container' -import SendHeader from '../send-header/send-header.container' -import SendContent from '../send-content/send-content.container' -import SendFooter from '../send-footer/send-footer.container' +import AddRecipient from '../send-content/add-recipient/add-recipient.container'; +import SendHeader from '../send-header/send-header.container'; +import SendContent from '../send-content/send-content.container'; +import SendFooter from '../send-footer/send-footer.container'; describe('Send Component', function () { - let wrapper + let wrapper; const mockBasicGasEstimates = { blockTime: 'mockBlockTime', - } + }; const propsMethodSpies = { updateAndSetGasLimit: sinon.spy(), @@ -27,23 +27,23 @@ describe('Send Component', function () { .returns(Promise.resolve(mockBasicGasEstimates)), fetchGasEstimates: sinon.spy(), updateToNicknameIfNecessary: sinon.spy(), - } + }; const utilsMethodStubs = { getAmountErrorObject: sinon.stub().returns({ amount: 'mockAmountError' }), getGasFeeErrorObject: sinon.stub().returns({ gasFee: 'mockGasFeeError' }), doesAmountErrorRequireUpdate: sinon .stub() .callsFake((obj) => obj.balance !== obj.prevBalance), - } + }; const SendTransactionScreen = proxyquire('../send.component.js', { './send.utils': utilsMethodStubs, - }).default + }).default; before(function () { - sinon.spy(SendTransactionScreen.prototype, 'componentDidMount') - sinon.spy(SendTransactionScreen.prototype, 'updateGas') - }) + sinon.spy(SendTransactionScreen.prototype, 'componentDidMount'); + sinon.spy(SendTransactionScreen.prototype, 'updateGas'); + }); beforeEach(function () { wrapper = shallow( @@ -79,66 +79,72 @@ describe('Send Component', function () { propsMethodSpies.updateToNicknameIfNecessary } />, - ) - }) + ); + }); afterEach(function () { - SendTransactionScreen.prototype.componentDidMount.resetHistory() - SendTransactionScreen.prototype.updateGas.resetHistory() - utilsMethodStubs.doesAmountErrorRequireUpdate.resetHistory() - utilsMethodStubs.getAmountErrorObject.resetHistory() - utilsMethodStubs.getGasFeeErrorObject.resetHistory() - propsMethodSpies.fetchBasicGasEstimates.resetHistory() - propsMethodSpies.updateAndSetGasLimit.resetHistory() - propsMethodSpies.updateSendErrors.resetHistory() - propsMethodSpies.updateSendTokenBalance.resetHistory() - propsMethodSpies.updateToNicknameIfNecessary.resetHistory() - }) + SendTransactionScreen.prototype.componentDidMount.resetHistory(); + SendTransactionScreen.prototype.updateGas.resetHistory(); + utilsMethodStubs.doesAmountErrorRequireUpdate.resetHistory(); + utilsMethodStubs.getAmountErrorObject.resetHistory(); + utilsMethodStubs.getGasFeeErrorObject.resetHistory(); + propsMethodSpies.fetchBasicGasEstimates.resetHistory(); + propsMethodSpies.updateAndSetGasLimit.resetHistory(); + propsMethodSpies.updateSendErrors.resetHistory(); + propsMethodSpies.updateSendTokenBalance.resetHistory(); + propsMethodSpies.updateToNicknameIfNecessary.resetHistory(); + }); after(function () { - sinon.restore() - }) + sinon.restore(); + }); it('should call componentDidMount', function () { - assert(SendTransactionScreen.prototype.componentDidMount.calledOnce) - }) + assert(SendTransactionScreen.prototype.componentDidMount.calledOnce); + }); describe('componentDidMount', function () { it('should call props.fetchBasicGasAndTimeEstimates', function () { - propsMethodSpies.fetchBasicGasEstimates.resetHistory() - assert.strictEqual(propsMethodSpies.fetchBasicGasEstimates.callCount, 0) - wrapper.instance().componentDidMount() - assert.strictEqual(propsMethodSpies.fetchBasicGasEstimates.callCount, 1) - }) + propsMethodSpies.fetchBasicGasEstimates.resetHistory(); + assert.strictEqual(propsMethodSpies.fetchBasicGasEstimates.callCount, 0); + wrapper.instance().componentDidMount(); + assert.strictEqual(propsMethodSpies.fetchBasicGasEstimates.callCount, 1); + }); it('should call this.updateGas', async function () { - SendTransactionScreen.prototype.updateGas.resetHistory() - propsMethodSpies.updateSendErrors.resetHistory() - assert.strictEqual(SendTransactionScreen.prototype.updateGas.callCount, 0) - wrapper.instance().componentDidMount() - await timeout(250) - assert.strictEqual(SendTransactionScreen.prototype.updateGas.callCount, 1) - }) - }) + SendTransactionScreen.prototype.updateGas.resetHistory(); + propsMethodSpies.updateSendErrors.resetHistory(); + assert.strictEqual( + SendTransactionScreen.prototype.updateGas.callCount, + 0, + ); + wrapper.instance().componentDidMount(); + await timeout(250); + assert.strictEqual( + SendTransactionScreen.prototype.updateGas.callCount, + 1, + ); + }); + }); describe('componentWillUnmount', function () { it('should call this.props.resetSendState', function () { - propsMethodSpies.resetSendState.resetHistory() - assert.strictEqual(propsMethodSpies.resetSendState.callCount, 0) - wrapper.instance().componentWillUnmount() - assert.strictEqual(propsMethodSpies.resetSendState.callCount, 1) - }) - }) + propsMethodSpies.resetSendState.resetHistory(); + assert.strictEqual(propsMethodSpies.resetSendState.callCount, 0); + wrapper.instance().componentWillUnmount(); + assert.strictEqual(propsMethodSpies.resetSendState.callCount, 1); + }); + }); describe('componentDidUpdate', function () { it('should call doesAmountErrorRequireUpdate with the expected params', function () { - utilsMethodStubs.getAmountErrorObject.resetHistory() + utilsMethodStubs.getAmountErrorObject.resetHistory(); wrapper.instance().componentDidUpdate({ from: { balance: '', }, - }) - assert(utilsMethodStubs.doesAmountErrorRequireUpdate.calledTwice) + }); + assert(utilsMethodStubs.doesAmountErrorRequireUpdate.calledTwice); assert.deepStrictEqual( utilsMethodStubs.doesAmountErrorRequireUpdate.getCall(0).args[0], { @@ -154,27 +160,27 @@ describe('Send Component', function () { }, tokenBalance: 'mockTokenBalance', }, - ) - }) + ); + }); it('should not call getAmountErrorObject if doesAmountErrorRequireUpdate returns false', function () { - utilsMethodStubs.getAmountErrorObject.resetHistory() + utilsMethodStubs.getAmountErrorObject.resetHistory(); wrapper.instance().componentDidUpdate({ from: { balance: 'mockBalance', }, - }) - assert.strictEqual(utilsMethodStubs.getAmountErrorObject.callCount, 0) - }) + }); + assert.strictEqual(utilsMethodStubs.getAmountErrorObject.callCount, 0); + }); it('should call getAmountErrorObject if doesAmountErrorRequireUpdate returns true', function () { - utilsMethodStubs.getAmountErrorObject.resetHistory() + utilsMethodStubs.getAmountErrorObject.resetHistory(); wrapper.instance().componentDidUpdate({ from: { balance: 'balanceChanged', }, - }) - assert.strictEqual(utilsMethodStubs.getAmountErrorObject.callCount, 1) + }); + assert.strictEqual(utilsMethodStubs.getAmountErrorObject.callCount, 1); assert.deepStrictEqual( utilsMethodStubs.getAmountErrorObject.getCall(0).args[0], { @@ -190,17 +196,17 @@ describe('Send Component', function () { }, tokenBalance: 'mockTokenBalance', }, - ) - }) + ); + }); it('should call getGasFeeErrorObject if doesAmountErrorRequireUpdate returns true and sendToken is truthy', function () { - utilsMethodStubs.getGasFeeErrorObject.resetHistory() + utilsMethodStubs.getGasFeeErrorObject.resetHistory(); wrapper.instance().componentDidUpdate({ from: { balance: 'balanceChanged', }, - }) - assert.strictEqual(utilsMethodStubs.getGasFeeErrorObject.callCount, 1) + }); + assert.strictEqual(utilsMethodStubs.getGasFeeErrorObject.callCount, 1); assert.deepStrictEqual( utilsMethodStubs.getGasFeeErrorObject.getCall(0).args[0], { @@ -214,106 +220,112 @@ describe('Send Component', function () { symbol: 'TST', }, }, - ) - }) + ); + }); it('should not call getGasFeeErrorObject if doesAmountErrorRequireUpdate returns false', function () { - utilsMethodStubs.getGasFeeErrorObject.resetHistory() + utilsMethodStubs.getGasFeeErrorObject.resetHistory(); wrapper.instance().componentDidUpdate({ from: { address: 'mockAddress', balance: 'mockBalance' }, - }) - assert.strictEqual(utilsMethodStubs.getGasFeeErrorObject.callCount, 0) - }) + }); + assert.strictEqual(utilsMethodStubs.getGasFeeErrorObject.callCount, 0); + }); it('should not call getGasFeeErrorObject if doesAmountErrorRequireUpdate returns true but sendToken is falsy', function () { - utilsMethodStubs.getGasFeeErrorObject.resetHistory() - wrapper.setProps({ sendToken: null }) + utilsMethodStubs.getGasFeeErrorObject.resetHistory(); + wrapper.setProps({ sendToken: null }); wrapper.instance().componentDidUpdate({ from: { balance: 'balanceChanged', }, - }) - assert.strictEqual(utilsMethodStubs.getGasFeeErrorObject.callCount, 0) - }) + }); + assert.strictEqual(utilsMethodStubs.getGasFeeErrorObject.callCount, 0); + }); it('should call updateSendErrors with the expected params if sendToken is falsy', function () { - propsMethodSpies.updateSendErrors.resetHistory() - wrapper.setProps({ sendToken: null }) + propsMethodSpies.updateSendErrors.resetHistory(); + wrapper.setProps({ sendToken: null }); wrapper.instance().componentDidUpdate({ from: { balance: 'balanceChanged', }, - }) - assert.strictEqual(propsMethodSpies.updateSendErrors.callCount, 1) + }); + assert.strictEqual(propsMethodSpies.updateSendErrors.callCount, 1); assert.deepStrictEqual( propsMethodSpies.updateSendErrors.getCall(0).args[0], { amount: 'mockAmountError', gasFee: null, }, - ) - }) + ); + }); it('should call updateSendErrors with the expected params if sendToken is truthy', function () { - propsMethodSpies.updateSendErrors.resetHistory() + propsMethodSpies.updateSendErrors.resetHistory(); wrapper.setProps({ sendToken: { address: 'mockTokenAddress', decimals: 18, symbol: 'TST' }, - }) + }); wrapper.instance().componentDidUpdate({ from: { balance: 'balanceChanged', }, - }) - assert.strictEqual(propsMethodSpies.updateSendErrors.callCount, 1) + }); + assert.strictEqual(propsMethodSpies.updateSendErrors.callCount, 1); assert.deepStrictEqual( propsMethodSpies.updateSendErrors.getCall(0).args[0], { amount: 'mockAmountError', gasFee: 'mockGasFeeError', }, - ) - }) + ); + }); it('should not call updateSendTokenBalance or this.updateGas if network === prevNetwork', function () { - SendTransactionScreen.prototype.updateGas.resetHistory() - propsMethodSpies.updateSendTokenBalance.resetHistory() + SendTransactionScreen.prototype.updateGas.resetHistory(); + propsMethodSpies.updateSendTokenBalance.resetHistory(); wrapper.instance().componentDidUpdate({ from: { balance: 'balanceChanged', }, network: '3', sendToken: { address: 'mockTokenAddress', decimals: 18, symbol: 'TST' }, // Make sure not to hit updateGas when changing asset - }) - assert.strictEqual(propsMethodSpies.updateSendTokenBalance.callCount, 0) - assert.strictEqual(SendTransactionScreen.prototype.updateGas.callCount, 0) - }) + }); + assert.strictEqual(propsMethodSpies.updateSendTokenBalance.callCount, 0); + assert.strictEqual( + SendTransactionScreen.prototype.updateGas.callCount, + 0, + ); + }); it('should not call updateSendTokenBalance or this.updateGas if network === loading', function () { - wrapper.setProps({ network: 'loading' }) - SendTransactionScreen.prototype.updateGas.resetHistory() - propsMethodSpies.updateSendTokenBalance.resetHistory() + wrapper.setProps({ network: 'loading' }); + SendTransactionScreen.prototype.updateGas.resetHistory(); + propsMethodSpies.updateSendTokenBalance.resetHistory(); wrapper.instance().componentDidUpdate({ from: { balance: 'balanceChanged', }, network: '3', sendToken: { address: 'mockTokenAddress', decimals: 18, symbol: 'TST' }, // Make sure not to hit updateGas when changing asset - }) - assert.strictEqual(propsMethodSpies.updateSendTokenBalance.callCount, 0) - assert.strictEqual(SendTransactionScreen.prototype.updateGas.callCount, 0) - }) + }); + assert.strictEqual(propsMethodSpies.updateSendTokenBalance.callCount, 0); + assert.strictEqual( + SendTransactionScreen.prototype.updateGas.callCount, + 0, + ); + }); it('should call updateSendTokenBalance and this.updateGas with the correct params', function () { - SendTransactionScreen.prototype.updateGas.resetHistory() - propsMethodSpies.updateSendTokenBalance.resetHistory() + SendTransactionScreen.prototype.updateGas.resetHistory(); + propsMethodSpies.updateSendTokenBalance.resetHistory(); wrapper.instance().componentDidUpdate({ from: { balance: 'balanceChanged', }, network: '2', sendToken: { address: 'mockTokenAddress', decimals: 18, symbol: 'TST' }, // Make sure not to hit updateGas when changing asset - }) - assert.strictEqual(propsMethodSpies.updateSendTokenBalance.callCount, 1) + }); + assert.strictEqual(propsMethodSpies.updateSendTokenBalance.callCount, 1); assert.deepStrictEqual( propsMethodSpies.updateSendTokenBalance.getCall(0).args[0], { @@ -325,37 +337,40 @@ describe('Send Component', function () { tokenContract: { method: 'mockTokenMethod' }, address: 'mockAddress', }, - ) - assert.strictEqual(SendTransactionScreen.prototype.updateGas.callCount, 1) + ); + assert.strictEqual( + SendTransactionScreen.prototype.updateGas.callCount, + 1, + ); assert.deepStrictEqual( SendTransactionScreen.prototype.updateGas.getCall(0).args, [], - ) - }) + ); + }); it('should call updateGas when sendToken.address is changed', function () { - SendTransactionScreen.prototype.updateGas.resetHistory() - propsMethodSpies.updateAndSetGasLimit.resetHistory() + SendTransactionScreen.prototype.updateGas.resetHistory(); + propsMethodSpies.updateAndSetGasLimit.resetHistory(); wrapper.instance().componentDidUpdate({ from: { balance: 'balancedChanged', }, network: '3', // Make sure not to hit updateGas when changing network sendToken: { address: 'newSelectedToken' }, - }) + }); assert.strictEqual( propsMethodSpies.updateToNicknameIfNecessary.callCount, 0, - ) // Network did not change - assert.strictEqual(propsMethodSpies.updateAndSetGasLimit.callCount, 1) - }) - }) + ); // Network did not change + assert.strictEqual(propsMethodSpies.updateAndSetGasLimit.callCount, 1); + }); + }); describe('updateGas', function () { it('should call updateAndSetGasLimit with the correct params if no to prop is passed', function () { - propsMethodSpies.updateAndSetGasLimit.resetHistory() - wrapper.instance().updateGas() - assert.strictEqual(propsMethodSpies.updateAndSetGasLimit.callCount, 1) + propsMethodSpies.updateAndSetGasLimit.resetHistory(); + wrapper.instance().updateGas(); + assert.strictEqual(propsMethodSpies.updateAndSetGasLimit.callCount, 1); assert.deepStrictEqual( propsMethodSpies.updateAndSetGasLimit.getCall(0).args[0], { @@ -373,153 +388,153 @@ describe('Send Component', function () { value: 'mockAmount', data: undefined, }, - ) - }) + ); + }); it('should call updateAndSetGasLimit with the correct params if a to prop is passed', function () { - propsMethodSpies.updateAndSetGasLimit.resetHistory() - wrapper.setProps({ to: 'someAddress' }) - wrapper.instance().updateGas() + propsMethodSpies.updateAndSetGasLimit.resetHistory(); + wrapper.setProps({ to: 'someAddress' }); + wrapper.instance().updateGas(); assert.strictEqual( propsMethodSpies.updateAndSetGasLimit.getCall(0).args[0].to, 'someaddress', - ) - }) + ); + }); it('should call updateAndSetGasLimit with to set to lowercase if passed', function () { - propsMethodSpies.updateAndSetGasLimit.resetHistory() - wrapper.instance().updateGas({ to: '0xABC' }) + propsMethodSpies.updateAndSetGasLimit.resetHistory(); + wrapper.instance().updateGas({ to: '0xABC' }); assert.strictEqual( propsMethodSpies.updateAndSetGasLimit.getCall(0).args[0].to, '0xabc', - ) - }) - }) + ); + }); + }); describe('render', function () { it('should render a page-container class', function () { - assert.strictEqual(wrapper.find('.page-container').length, 1) - }) + assert.strictEqual(wrapper.find('.page-container').length, 1); + }); it('should render SendHeader and AddRecipient', function () { - assert.strictEqual(wrapper.find(SendHeader).length, 1) - assert.strictEqual(wrapper.find(AddRecipient).length, 1) - }) + assert.strictEqual(wrapper.find(SendHeader).length, 1); + assert.strictEqual(wrapper.find(AddRecipient).length, 1); + }); it('should pass the history prop to SendHeader and SendFooter', function () { wrapper.setProps({ to: '0x80F061544cC398520615B5d3e7A3BedD70cd4510', - }) - assert.strictEqual(wrapper.find(SendHeader).length, 1) - assert.strictEqual(wrapper.find(SendContent).length, 1) - assert.strictEqual(wrapper.find(SendFooter).length, 1) + }); + assert.strictEqual(wrapper.find(SendHeader).length, 1); + assert.strictEqual(wrapper.find(SendContent).length, 1); + assert.strictEqual(wrapper.find(SendFooter).length, 1); assert.deepStrictEqual(wrapper.find(SendFooter).props(), { history: { mockProp: 'history-abc' }, - }) - }) + }); + }); it('should pass showHexData to SendContent', function () { wrapper.setProps({ to: '0x80F061544cC398520615B5d3e7A3BedD70cd4510', - }) - assert.strictEqual(wrapper.find(SendContent).props().showHexData, true) - }) - }) + }); + assert.strictEqual(wrapper.find(SendContent).props().showHexData, true); + }); + }); describe('validate when input change', function () { - let clock + let clock; beforeEach(function () { - clock = sinon.useFakeTimers() - }) + clock = sinon.useFakeTimers(); + }); afterEach(function () { - clock.restore() - }) + clock.restore(); + }); it('should validate when input changes', function () { - const instance = wrapper.instance() + const instance = wrapper.instance(); instance.onRecipientInputChange( '0x80F061544cC398520615B5d3e7A3BedD70cd4510', - ) + ); assert.deepStrictEqual(instance.state, { internalSearch: false, query: '0x80F061544cC398520615B5d3e7A3BedD70cd4510', toError: null, toWarning: null, - }) - }) + }); + }); it('should validate when input changes and has error', function () { - const instance = wrapper.instance() + const instance = wrapper.instance(); instance.onRecipientInputChange( '0x80F061544cC398520615B5d3e7a3BedD70cd4510', - ) + ); - clock.tick(1001) + clock.tick(1001); assert.deepStrictEqual(instance.state, { internalSearch: false, query: '0x80F061544cC398520615B5d3e7a3BedD70cd4510', toError: 'invalidAddressRecipient', toWarning: null, - }) - }) + }); + }); it('should validate when input changes and has error on a bad network', function () { - wrapper.setProps({ network: 'bad' }) - const instance = wrapper.instance() + wrapper.setProps({ network: 'bad' }); + const instance = wrapper.instance(); instance.onRecipientInputChange( '0x80F061544cC398520615B5d3e7a3BedD70cd4510', - ) + ); - clock.tick(1001) + clock.tick(1001); assert.deepStrictEqual(instance.state, { internalSearch: false, query: '0x80F061544cC398520615B5d3e7a3BedD70cd4510', toError: 'invalidAddressRecipientNotEthNetwork', toWarning: null, - }) - }) + }); + }); it('should synchronously validate when input changes to ""', function () { - wrapper.setProps({ network: 'bad' }) - const instance = wrapper.instance() + wrapper.setProps({ network: 'bad' }); + const instance = wrapper.instance(); instance.onRecipientInputChange( '0x80F061544cC398520615B5d3e7a3BedD70cd4510', - ) + ); - clock.tick(1001) + clock.tick(1001); assert.deepStrictEqual(instance.state, { internalSearch: false, query: '0x80F061544cC398520615B5d3e7a3BedD70cd4510', toError: 'invalidAddressRecipientNotEthNetwork', toWarning: null, - }) + }); - instance.onRecipientInputChange('') + instance.onRecipientInputChange(''); assert.deepStrictEqual(instance.state, { internalSearch: false, query: '', toError: '', toWarning: '', - }) - }) + }); + }); it('should warn when send to a known token contract address', function () { - wrapper.setProps({ address: '0x888', decimals: 18, symbol: '888' }) - const instance = wrapper.instance() + wrapper.setProps({ address: '0x888', decimals: 18, symbol: '888' }); + const instance = wrapper.instance(); instance.onRecipientInputChange( '0x13cb85823f78Cff38f0B0E90D3e975b8CB3AAd64', - ) + ); - clock.tick(1001) + clock.tick(1001); assert.deepStrictEqual(instance.state, { internalSearch: false, query: '0x13cb85823f78Cff38f0B0E90D3e975b8CB3AAd64', toError: null, toWarning: 'knownAddressRecipient', - }) - }) - }) -}) + }); + }); + }); +}); diff --git a/ui/app/pages/send/tests/send-container.test.js b/ui/app/pages/send/tests/send-container.test.js index 3a9f4a807..377118920 100644 --- a/ui/app/pages/send/tests/send-container.test.js +++ b/ui/app/pages/send/tests/send-container.test.js @@ -1,24 +1,24 @@ -import assert from 'assert' -import proxyquire from 'proxyquire' -import sinon from 'sinon' +import assert from 'assert'; +import proxyquire from 'proxyquire'; +import sinon from 'sinon'; -let mapDispatchToProps +let mapDispatchToProps; const actionSpies = { updateSendTokenBalance: sinon.spy(), updateGasData: sinon.spy(), setGasTotal: sinon.spy(), -} +}; const duckActionSpies = { updateSendErrors: sinon.spy(), resetSendState: sinon.spy(), -} +}; proxyquire('../send.container.js', { 'react-redux': { connect: (_, md) => { - mapDispatchToProps = md - return () => ({}) + mapDispatchToProps = md; + return () => ({}); }, }, 'react-router-dom': { withRouter: () => undefined }, @@ -28,17 +28,17 @@ proxyquire('../send.container.js', { './send.utils.js': { calcGasTotal: (gasLimit, gasPrice) => gasLimit + gasPrice, }, -}) +}); describe('send container', function () { describe('mapDispatchToProps()', function () { - let dispatchSpy - let mapDispatchToPropsObject + let dispatchSpy; + let mapDispatchToPropsObject; beforeEach(function () { - dispatchSpy = sinon.spy() - mapDispatchToPropsObject = mapDispatchToProps(dispatchSpy) - }) + dispatchSpy = sinon.spy(); + mapDispatchToPropsObject = mapDispatchToProps(dispatchSpy); + }); describe('updateAndSetGasLimit()', function () { const mockProps = { @@ -51,13 +51,16 @@ describe('send container', function () { to: 'mockTo', value: 'mockValue', data: undefined, - } + }; it('should dispatch a setGasTotal action when editingTransactionId is truthy', function () { - mapDispatchToPropsObject.updateAndSetGasLimit(mockProps) - assert(dispatchSpy.calledOnce) - assert.strictEqual(actionSpies.setGasTotal.getCall(0).args[0], '0x30x4') - }) + mapDispatchToPropsObject.updateAndSetGasLimit(mockProps); + assert(dispatchSpy.calledOnce); + assert.strictEqual( + actionSpies.setGasTotal.getCall(0).args[0], + '0x30x4', + ); + }); it('should dispatch an updateGasData action when editingTransactionId is falsy', function () { const { @@ -68,12 +71,12 @@ describe('send container', function () { to, value, data, - } = mockProps + } = mockProps; mapDispatchToPropsObject.updateAndSetGasLimit({ ...mockProps, editingTransactionId: false, - }) - assert(dispatchSpy.calledOnce) + }); + assert(dispatchSpy.calledOnce); assert.deepStrictEqual(actionSpies.updateGasData.getCall(0).args[0], { gasPrice, selectedAddress, @@ -82,47 +85,47 @@ describe('send container', function () { to, value, data, - }) - }) - }) + }); + }); + }); describe('updateSendTokenBalance()', function () { const mockProps = { address: '0x10', tokenContract: '0x00a', sendToken: { address: '0x1' }, - } + }; it('should dispatch an action', function () { - mapDispatchToPropsObject.updateSendTokenBalance({ ...mockProps }) - assert(dispatchSpy.calledOnce) + mapDispatchToPropsObject.updateSendTokenBalance({ ...mockProps }); + assert(dispatchSpy.calledOnce); assert.deepStrictEqual( actionSpies.updateSendTokenBalance.getCall(0).args[0], mockProps, - ) - }) - }) + ); + }); + }); describe('updateSendErrors()', function () { it('should dispatch an action', function () { - mapDispatchToPropsObject.updateSendErrors('mockError') - assert(dispatchSpy.calledOnce) + mapDispatchToPropsObject.updateSendErrors('mockError'); + assert(dispatchSpy.calledOnce); assert.strictEqual( duckActionSpies.updateSendErrors.getCall(0).args[0], 'mockError', - ) - }) - }) + ); + }); + }); describe('resetSendState()', function () { it('should dispatch an action', function () { - mapDispatchToPropsObject.resetSendState() - assert(dispatchSpy.calledOnce) + mapDispatchToPropsObject.resetSendState(); + assert(dispatchSpy.calledOnce); assert.strictEqual( duckActionSpies.resetSendState.getCall(0).args.length, 0, - ) - }) - }) - }) -}) + ); + }); + }); + }); +}); diff --git a/ui/app/pages/send/tests/send-utils.test.js b/ui/app/pages/send/tests/send-utils.test.js index 853581e96..6f51b3fd1 100644 --- a/ui/app/pages/send/tests/send-utils.test.js +++ b/ui/app/pages/send/tests/send-utils.test.js @@ -1,23 +1,23 @@ -import assert from 'assert' -import sinon from 'sinon' -import proxyquire from 'proxyquire' +import assert from 'assert'; +import sinon from 'sinon'; +import proxyquire from 'proxyquire'; import { BASE_TOKEN_GAS_COST, SIMPLE_GAS_COST, INSUFFICIENT_FUNDS_ERROR, INSUFFICIENT_TOKENS_ERROR, -} from '../send.constants' +} from '../send.constants'; const stubs = { addCurrencies: sinon.stub().callsFake((a, b) => { - let [a1, b1] = [a, b] + let [a1, b1] = [a, b]; if (String(a).match(/^0x.+/u)) { - a1 = Number(String(a).slice(2)) + a1 = Number(String(a).slice(2)); } if (String(b).match(/^0x.+/u)) { - b1 = Number(String(b).slice(2)) + b1 = Number(String(b).slice(2)); } - return a1 + b1 + return a1 + b1; }), conversionUtil: sinon.stub().callsFake((val) => parseInt(val, 16)), conversionGTE: sinon @@ -32,7 +32,7 @@ const stubs = { conversionLessThan: sinon .stub() .callsFake((obj1, obj2) => obj1.value < obj2.value), -} +}; const sendUtils = proxyquire('../send.utils.js', { '../../helpers/utils/conversion-util': { @@ -47,7 +47,7 @@ const sendUtils = proxyquire('../send.utils.js', { 'ethereumjs-abi': { rawEncode: stubs.rawEncode, }, -}) +}); const { calcGasTotal, @@ -61,14 +61,14 @@ const { isBalanceSufficient, isTokenBalanceSufficient, removeLeadingZeroes, -} = sendUtils +} = sendUtils; describe('send utils', function () { describe('calcGasTotal()', function () { it('should call multiplyCurrencies with the correct params and return the multiplyCurrencies return', function () { - const result = calcGasTotal(12, 15) - assert.strictEqual(result, '12x15') - const call_ = stubs.multiplyCurrencies.getCall(0).args + const result = calcGasTotal(12, 15); + assert.strictEqual(result, '12x15'); + const call_ = stubs.multiplyCurrencies.getCall(0).args; assert.deepStrictEqual(call_, [ 12, 15, @@ -77,9 +77,9 @@ describe('send utils', function () { multiplicandBase: 16, multiplierBase: 16, }, - ]) - }) - }) + ]); + }); + }); describe('doesAmountErrorRequireUpdate()', function () { const config = { @@ -109,16 +109,16 @@ describe('send utils', function () { sendToken: { address: '0x0' }, expectedResult: false, }, - } + }; Object.entries(config).forEach(([description, obj]) => { it(description, function () { assert.strictEqual( doesAmountErrorRequireUpdate(obj), obj.expectedResult, - ) - }) - }) - }) + ); + }); + }); + }); describe('generateTokenTransferData()', function () { it('should return undefined if not passed a send token', function () { @@ -129,21 +129,21 @@ describe('send utils', function () { sendToken: undefined, }), undefined, - ) - }) + ); + }); it('should call abi.rawEncode with the correct params', function () { - stubs.rawEncode.resetHistory() + stubs.rawEncode.resetHistory(); generateTokenTransferData({ toAddress: 'mockAddress', amount: 'ab', sendToken: { address: '0x0' }, - }) + }); assert.deepStrictEqual(stubs.rawEncode.getCall(0).args, [ ['address', 'uint256'], ['mockAddress', '0xab'], - ]) - }) + ]); + }); it('should return encoded token transfer data', function () { assert.strictEqual( @@ -153,9 +153,9 @@ describe('send utils', function () { sendToken: { address: '0x0' }, }), '0xa9059cbb104c', - ) - }) - }) + ); + }); + }); describe('getAmountErrorObject()', function () { const config = { @@ -189,13 +189,13 @@ describe('send utils', function () { tokenBalance: 123, expectedResult: { amount: INSUFFICIENT_TOKENS_ERROR }, }, - } + }; Object.entries(config).forEach(([description, obj]) => { it(description, function () { - assert.deepStrictEqual(getAmountErrorObject(obj), obj.expectedResult) - }) - }) - }) + assert.deepStrictEqual(getAmountErrorObject(obj), obj.expectedResult); + }); + }); + }); describe('getGasFeeErrorObject()', function () { const config = { @@ -213,13 +213,13 @@ describe('send utils', function () { primaryCurrency: 'ABC', expectedResult: { gasFee: null }, }, - } + }; Object.entries(config).forEach(([description, obj]) => { it(description, function () { - assert.deepStrictEqual(getGasFeeErrorObject(obj), obj.expectedResult) - }) - }) - }) + assert.deepStrictEqual(getGasFeeErrorObject(obj), obj.expectedResult); + }); + }); + }); describe('calcTokenBalance()', function () { it('should return the calculated token balance', function () { @@ -234,20 +234,20 @@ describe('send utils', function () { }, }), 'calc:2011', - ) - }) - }) + ); + }); + }); describe('isBalanceSufficient()', function () { it('should correctly call addCurrencies and return the result of calling conversionGTE', function () { - stubs.conversionGTE.resetHistory() + stubs.conversionGTE.resetHistory(); const result = isBalanceSufficient({ amount: 15, balance: 100, conversionRate: 3, gasTotal: 17, primaryCurrency: 'ABC', - }) + }); assert.deepStrictEqual(stubs.addCurrencies.getCall(0).args, [ 15, 17, @@ -256,7 +256,7 @@ describe('send utils', function () { bBase: 16, toNumericBase: 'hex', }, - ]) + ]); assert.deepStrictEqual(stubs.conversionGTE.getCall(0).args, [ { value: 100, @@ -270,27 +270,27 @@ describe('send utils', function () { conversionRate: 3, fromCurrency: 'ABC', }, - ]) + ]); - assert.strictEqual(result, true) - }) - }) + assert.strictEqual(result, true); + }); + }); describe('isTokenBalanceSufficient()', function () { it('should correctly call conversionUtil and return the result of calling conversionGTE', function () { - stubs.conversionGTE.resetHistory() - stubs.conversionUtil.resetHistory() + stubs.conversionGTE.resetHistory(); + stubs.conversionUtil.resetHistory(); const result = isTokenBalanceSufficient({ amount: '0x10', tokenBalance: 123, decimals: 10, - }) + }); assert.deepStrictEqual(stubs.conversionUtil.getCall(0).args, [ '0x10', { fromNumericBase: 'hex', }, - ]) + ]); assert.deepStrictEqual(stubs.conversionGTE.getCall(0).args, [ { value: 123, @@ -299,11 +299,11 @@ describe('send utils', function () { { value: 'calc:1610', }, - ]) + ]); - assert.strictEqual(result, false) - }) - }) + assert.strictEqual(result, false); + }); + }); describe('estimateGasForSend', function () { const baseMockParams = { @@ -312,17 +312,17 @@ describe('send utils', function () { to: '0xisContract', estimateGasMethod: sinon.stub().callsFake(({ to }) => { if (typeof to === 'string' && to.match(/willFailBecauseOf:/u)) { - throw new Error(to.match(/:(.+)$/u)[1]) + throw new Error(to.match(/:(.+)$/u)[1]); } - return { toString: (n) => `0xabc${n}` } + return { toString: (n) => `0xabc${n}` }; }), - } + }; const baseExpectedCall = { from: 'mockAddress', gas: '0x64x0.95', to: '0xisContract', value: '0xff', - } + }; beforeEach(function () { global.eth = { @@ -331,17 +331,17 @@ describe('send utils', function () { .callsFake((address) => Promise.resolve(address.match(/isContract/u) ? 'not-0x' : '0x'), ), - } - }) + }; + }); afterEach(function () { - baseMockParams.estimateGasMethod.resetHistory() - global.eth.getCode.resetHistory() - }) + baseMockParams.estimateGasMethod.resetHistory(); + global.eth.getCode.resetHistory(); + }); it('should call ethQuery.estimateGasForSend with the expected params', async function () { - const result = await estimateGasForSend(baseMockParams) - assert.strictEqual(baseMockParams.estimateGasMethod.callCount, 1) + const result = await estimateGasForSend(baseMockParams); + assert.strictEqual(baseMockParams.estimateGasMethod.callCount, 1); assert.deepStrictEqual( baseMockParams.estimateGasMethod.getCall(0).args[0], { @@ -349,16 +349,16 @@ describe('send utils', function () { value: undefined, ...baseExpectedCall, }, - ) - assert.strictEqual(result, '0xabc16') - }) + ); + assert.strictEqual(result, '0xabc16'); + }); it('should call ethQuery.estimateGasForSend with the expected params when initialGasLimitHex is lower than the upperGasLimit', async function () { const result = await estimateGasForSend({ ...baseMockParams, blockGasLimit: '0xbcd', - }) - assert.strictEqual(baseMockParams.estimateGasMethod.callCount, 1) + }); + assert.strictEqual(baseMockParams.estimateGasMethod.callCount, 1); assert.deepStrictEqual( baseMockParams.estimateGasMethod.getCall(0).args[0], { @@ -367,17 +367,17 @@ describe('send utils', function () { ...baseExpectedCall, gas: '0xbcdx0.95', }, - ) - assert.strictEqual(result, '0xabc16x1.5') - }) + ); + assert.strictEqual(result, '0xabc16x1.5'); + }); it('should call ethQuery.estimateGasForSend with a value of 0x0 and the expected data and to if passed a sendToken', async function () { const result = await estimateGasForSend({ data: 'mockData', sendToken: { address: 'mockAddress' }, ...baseMockParams, - }) - assert.strictEqual(baseMockParams.estimateGasMethod.callCount, 1) + }); + assert.strictEqual(baseMockParams.estimateGasMethod.callCount, 1); assert.deepStrictEqual( baseMockParams.estimateGasMethod.getCall(0).args[0], { @@ -387,15 +387,15 @@ describe('send utils', function () { data: '0xa9059cbb104c', to: 'mockAddress', }, - ) - assert.strictEqual(result, '0xabc16') - }) + ); + assert.strictEqual(result, '0xabc16'); + }); it('should call ethQuery.estimateGasForSend without a recipient if the recipient is empty and data passed', async function () { - const data = 'mockData' - const to = '' - const result = await estimateGasForSend({ ...baseMockParams, data, to }) - assert.strictEqual(baseMockParams.estimateGasMethod.callCount, 1) + const data = 'mockData'; + const to = ''; + const result = await estimateGasForSend({ ...baseMockParams, data, to }); + assert.strictEqual(baseMockParams.estimateGasMethod.callCount, 1); assert.deepStrictEqual( baseMockParams.estimateGasMethod.getCall(0).args[0], { @@ -405,106 +405,106 @@ describe('send utils', function () { from: baseExpectedCall.from, gas: baseExpectedCall.gas, }, - ) - assert.strictEqual(result, '0xabc16') - }) + ); + assert.strictEqual(result, '0xabc16'); + }); it(`should return ${SIMPLE_GAS_COST} if ethQuery.getCode does not return '0x'`, async function () { - assert.strictEqual(baseMockParams.estimateGasMethod.callCount, 0) + assert.strictEqual(baseMockParams.estimateGasMethod.callCount, 0); const result = await estimateGasForSend({ ...baseMockParams, to: '0x123', - }) - assert.strictEqual(result, SIMPLE_GAS_COST) - }) + }); + assert.strictEqual(result, SIMPLE_GAS_COST); + }); it(`should return ${SIMPLE_GAS_COST} if not passed a sendToken or truthy to address`, async function () { - assert.strictEqual(baseMockParams.estimateGasMethod.callCount, 0) - const result = await estimateGasForSend({ ...baseMockParams, to: null }) - assert.strictEqual(result, SIMPLE_GAS_COST) - }) + assert.strictEqual(baseMockParams.estimateGasMethod.callCount, 0); + const result = await estimateGasForSend({ ...baseMockParams, to: null }); + assert.strictEqual(result, SIMPLE_GAS_COST); + }); it(`should not return ${SIMPLE_GAS_COST} if passed a sendToken`, async function () { - assert.strictEqual(baseMockParams.estimateGasMethod.callCount, 0) + assert.strictEqual(baseMockParams.estimateGasMethod.callCount, 0); const result = await estimateGasForSend({ ...baseMockParams, to: '0x123', sendToken: { address: '0x0' }, - }) - assert.notStrictEqual(result, SIMPLE_GAS_COST) - }) + }); + assert.notStrictEqual(result, SIMPLE_GAS_COST); + }); it(`should return ${BASE_TOKEN_GAS_COST} if passed a sendToken but no to address`, async function () { const result = await estimateGasForSend({ ...baseMockParams, to: null, sendToken: { address: '0x0' }, - }) - assert.strictEqual(result, BASE_TOKEN_GAS_COST) - }) + }); + assert.strictEqual(result, BASE_TOKEN_GAS_COST); + }); it(`should return the adjusted blockGasLimit if it fails with a 'Transaction execution error.'`, async function () { const result = await estimateGasForSend({ ...baseMockParams, to: 'isContract willFailBecauseOf:Transaction execution error.', - }) - assert.strictEqual(result, '0x64x0.95') - }) + }); + assert.strictEqual(result, '0x64x0.95'); + }); it(`should return the adjusted blockGasLimit if it fails with a 'gas required exceeds allowance or always failing transaction.'`, async function () { const result = await estimateGasForSend({ ...baseMockParams, to: 'isContract willFailBecauseOf:gas required exceeds allowance or always failing transaction.', - }) - assert.strictEqual(result, '0x64x0.95') - }) + }); + assert.strictEqual(result, '0x64x0.95'); + }); it(`should reject other errors`, async function () { try { await estimateGasForSend({ ...baseMockParams, to: 'isContract willFailBecauseOf:some other error', - }) + }); } catch (err) { - assert.strictEqual(err.message, 'some other error') + assert.strictEqual(err.message, 'some other error'); } - }) - }) + }); + }); describe('getToAddressForGasUpdate()', function () { it('should return empty string if all params are undefined or null', function () { - assert.strictEqual(getToAddressForGasUpdate(undefined, null), '') - }) + assert.strictEqual(getToAddressForGasUpdate(undefined, null), ''); + }); it('should return the first string that is not defined or null in lower case', function () { - assert.strictEqual(getToAddressForGasUpdate('A', null), 'a') - assert.strictEqual(getToAddressForGasUpdate(undefined, 'B'), 'b') - }) - }) + assert.strictEqual(getToAddressForGasUpdate('A', null), 'a'); + assert.strictEqual(getToAddressForGasUpdate(undefined, 'B'), 'b'); + }); + }); describe('removeLeadingZeroes()', function () { it('should remove leading zeroes from int when user types', function () { - assert.strictEqual(removeLeadingZeroes('0'), '0') - assert.strictEqual(removeLeadingZeroes('1'), '1') - assert.strictEqual(removeLeadingZeroes('00'), '0') - assert.strictEqual(removeLeadingZeroes('01'), '1') - }) + assert.strictEqual(removeLeadingZeroes('0'), '0'); + assert.strictEqual(removeLeadingZeroes('1'), '1'); + assert.strictEqual(removeLeadingZeroes('00'), '0'); + assert.strictEqual(removeLeadingZeroes('01'), '1'); + }); it('should remove leading zeroes from int when user copy/paste', function () { - assert.strictEqual(removeLeadingZeroes('001'), '1') - }) + assert.strictEqual(removeLeadingZeroes('001'), '1'); + }); it('should remove leading zeroes from float when user types', function () { - assert.strictEqual(removeLeadingZeroes('0.'), '0.') - assert.strictEqual(removeLeadingZeroes('0.0'), '0.0') - assert.strictEqual(removeLeadingZeroes('0.00'), '0.00') - assert.strictEqual(removeLeadingZeroes('0.001'), '0.001') - assert.strictEqual(removeLeadingZeroes('0.10'), '0.10') - }) + assert.strictEqual(removeLeadingZeroes('0.'), '0.'); + assert.strictEqual(removeLeadingZeroes('0.0'), '0.0'); + assert.strictEqual(removeLeadingZeroes('0.00'), '0.00'); + assert.strictEqual(removeLeadingZeroes('0.001'), '0.001'); + assert.strictEqual(removeLeadingZeroes('0.10'), '0.10'); + }); it('should remove leading zeroes from float when user copy/paste', function () { - assert.strictEqual(removeLeadingZeroes('00.1'), '0.1') - }) - }) -}) + assert.strictEqual(removeLeadingZeroes('00.1'), '0.1'); + }); + }); +}); diff --git a/ui/app/pages/settings/advanced-tab/advanced-tab.component.js b/ui/app/pages/settings/advanced-tab/advanced-tab.component.js index 25aefece0..742d1c233 100644 --- a/ui/app/pages/settings/advanced-tab/advanced-tab.component.js +++ b/ui/app/pages/settings/advanced-tab/advanced-tab.component.js @@ -1,17 +1,17 @@ -import React, { PureComponent } from 'react' -import PropTypes from 'prop-types' -import classnames from 'classnames' -import { exportAsFile } from '../../../helpers/utils/util' -import ToggleButton from '../../../components/ui/toggle-button' -import TextField from '../../../components/ui/text-field' -import Button from '../../../components/ui/button' -import { MOBILE_SYNC_ROUTE } from '../../../helpers/constants/routes' +import React, { PureComponent } from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; +import { exportAsFile } from '../../../helpers/utils/util'; +import ToggleButton from '../../../components/ui/toggle-button'; +import TextField from '../../../components/ui/text-field'; +import Button from '../../../components/ui/button'; +import { MOBILE_SYNC_ROUTE } from '../../../helpers/constants/routes'; export default class AdvancedTab extends PureComponent { static contextTypes = { t: PropTypes.func, metricsEvent: PropTypes.func, - } + }; static propTypes = { setUseNonceField: PropTypes.func, @@ -33,18 +33,18 @@ export default class AdvancedTab extends PureComponent { threeBoxDisabled: PropTypes.bool.isRequired, setIpfsGateway: PropTypes.func.isRequired, ipfsGateway: PropTypes.string.isRequired, - } + }; state = { autoLockTimeLimit: this.props.autoLockTimeLimit, lockTimeError: '', ipfsGateway: this.props.ipfsGateway, ipfsGatewayError: '', - } + }; renderMobileSync() { - const { t } = this.context - const { history } = this.props + const { t } = this.context; + const { history } = this.props; return (
    { - event.preventDefault() - history.push(MOBILE_SYNC_ROUTE) + event.preventDefault(); + history.push(MOBILE_SYNC_ROUTE); }} > {t('syncWithMobile')} @@ -69,12 +69,12 @@ export default class AdvancedTab extends PureComponent {
    - ) + ); } renderStateLogs() { - const { t } = this.context - const { displayWarning } = this.props + const { t } = this.context; + const { displayWarning } = this.props; return (
    { window.logStateString((err, result) => { if (err) { - displayWarning(t('stateLogError')) + displayWarning(t('stateLogError')); } else { - exportAsFile(`${t('stateLogFileName')}.json`, result) + exportAsFile(`${t('stateLogFileName')}.json`, result); } - }) + }); }} > {t('downloadStateLogs')} @@ -107,12 +107,12 @@ export default class AdvancedTab extends PureComponent {
    - ) + ); } renderResetAccount() { - const { t } = this.context - const { showResetAccountConfirmationModal } = this.props + const { t } = this.context; + const { showResetAccountConfirmationModal } = this.props; return (
    { - event.preventDefault() + event.preventDefault(); this.context.metricsEvent({ eventOpts: { category: 'Settings', action: 'Reset Account', name: 'Reset Account', }, - }) - showResetAccountConfirmationModal() + }); + showResetAccountConfirmationModal(); }} > {t('resetAccount')} @@ -148,12 +148,12 @@ export default class AdvancedTab extends PureComponent {
    - ) + ); } renderHexDataOptIn() { - const { t } = this.context - const { sendHexData, setHexDataFeatureFlag } = this.props + const { t } = this.context; + const { sendHexData, setHexDataFeatureFlag } = this.props; return (
    - ) + ); } renderAdvancedGasInputInline() { - const { t } = this.context - const { advancedInlineGas, setAdvancedInlineGasFeatureFlag } = this.props + const { t } = this.context; + const { advancedInlineGas, setAdvancedInlineGasFeatureFlag } = this.props; return (
    - ) + ); } renderShowConversionInTestnets() { - const { t } = this.context + const { t } = this.context; const { showFiatInTestnets, setShowFiatConversionOnTestnetsPreference, - } = this.props + } = this.props; return (
    - ) + ); } renderUseNonceOptIn() { - const { t } = this.context - const { useNonceField, setUseNonceField } = this.props + const { t } = this.context; + const { useNonceField, setUseNonceField } = this.props; return (
    - ) + ); } handleLockChange(time) { - const { t } = this.context - const autoLockTimeLimit = Math.max(Number(time), 0) + const { t } = this.context; + const autoLockTimeLimit = Math.max(Number(time), 0); this.setState(() => { - let lockTimeError = '' + let lockTimeError = ''; if (autoLockTimeLimit > 10080) { - lockTimeError = t('lockTimeTooGreat') + lockTimeError = t('lockTimeTooGreat'); } return { autoLockTimeLimit, lockTimeError, - } - }) + }; + }); } renderAutoLockTimeLimit() { - const { t } = this.context - const { lockTimeError } = this.state - const { autoLockTimeLimit, setAutoLockTimeLimit } = this.props + const { t } = this.context; + const { lockTimeError } = this.state; + const { autoLockTimeLimit, setAutoLockTimeLimit } = this.props; return (
    { - setAutoLockTimeLimit(this.state.autoLockTimeLimit) + setAutoLockTimeLimit(this.state.autoLockTimeLimit); }} > {t('save')} @@ -333,23 +333,23 @@ export default class AdvancedTab extends PureComponent {
    - ) + ); } renderThreeBoxControl() { - const { t } = this.context + const { t } = this.context; const { threeBoxSyncingAllowed, setThreeBoxSyncingPermission, threeBoxDisabled, - } = this.props + } = this.props; - let allowed = threeBoxSyncingAllowed - let description = t('syncWithThreeBoxDescription') + let allowed = threeBoxSyncingAllowed; + let description = t('syncWithThreeBoxDescription'); if (threeBoxDisabled) { - allowed = false - description = t('syncWithThreeBoxDisabled') + allowed = false; + description = t('syncWithThreeBoxDisabled'); } return (
    { if (!threeBoxDisabled) { - setThreeBoxSyncingPermission(!value) + setThreeBoxSyncingPermission(!value); } }} offLabel={t('off')} @@ -381,49 +381,49 @@ export default class AdvancedTab extends PureComponent {
    - ) + ); } handleIpfsGatewayChange(url) { - const { t } = this.context + const { t } = this.context; this.setState(() => { - let ipfsGatewayError = '' + let ipfsGatewayError = ''; try { - const urlObj = new URL(addUrlProtocolPrefix(url)) + const urlObj = new URL(addUrlProtocolPrefix(url)); if (!urlObj.host) { - throw new Error() + throw new Error(); } // don't allow the use of this gateway if (urlObj.host === 'gateway.ipfs.io') { - throw new Error('Forbidden gateway') + throw new Error('Forbidden gateway'); } } catch (error) { ipfsGatewayError = error.message === 'Forbidden gateway' ? t('forbiddenIpfsGateway') - : t('invalidIpfsGateway') + : t('invalidIpfsGateway'); } return { ipfsGateway: url, ipfsGatewayError, - } - }) + }; + }); } handleIpfsGatewaySave() { - const url = new URL(addUrlProtocolPrefix(this.state.ipfsGateway)) - const { host } = url + const url = new URL(addUrlProtocolPrefix(this.state.ipfsGateway)); + const { host } = url; - this.props.setIpfsGateway(host) + this.props.setIpfsGateway(host); } renderIpfsGatewayControl() { - const { t } = this.context - const { ipfsGatewayError } = this.state + const { t } = this.context; + const { ipfsGatewayError } = this.state; return (
    { - this.handleIpfsGatewaySave() + this.handleIpfsGatewaySave(); }} > {t('save')} @@ -459,11 +459,11 @@ export default class AdvancedTab extends PureComponent {
    - ) + ); } render() { - const { warning } = this.props + const { warning } = this.props; return (
    @@ -479,13 +479,13 @@ export default class AdvancedTab extends PureComponent { {this.renderThreeBoxControl()} {this.renderIpfsGatewayControl()}
    - ) + ); } } function addUrlProtocolPrefix(urlString) { if (!urlString.match(/(^http:\/\/)|(^https:\/\/)/u)) { - return `https://${urlString}` + return `https://${urlString}`; } - return urlString + return urlString; } diff --git a/ui/app/pages/settings/advanced-tab/advanced-tab.container.js b/ui/app/pages/settings/advanced-tab/advanced-tab.container.js index fc4fd8db1..1bfa82f30 100644 --- a/ui/app/pages/settings/advanced-tab/advanced-tab.container.js +++ b/ui/app/pages/settings/advanced-tab/advanced-tab.container.js @@ -1,6 +1,6 @@ -import { compose } from 'redux' -import { connect } from 'react-redux' -import { withRouter } from 'react-router-dom' +import { compose } from 'redux'; +import { connect } from 'react-redux'; +import { withRouter } from 'react-router-dom'; import { displayWarning, setFeatureFlag, @@ -11,23 +11,23 @@ import { turnThreeBoxSyncingOnAndInitialize, setUseNonceField, setIpfsGateway, -} from '../../../store/actions' -import { getPreferences } from '../../../selectors' -import AdvancedTab from './advanced-tab.component' +} from '../../../store/actions'; +import { getPreferences } from '../../../selectors'; +import AdvancedTab from './advanced-tab.component'; export const mapStateToProps = (state) => { const { appState: { warning }, metamask, - } = state + } = state; const { featureFlags: { sendHexData, advancedInlineGas } = {}, threeBoxSyncingAllowed, threeBoxDisabled, useNonceField, ipfsGateway, - } = metamask - const { showFiatInTestnets, autoLockTimeLimit } = getPreferences(state) + } = metamask; + const { showFiatInTestnets, autoLockTimeLimit } = getPreferences(state); return { warning, @@ -39,8 +39,8 @@ export const mapStateToProps = (state) => { threeBoxDisabled, useNonceField, ipfsGateway, - } -} + }; +}; export const mapDispatchToProps = (dispatch) => { return { @@ -53,25 +53,25 @@ export const mapDispatchToProps = (dispatch) => { dispatch(setFeatureFlag('advancedInlineGas', shouldShow)), setUseNonceField: (value) => dispatch(setUseNonceField(value)), setShowFiatConversionOnTestnetsPreference: (value) => { - return dispatch(setShowFiatConversionOnTestnetsPreference(value)) + return dispatch(setShowFiatConversionOnTestnetsPreference(value)); }, setAutoLockTimeLimit: (value) => { - return dispatch(setAutoLockTimeLimit(value)) + return dispatch(setAutoLockTimeLimit(value)); }, setThreeBoxSyncingPermission: (newThreeBoxSyncingState) => { if (newThreeBoxSyncingState) { - dispatch(turnThreeBoxSyncingOnAndInitialize()) + dispatch(turnThreeBoxSyncingOnAndInitialize()); } else { - dispatch(setThreeBoxSyncingPermission(newThreeBoxSyncingState)) + dispatch(setThreeBoxSyncingPermission(newThreeBoxSyncingState)); } }, setIpfsGateway: (value) => { - return dispatch(setIpfsGateway(value)) + return dispatch(setIpfsGateway(value)); }, - } -} + }; +}; export default compose( withRouter, connect(mapStateToProps, mapDispatchToProps), -)(AdvancedTab) +)(AdvancedTab); diff --git a/ui/app/pages/settings/advanced-tab/index.js b/ui/app/pages/settings/advanced-tab/index.js index 85955174e..f8ead6ef9 100644 --- a/ui/app/pages/settings/advanced-tab/index.js +++ b/ui/app/pages/settings/advanced-tab/index.js @@ -1 +1 @@ -export { default } from './advanced-tab.container' +export { default } from './advanced-tab.container'; diff --git a/ui/app/pages/settings/advanced-tab/tests/advanced-tab-component.test.js b/ui/app/pages/settings/advanced-tab/tests/advanced-tab-component.test.js index 024702ae3..76b9360f3 100644 --- a/ui/app/pages/settings/advanced-tab/tests/advanced-tab-component.test.js +++ b/ui/app/pages/settings/advanced-tab/tests/advanced-tab-component.test.js @@ -1,9 +1,9 @@ -import assert from 'assert' -import React from 'react' -import sinon from 'sinon' -import { shallow } from 'enzyme' -import AdvancedTab from '../advanced-tab.component' -import TextField from '../../../../components/ui/text-field' +import assert from 'assert'; +import React from 'react'; +import sinon from 'sinon'; +import { shallow } from 'enzyme'; +import AdvancedTab from '../advanced-tab.component'; +import TextField from '../../../../components/ui/text-field'; describe('AdvancedTab Component', function () { it('should render correctly when threeBoxFeatureFlag', function () { @@ -22,13 +22,13 @@ describe('AdvancedTab Component', function () { t: (s) => `_${s}`, }, }, - ) + ); - assert.strictEqual(root.find('.settings-page__content-row').length, 10) - }) + assert.strictEqual(root.find('.settings-page__content-row').length, 10); + }); it('should update autoLockTimeLimit', function () { - const setAutoLockTimeLimitSpy = sinon.spy() + const setAutoLockTimeLimitSpy = sinon.spy(); const root = shallow( `_${s}`, }, }, - ) + ); - const autoTimeout = root.find('.settings-page__content-row').at(7) - const textField = autoTimeout.find(TextField) + const autoTimeout = root.find('.settings-page__content-row').at(7); + const textField = autoTimeout.find(TextField); - textField.props().onChange({ target: { value: 1440 } }) - assert.strictEqual(root.state().autoLockTimeLimit, 1440) + textField.props().onChange({ target: { value: 1440 } }); + assert.strictEqual(root.state().autoLockTimeLimit, 1440); - autoTimeout.find('.settings-tab__rpc-save-button').simulate('click') - assert.strictEqual(setAutoLockTimeLimitSpy.args[0][0], 1440) - }) -}) + autoTimeout.find('.settings-tab__rpc-save-button').simulate('click'); + assert.strictEqual(setAutoLockTimeLimitSpy.args[0][0], 1440); + }); +}); diff --git a/ui/app/pages/settings/alerts-tab/alerts-tab.js b/ui/app/pages/settings/alerts-tab/alerts-tab.js index 832a4ec17..cdf77c7a5 100644 --- a/ui/app/pages/settings/alerts-tab/alerts-tab.js +++ b/ui/app/pages/settings/alerts-tab/alerts-tab.js @@ -1,17 +1,17 @@ -import React from 'react' -import PropTypes from 'prop-types' -import { useSelector } from 'react-redux' +import React from 'react'; +import PropTypes from 'prop-types'; +import { useSelector } from 'react-redux'; -import { ALERT_TYPES } from '../../../../../shared/constants/alerts' -import Tooltip from '../../../components/ui/tooltip' -import ToggleButton from '../../../components/ui/toggle-button' -import { setAlertEnabledness } from '../../../store/actions' -import { getAlertEnabledness } from '../../../ducks/metamask/metamask' -import { useI18nContext } from '../../../hooks/useI18nContext' +import { ALERT_TYPES } from '../../../../../shared/constants/alerts'; +import Tooltip from '../../../components/ui/tooltip'; +import ToggleButton from '../../../components/ui/toggle-button'; +import { setAlertEnabledness } from '../../../store/actions'; +import { getAlertEnabledness } from '../../../ducks/metamask/metamask'; +import { useI18nContext } from '../../../hooks/useI18nContext'; const AlertSettingsEntry = ({ alertId, description, title }) => { - const t = useI18nContext() - const isEnabled = useSelector((state) => getAlertEnabledness(state)[alertId]) + const t = useI18nContext(); + const isEnabled = useSelector((state) => getAlertEnabledness(state)[alertId]); return ( <> @@ -30,17 +30,17 @@ const AlertSettingsEntry = ({ alertId, description, title }) => { value={isEnabled} /> - ) -} + ); +}; AlertSettingsEntry.propTypes = { alertId: PropTypes.string.isRequired, description: PropTypes.string.isRequired, title: PropTypes.string.isRequired, -} +}; const AlertsTab = () => { - const t = useI18nContext() + const t = useI18nContext(); const alertConfig = { [ALERT_TYPES.unconnectedAccount]: { @@ -51,7 +51,7 @@ const AlertsTab = () => { title: t('alertSettingsWeb3ShimUsage'), description: t('alertSettingsWeb3ShimUsageDescription'), }, - } + }; return (
    @@ -64,7 +64,7 @@ const AlertsTab = () => { /> ))}
    - ) -} + ); +}; -export default AlertsTab +export default AlertsTab; diff --git a/ui/app/pages/settings/alerts-tab/index.js b/ui/app/pages/settings/alerts-tab/index.js index 691d54230..f6aa526da 100644 --- a/ui/app/pages/settings/alerts-tab/index.js +++ b/ui/app/pages/settings/alerts-tab/index.js @@ -1 +1 @@ -export { default } from './alerts-tab' +export { default } from './alerts-tab'; diff --git a/ui/app/pages/settings/contact-list-tab/add-contact/add-contact.component.js b/ui/app/pages/settings/contact-list-tab/add-contact/add-contact.component.js index 5fad37d53..896180517 100644 --- a/ui/app/pages/settings/contact-list-tab/add-contact/add-contact.component.js +++ b/ui/app/pages/settings/contact-list-tab/add-contact/add-contact.component.js @@ -1,20 +1,20 @@ -import React, { PureComponent } from 'react' -import PropTypes from 'prop-types' -import { debounce } from 'lodash' -import Identicon from '../../../../components/ui/identicon' -import TextField from '../../../../components/ui/text-field' -import { CONTACT_LIST_ROUTE } from '../../../../helpers/constants/routes' +import React, { PureComponent } from 'react'; +import PropTypes from 'prop-types'; +import { debounce } from 'lodash'; +import Identicon from '../../../../components/ui/identicon'; +import TextField from '../../../../components/ui/text-field'; +import { CONTACT_LIST_ROUTE } from '../../../../helpers/constants/routes'; import { isValidAddress, isValidDomainName, -} from '../../../../helpers/utils/util' -import EnsInput from '../../../send/send-content/add-recipient/ens-input' -import PageContainerFooter from '../../../../components/ui/page-container/page-container-footer' +} from '../../../../helpers/utils/util'; +import EnsInput from '../../../send/send-content/add-recipient/ens-input'; +import PageContainerFooter from '../../../../components/ui/page-container/page-container-footer'; export default class AddContact extends PureComponent { static contextTypes = { t: PropTypes.func, - } + }; static propTypes = { addToAddressBook: PropTypes.func, @@ -23,7 +23,7 @@ export default class AddContact extends PureComponent { qrCodeData: PropTypes.object /* eslint-disable-line react/no-unused-prop-types */, qrCodeDetected: PropTypes.func, - } + }; state = { newName: '', @@ -31,64 +31,64 @@ export default class AddContact extends PureComponent { ensAddress: '', error: '', ensError: '', - } + }; constructor(props) { - super(props) - this.dValidate = debounce(this.validate, 1000) + super(props); + this.dValidate = debounce(this.validate, 1000); } UNSAFE_componentWillReceiveProps(nextProps) { if (nextProps.qrCodeData) { if (nextProps.qrCodeData.type === 'address') { - const scannedAddress = nextProps.qrCodeData.values.address.toLowerCase() - const currentAddress = this.state.ensAddress || this.state.ethAddress + const scannedAddress = nextProps.qrCodeData.values.address.toLowerCase(); + const currentAddress = this.state.ensAddress || this.state.ethAddress; if (currentAddress.toLowerCase() !== scannedAddress) { - this.setState({ ethAddress: scannedAddress, ensAddress: '' }) + this.setState({ ethAddress: scannedAddress, ensAddress: '' }); // Clean up QR code data after handling - this.props.qrCodeDetected(null) + this.props.qrCodeDetected(null); } } } } validate = (address) => { - const valid = isValidAddress(address) - const validEnsAddress = isValidDomainName(address) + const valid = isValidAddress(address); + const validEnsAddress = isValidDomainName(address); if (valid || validEnsAddress || address === '') { - this.setState({ error: '', ethAddress: address }) + this.setState({ error: '', ethAddress: address }); } else { - this.setState({ error: 'Invalid Address' }) + this.setState({ error: 'Invalid Address' }); } - } + }; renderInput() { return ( { - this.props.scanQrCode() + this.props.scanQrCode(); }} onChange={this.dValidate} onPaste={(text) => this.setState({ ethAddress: text })} onReset={() => this.setState({ ethAddress: '', ensAddress: '' })} updateEnsResolution={(address) => { - this.setState({ ensAddress: address, error: '', ensError: '' }) + this.setState({ ensAddress: address, error: '', ensError: '' }); }} updateEnsResolutionError={(message) => this.setState({ ensError: message }) } value={this.state.ethAddress || ''} /> - ) + ); } render() { - const { t } = this.context - const { history, addToAddressBook } = this.props + const { t } = this.context; + const { history, addToAddressBook } = this.props; - const errorToRender = this.state.ensError || this.state.error + const errorToRender = this.state.ensError || this.state.error; return (
    @@ -134,16 +134,16 @@ export default class AddContact extends PureComponent { await addToAddressBook( this.state.ensAddress || this.state.ethAddress, this.state.newName, - ) - history.push(CONTACT_LIST_ROUTE) + ); + history.push(CONTACT_LIST_ROUTE); }} onCancel={() => { - history.push(CONTACT_LIST_ROUTE) + history.push(CONTACT_LIST_ROUTE); }} submitText={this.context.t('save')} submitButtonType="confirm" />
    - ) + ); } } diff --git a/ui/app/pages/settings/contact-list-tab/add-contact/add-contact.container.js b/ui/app/pages/settings/contact-list-tab/add-contact/add-contact.container.js index 51cbd2ec9..8d3c63c5f 100644 --- a/ui/app/pages/settings/contact-list-tab/add-contact/add-contact.container.js +++ b/ui/app/pages/settings/contact-list-tab/add-contact/add-contact.container.js @@ -1,19 +1,19 @@ -import { compose } from 'redux' -import { connect } from 'react-redux' -import { withRouter } from 'react-router-dom' +import { compose } from 'redux'; +import { connect } from 'react-redux'; +import { withRouter } from 'react-router-dom'; import { addToAddressBook, showQrScanner, qrCodeDetected, -} from '../../../../store/actions' -import { getQrCodeData } from '../../../../selectors' -import AddContact from './add-contact.component' +} from '../../../../store/actions'; +import { getQrCodeData } from '../../../../selectors'; +import AddContact from './add-contact.component'; const mapStateToProps = (state) => { return { qrCodeData: getQrCodeData(state), - } -} + }; +}; const mapDispatchToProps = (dispatch) => { return { @@ -21,10 +21,10 @@ const mapDispatchToProps = (dispatch) => { dispatch(addToAddressBook(recipient, nickname)), scanQrCode: () => dispatch(showQrScanner()), qrCodeDetected: (data) => dispatch(qrCodeDetected(data)), - } -} + }; +}; export default compose( withRouter, connect(mapStateToProps, mapDispatchToProps), -)(AddContact) +)(AddContact); diff --git a/ui/app/pages/settings/contact-list-tab/add-contact/index.js b/ui/app/pages/settings/contact-list-tab/add-contact/index.js index ce73025a3..232ca9362 100644 --- a/ui/app/pages/settings/contact-list-tab/add-contact/index.js +++ b/ui/app/pages/settings/contact-list-tab/add-contact/index.js @@ -1 +1 @@ -export { default } from './add-contact.container' +export { default } from './add-contact.container'; diff --git a/ui/app/pages/settings/contact-list-tab/contact-list-tab.component.js b/ui/app/pages/settings/contact-list-tab/contact-list-tab.component.js index 068dc3daf..d16db37b9 100644 --- a/ui/app/pages/settings/contact-list-tab/contact-list-tab.component.js +++ b/ui/app/pages/settings/contact-list-tab/contact-list-tab.component.js @@ -1,20 +1,20 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import ContactList from '../../../components/app/contact-list' +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import ContactList from '../../../components/app/contact-list'; import { CONTACT_ADD_ROUTE, CONTACT_VIEW_ROUTE, CONTACT_MY_ACCOUNTS_ROUTE, -} from '../../../helpers/constants/routes' -import EditContact from './edit-contact' -import AddContact from './add-contact' -import ViewContact from './view-contact' -import MyAccounts from './my-accounts' +} from '../../../helpers/constants/routes'; +import EditContact from './edit-contact'; +import AddContact from './add-contact'; +import ViewContact from './view-contact'; +import MyAccounts from './my-accounts'; export default class ContactListTab extends Component { static contextTypes = { t: PropTypes.func, - } + }; static propTypes = { addressBook: PropTypes.array, @@ -26,12 +26,12 @@ export default class ContactListTab extends Component { showContactContent: PropTypes.bool, hideAddressBook: PropTypes.bool, showingMyAccounts: PropTypes.bool, - } + }; renderAddresses() { - const { addressBook, history, selectedAddress } = this.props - const contacts = addressBook.filter(({ name }) => Boolean(name)) - const nonContacts = addressBook.filter(({ name }) => !name) + const { addressBook, history, selectedAddress } = this.props; + const contacts = addressBook.filter(({ name }) => Boolean(name)); + const nonContacts = addressBook.filter(({ name }) => !name); return (
    @@ -39,22 +39,22 @@ export default class ContactListTab extends Component { searchForContacts={() => contacts} searchForRecents={() => nonContacts} selectRecipient={(address) => { - history.push(`${CONTACT_VIEW_ROUTE}/${address}`) + history.push(`${CONTACT_VIEW_ROUTE}/${address}`); }} selectedAddress={selectedAddress} />
    - ) + ); } renderAddButton() { - const { history } = this.props + const { history } = this.props; return (
    { - history.push(CONTACT_ADD_ROUTE) + history.push(CONTACT_ADD_ROUTE); }} > {this.context.t('addAccount')}
    - ) + ); } renderMyAccountsButton() { - const { history } = this.props - const { t } = this.context + const { history } = this.props; + const { t } = this.context; return (
    { - history.push(CONTACT_MY_ACCOUNTS_ROUTE) + history.push(CONTACT_MY_ACCOUNTS_ROUTE); }} >
    @@ -86,7 +86,7 @@ export default class ContactListTab extends Component {
    - ) + ); } renderContactContent() { @@ -95,19 +95,19 @@ export default class ContactListTab extends Component { editingContact, addingContact, showContactContent, - } = this.props + } = this.props; if (!showContactContent) { - return null + return null; } - let ContactContentComponent = null + let ContactContentComponent = null; if (viewingContact) { - ContactContentComponent = ViewContact + ContactContentComponent = ViewContact; } else if (editingContact) { - ContactContentComponent = EditContact + ContactContentComponent = EditContact; } else if (addingContact) { - ContactContentComponent = AddContact + ContactContentComponent = AddContact; } return ( @@ -116,11 +116,11 @@ export default class ContactListTab extends Component {
    ) - ) + ); } renderAddressBookContent() { - const { hideAddressBook, showingMyAccounts } = this.props + const { hideAddressBook, showingMyAccounts } = this.props; if (!hideAddressBook && !showingMyAccounts) { return ( @@ -128,15 +128,15 @@ export default class ContactListTab extends Component { {this.renderMyAccountsButton()} {this.renderAddresses()} - ) + ); } else if (!hideAddressBook && showingMyAccounts) { - return + return ; } - return null + return null; } render() { - const { addingContact } = this.props + const { addingContact } = this.props; return (
    @@ -148,6 +148,6 @@ export default class ContactListTab extends Component {
    )} - ) + ); } } diff --git a/ui/app/pages/settings/contact-list-tab/contact-list-tab.container.js b/ui/app/pages/settings/contact-list-tab/contact-list-tab.container.js index 101daf7ab..19749eafd 100644 --- a/ui/app/pages/settings/contact-list-tab/contact-list-tab.container.js +++ b/ui/app/pages/settings/contact-list-tab/contact-list-tab.container.js @@ -1,9 +1,9 @@ -import { compose } from 'redux' -import { connect } from 'react-redux' -import { withRouter } from 'react-router-dom' -import { getAddressBook } from '../../../selectors' -import { ENVIRONMENT_TYPE_POPUP } from '../../../../../shared/constants/app' -import { getEnvironmentType } from '../../../../../app/scripts/lib/util' +import { compose } from 'redux'; +import { connect } from 'react-redux'; +import { withRouter } from 'react-router-dom'; +import { getAddressBook } from '../../../selectors'; +import { ENVIRONMENT_TYPE_POPUP } from '../../../../../shared/constants/app'; +import { getEnvironmentType } from '../../../../../app/scripts/lib/util'; import { CONTACT_ADD_ROUTE, @@ -12,34 +12,34 @@ import { CONTACT_MY_ACCOUNTS_ROUTE, CONTACT_MY_ACCOUNTS_VIEW_ROUTE, CONTACT_MY_ACCOUNTS_EDIT_ROUTE, -} from '../../../helpers/constants/routes' -import ContactListTab from './contact-list-tab.component' +} from '../../../helpers/constants/routes'; +import ContactListTab from './contact-list-tab.component'; const mapStateToProps = (state, ownProps) => { - const { location } = ownProps - const { pathname } = location + const { location } = ownProps; + const { pathname } = location; - const pathNameTail = pathname.match(/[^/]+$/u)[0] - const pathNameTailIsAddress = pathNameTail.includes('0x') + const pathNameTail = pathname.match(/[^/]+$/u)[0]; + const pathNameTailIsAddress = pathNameTail.includes('0x'); const viewingContact = Boolean( pathname.match(CONTACT_VIEW_ROUTE) || pathname.match(CONTACT_MY_ACCOUNTS_VIEW_ROUTE), - ) + ); const editingContact = Boolean( pathname.match(CONTACT_EDIT_ROUTE) || pathname.match(CONTACT_MY_ACCOUNTS_EDIT_ROUTE), - ) - const addingContact = Boolean(pathname.match(CONTACT_ADD_ROUTE)) + ); + const addingContact = Boolean(pathname.match(CONTACT_ADD_ROUTE)); const showingMyAccounts = Boolean( pathname.match(CONTACT_MY_ACCOUNTS_ROUTE) || pathname.match(CONTACT_MY_ACCOUNTS_VIEW_ROUTE) || pathname.match(CONTACT_MY_ACCOUNTS_EDIT_ROUTE), - ) - const envIsPopup = getEnvironmentType() === ENVIRONMENT_TYPE_POPUP + ); + const envIsPopup = getEnvironmentType() === ENVIRONMENT_TYPE_POPUP; const hideAddressBook = - envIsPopup && (viewingContact || editingContact || addingContact) + envIsPopup && (viewingContact || editingContact || addingContact); return { viewingContact, @@ -51,7 +51,7 @@ const mapStateToProps = (state, ownProps) => { hideAddressBook, envIsPopup, showContactContent: !envIsPopup || hideAddressBook, - } -} + }; +}; -export default compose(withRouter, connect(mapStateToProps))(ContactListTab) +export default compose(withRouter, connect(mapStateToProps))(ContactListTab); diff --git a/ui/app/pages/settings/contact-list-tab/edit-contact/edit-contact.component.js b/ui/app/pages/settings/contact-list-tab/edit-contact/edit-contact.component.js index e8c3c00f5..e705dd7fb 100644 --- a/ui/app/pages/settings/contact-list-tab/edit-contact/edit-contact.component.js +++ b/ui/app/pages/settings/contact-list-tab/edit-contact/edit-contact.component.js @@ -1,16 +1,16 @@ -import React, { PureComponent } from 'react' -import PropTypes from 'prop-types' -import { Redirect } from 'react-router-dom' -import Identicon from '../../../../components/ui/identicon' -import Button from '../../../../components/ui/button/button.component' -import TextField from '../../../../components/ui/text-field' -import { isValidAddress } from '../../../../helpers/utils/util' -import PageContainerFooter from '../../../../components/ui/page-container/page-container-footer' +import React, { PureComponent } from 'react'; +import PropTypes from 'prop-types'; +import { Redirect } from 'react-router-dom'; +import Identicon from '../../../../components/ui/identicon'; +import Button from '../../../../components/ui/button/button.component'; +import TextField from '../../../../components/ui/text-field'; +import { isValidAddress } from '../../../../helpers/utils/util'; +import PageContainerFooter from '../../../../components/ui/page-container/page-container-footer'; export default class EditContact extends PureComponent { static contextTypes = { t: PropTypes.func, - } + }; static propTypes = { addToAddressBook: PropTypes.func, @@ -24,22 +24,22 @@ export default class EditContact extends PureComponent { listRoute: PropTypes.string, setAccountLabel: PropTypes.func, showingMyAccounts: PropTypes.bool.isRequired, - } + }; static defaultProps = { name: '', memo: '', - } + }; state = { newName: this.props.name, newAddress: this.props.address, newMemo: this.props.memo, error: '', - } + }; render() { - const { t } = this.context + const { t } = this.context; const { address, addToAddressBook, @@ -52,10 +52,10 @@ export default class EditContact extends PureComponent { setAccountLabel, showingMyAccounts, viewRoute, - } = this.props + } = this.props; if (!address) { - return + return ; } return ( @@ -67,7 +67,7 @@ export default class EditContact extends PureComponent { type="link" className="settings-page__address-book-button" onClick={async () => { - await removeFromAddressBook(chainId, address) + await removeFromAddressBook(chainId, address); }} > {t('deleteAccount')} @@ -135,21 +135,21 @@ export default class EditContact extends PureComponent { ) { // if the user makes a valid change to the address field, remove the original address if (isValidAddress(this.state.newAddress)) { - await removeFromAddressBook(chainId, address) + await removeFromAddressBook(chainId, address); await addToAddressBook( this.state.newAddress, this.state.newName || name, this.state.newMemo || memo, - ) + ); if (showingMyAccounts) { setAccountLabel( this.state.newAddress, this.state.newName || name, - ) + ); } - history.push(listRoute) + history.push(listRoute); } else { - this.setState({ error: this.context.t('invalidAddress') }) + this.setState({ error: this.context.t('invalidAddress') }); } } else { // update name @@ -157,20 +157,20 @@ export default class EditContact extends PureComponent { address, this.state.newName || name, this.state.newMemo || memo, - ) + ); if (showingMyAccounts) { - setAccountLabel(address, this.state.newName || name) + setAccountLabel(address, this.state.newName || name); } - history.push(listRoute) + history.push(listRoute); } }} onCancel={() => { - history.push(`${viewRoute}/${address}`) + history.push(`${viewRoute}/${address}`); }} submitText={this.context.t('save')} submitButtonType="confirm" /> - ) + ); } } diff --git a/ui/app/pages/settings/contact-list-tab/edit-contact/edit-contact.container.js b/ui/app/pages/settings/contact-list-tab/edit-contact/edit-contact.container.js index ff038e4b3..dfb23aabd 100644 --- a/ui/app/pages/settings/contact-list-tab/edit-contact/edit-contact.container.js +++ b/ui/app/pages/settings/contact-list-tab/edit-contact/edit-contact.container.js @@ -1,39 +1,39 @@ -import { compose } from 'redux' -import { connect } from 'react-redux' -import { withRouter } from 'react-router-dom' -import { getAddressBookEntry } from '../../../../selectors' +import { compose } from 'redux'; +import { connect } from 'react-redux'; +import { withRouter } from 'react-router-dom'; +import { getAddressBookEntry } from '../../../../selectors'; import { CONTACT_VIEW_ROUTE, CONTACT_MY_ACCOUNTS_ROUTE, CONTACT_MY_ACCOUNTS_VIEW_ROUTE, CONTACT_MY_ACCOUNTS_EDIT_ROUTE, CONTACT_LIST_ROUTE, -} from '../../../../helpers/constants/routes' +} from '../../../../helpers/constants/routes'; import { addToAddressBook, removeFromAddressBook, setAccountLabel, -} from '../../../../store/actions' -import EditContact from './edit-contact.component' +} from '../../../../store/actions'; +import EditContact from './edit-contact.component'; const mapStateToProps = (state, ownProps) => { - const { location } = ownProps - const { pathname } = location - const pathNameTail = pathname.match(/[^/]+$/u)[0] - const pathNameTailIsAddress = pathNameTail.includes('0x') + const { location } = ownProps; + const { pathname } = location; + const pathNameTail = pathname.match(/[^/]+$/u)[0]; + const pathNameTailIsAddress = pathNameTail.includes('0x'); const address = pathNameTailIsAddress ? pathNameTail.toLowerCase() - : ownProps.match.params.id + : ownProps.match.params.id; const contact = - getAddressBookEntry(state, address) || state.metamask.identities[address] - const { memo, name } = contact || {} + getAddressBookEntry(state, address) || state.metamask.identities[address]; + const { memo, name } = contact || {}; - const { chainId } = state.metamask.provider + const { chainId } = state.metamask.provider; const showingMyAccounts = Boolean( pathname.match(CONTACT_MY_ACCOUNTS_EDIT_ROUTE), - ) + ); return { address: contact ? address : null, @@ -47,8 +47,8 @@ const mapStateToProps = (state, ownProps) => { ? CONTACT_MY_ACCOUNTS_ROUTE : CONTACT_LIST_ROUTE, showingMyAccounts, - } -} + }; +}; const mapDispatchToProps = (dispatch) => { return { @@ -58,10 +58,10 @@ const mapDispatchToProps = (dispatch) => { dispatch(removeFromAddressBook(chainId, addressToRemove)), setAccountLabel: (address, label) => dispatch(setAccountLabel(address, label)), - } -} + }; +}; export default compose( withRouter, connect(mapStateToProps, mapDispatchToProps), -)(EditContact) +)(EditContact); diff --git a/ui/app/pages/settings/contact-list-tab/edit-contact/index.js b/ui/app/pages/settings/contact-list-tab/edit-contact/index.js index fe5ee206a..ba1254ba9 100644 --- a/ui/app/pages/settings/contact-list-tab/edit-contact/index.js +++ b/ui/app/pages/settings/contact-list-tab/edit-contact/index.js @@ -1 +1 @@ -export { default } from './edit-contact.container' +export { default } from './edit-contact.container'; diff --git a/ui/app/pages/settings/contact-list-tab/index.js b/ui/app/pages/settings/contact-list-tab/index.js index c09e9787b..2662ef2bf 100644 --- a/ui/app/pages/settings/contact-list-tab/index.js +++ b/ui/app/pages/settings/contact-list-tab/index.js @@ -1 +1 @@ -export { default } from './contact-list-tab.container' +export { default } from './contact-list-tab.container'; diff --git a/ui/app/pages/settings/contact-list-tab/my-accounts/index.js b/ui/app/pages/settings/contact-list-tab/my-accounts/index.js index 13a7a9cbf..e5bde6530 100644 --- a/ui/app/pages/settings/contact-list-tab/my-accounts/index.js +++ b/ui/app/pages/settings/contact-list-tab/my-accounts/index.js @@ -1 +1 @@ -export { default } from './my-accounts.container' +export { default } from './my-accounts.container'; diff --git a/ui/app/pages/settings/contact-list-tab/my-accounts/my-accounts.component.js b/ui/app/pages/settings/contact-list-tab/my-accounts/my-accounts.component.js index d9cac4544..bb7702c56 100644 --- a/ui/app/pages/settings/contact-list-tab/my-accounts/my-accounts.component.js +++ b/ui/app/pages/settings/contact-list-tab/my-accounts/my-accounts.component.js @@ -1,34 +1,34 @@ -import React, { PureComponent } from 'react' -import PropTypes from 'prop-types' -import ContactList from '../../../../components/app/contact-list' -import { CONTACT_MY_ACCOUNTS_VIEW_ROUTE } from '../../../../helpers/constants/routes' +import React, { PureComponent } from 'react'; +import PropTypes from 'prop-types'; +import ContactList from '../../../../components/app/contact-list'; +import { CONTACT_MY_ACCOUNTS_VIEW_ROUTE } from '../../../../helpers/constants/routes'; export default class ViewContact extends PureComponent { static contextTypes = { t: PropTypes.func, - } + }; static propTypes = { myAccounts: PropTypes.array, history: PropTypes.object, - } + }; renderMyAccounts() { - const { myAccounts, history } = this.props + const { myAccounts, history } = this.props; return (
    myAccounts} selectRecipient={(address) => { - history.push(`${CONTACT_MY_ACCOUNTS_VIEW_ROUTE}/${address}`) + history.push(`${CONTACT_MY_ACCOUNTS_VIEW_ROUTE}/${address}`); }} />
    - ) + ); } render() { - return
    {this.renderMyAccounts()}
    + return
    {this.renderMyAccounts()}
    ; } } diff --git a/ui/app/pages/settings/contact-list-tab/my-accounts/my-accounts.container.js b/ui/app/pages/settings/contact-list-tab/my-accounts/my-accounts.container.js index 605d6dd89..82ac4b4ef 100644 --- a/ui/app/pages/settings/contact-list-tab/my-accounts/my-accounts.container.js +++ b/ui/app/pages/settings/contact-list-tab/my-accounts/my-accounts.container.js @@ -1,15 +1,15 @@ -import { compose } from 'redux' -import { connect } from 'react-redux' -import { withRouter } from 'react-router-dom' -import { accountsWithSendEtherInfoSelector } from '../../../../selectors' -import ViewContact from './my-accounts.component' +import { compose } from 'redux'; +import { connect } from 'react-redux'; +import { withRouter } from 'react-router-dom'; +import { accountsWithSendEtherInfoSelector } from '../../../../selectors'; +import ViewContact from './my-accounts.component'; const mapStateToProps = (state) => { - const myAccounts = accountsWithSendEtherInfoSelector(state) + const myAccounts = accountsWithSendEtherInfoSelector(state); return { myAccounts, - } -} + }; +}; -export default compose(withRouter, connect(mapStateToProps))(ViewContact) +export default compose(withRouter, connect(mapStateToProps))(ViewContact); diff --git a/ui/app/pages/settings/contact-list-tab/view-contact/index.js b/ui/app/pages/settings/contact-list-tab/view-contact/index.js index 78bf19d18..6b8fe106a 100644 --- a/ui/app/pages/settings/contact-list-tab/view-contact/index.js +++ b/ui/app/pages/settings/contact-list-tab/view-contact/index.js @@ -1 +1 @@ -export { default } from './view-contact.container' +export { default } from './view-contact.container'; diff --git a/ui/app/pages/settings/contact-list-tab/view-contact/view-contact.component.js b/ui/app/pages/settings/contact-list-tab/view-contact/view-contact.component.js index aada6d13a..bcc6e9adc 100644 --- a/ui/app/pages/settings/contact-list-tab/view-contact/view-contact.component.js +++ b/ui/app/pages/settings/contact-list-tab/view-contact/view-contact.component.js @@ -1,20 +1,20 @@ -import React from 'react' -import PropTypes from 'prop-types' -import { Redirect } from 'react-router-dom' +import React from 'react'; +import PropTypes from 'prop-types'; +import { Redirect } from 'react-router-dom'; -import Identicon from '../../../../components/ui/identicon' -import Copy from '../../../../components/ui/icon/copy-icon.component' -import Button from '../../../../components/ui/button/button.component' +import Identicon from '../../../../components/ui/identicon'; +import Copy from '../../../../components/ui/icon/copy-icon.component'; +import Button from '../../../../components/ui/button/button.component'; -import Tooltip from '../../../../components/ui/tooltip' -import { useI18nContext } from '../../../../hooks/useI18nContext' -import { useCopyToClipboard } from '../../../../hooks/useCopyToClipboard' +import Tooltip from '../../../../components/ui/tooltip'; +import { useI18nContext } from '../../../../hooks/useI18nContext'; +import { useCopyToClipboard } from '../../../../hooks/useCopyToClipboard'; function quadSplit(address) { return `0x ${address .slice(2) .match(/.{1,4}/gu) - .join(' ')}` + .join(' ')}`; } function ViewContact({ @@ -26,11 +26,11 @@ function ViewContact({ editRoute, listRoute, }) { - const t = useI18nContext() - const [copied, handleCopy] = useCopyToClipboard() + const t = useI18nContext(); + const [copied, handleCopy] = useCopyToClipboard(); if (!address) { - return + return ; } return ( @@ -44,7 +44,7 @@ function ViewContact({ - ) + ); } render() { - const { t } = this.context + const { t } = this.context; return (
    @@ -113,6 +113,6 @@ export default class InfoTab extends PureComponent {
    - ) + ); } } diff --git a/ui/app/pages/settings/networks-tab/index.js b/ui/app/pages/settings/networks-tab/index.js index 362004498..fc436c9a4 100644 --- a/ui/app/pages/settings/networks-tab/index.js +++ b/ui/app/pages/settings/networks-tab/index.js @@ -1 +1 @@ -export { default } from './networks-tab.container' +export { default } from './networks-tab.container'; diff --git a/ui/app/pages/settings/networks-tab/network-form/index.js b/ui/app/pages/settings/networks-tab/network-form/index.js index 89d9de42b..bd21ef354 100644 --- a/ui/app/pages/settings/networks-tab/network-form/index.js +++ b/ui/app/pages/settings/networks-tab/network-form/index.js @@ -1 +1 @@ -export { default } from './network-form.component' +export { default } from './network-form.component'; diff --git a/ui/app/pages/settings/networks-tab/network-form/network-form.component.js b/ui/app/pages/settings/networks-tab/network-form/network-form.component.js index a20aa5534..4d9e10a6e 100644 --- a/ui/app/pages/settings/networks-tab/network-form/network-form.component.js +++ b/ui/app/pages/settings/networks-tab/network-form/network-form.component.js @@ -1,15 +1,15 @@ -import React, { PureComponent } from 'react' -import PropTypes from 'prop-types' -import validUrl from 'valid-url' -import log from 'loglevel' -import TextField from '../../../../components/ui/text-field' -import Button from '../../../../components/ui/button' -import Tooltip from '../../../../components/ui/tooltip' +import React, { PureComponent } from 'react'; +import PropTypes from 'prop-types'; +import validUrl from 'valid-url'; +import log from 'loglevel'; +import TextField from '../../../../components/ui/text-field'; +import Button from '../../../../components/ui/button'; +import Tooltip from '../../../../components/ui/tooltip'; import { isPrefixedFormattedHexString, isSafeChainId, -} from '../../../../../../shared/modules/utils' -import { jsonRpcRequest } from '../../../../helpers/utils/util' +} from '../../../../../../shared/modules/utils'; +import { jsonRpcRequest } from '../../../../helpers/utils/util'; const FORM_STATE_KEYS = [ 'rpcUrl', @@ -17,13 +17,13 @@ const FORM_STATE_KEYS = [ 'ticker', 'networkName', 'blockExplorerUrl', -] +]; export default class NetworkForm extends PureComponent { static contextTypes = { t: PropTypes.func.isRequired, metricsEvent: PropTypes.func.isRequired, - } + }; static propTypes = { editRpc: PropTypes.func.isRequired, @@ -41,7 +41,7 @@ export default class NetworkForm extends PureComponent { rpcPrefs: PropTypes.object, rpcUrls: PropTypes.array, isFullScreen: PropTypes.bool, - } + }; state = { rpcUrl: this.props.rpcUrl, @@ -51,11 +51,11 @@ export default class NetworkForm extends PureComponent { blockExplorerUrl: this.props.blockExplorerUrl, errors: {}, isSubmitting: false, - } + }; componentDidUpdate(prevProps) { - const { networksTabIsInAddMode: prevAddMode } = prevProps - const { networksTabIsInAddMode } = this.props + const { networksTabIsInAddMode: prevAddMode } = prevProps; + const { networksTabIsInAddMode } = this.props; if (!prevAddMode && networksTabIsInAddMode) { this.setState({ @@ -66,12 +66,12 @@ export default class NetworkForm extends PureComponent { blockExplorerUrl: '', errors: {}, isSubmitting: false, - }) + }); } else { for (const key of FORM_STATE_KEYS) { if (prevProps[key] !== this.props[key]) { - this.resetForm() - break + this.resetForm(); + break; } } } @@ -85,12 +85,12 @@ export default class NetworkForm extends PureComponent { networkName: '', blockExplorerUrl: '', errors: {}, - }) + }); // onClear will push the network settings route unless was pass false. // Since we call onClear to cause this component to be unmounted, the // route will already have been updated, and we avoid setting it twice. - this.props.onClear(false) + this.props.onClear(false); } resetForm() { @@ -100,7 +100,7 @@ export default class NetworkForm extends PureComponent { ticker, networkName, blockExplorerUrl, - } = this.props + } = this.props; this.setState({ rpcUrl, @@ -110,7 +110,7 @@ export default class NetworkForm extends PureComponent { blockExplorerUrl, errors: {}, isSubmitting: false, - }) + }); } /** @@ -126,15 +126,15 @@ export default class NetworkForm extends PureComponent { */ getDisplayChainId(chainId) { if (!chainId || typeof chainId !== 'string' || !chainId.startsWith('0x')) { - return chainId + return chainId; } - return parseInt(chainId, 16).toString(10) + return parseInt(chainId, 16).toString(10); } onSubmit = async () => { this.setState({ isSubmitting: true, - }) + }); try { const { @@ -144,27 +144,27 @@ export default class NetworkForm extends PureComponent { rpcPrefs = {}, onClear, networksTabIsInAddMode, - } = this.props + } = this.props; const { networkName, rpcUrl, chainId: stateChainId, ticker, blockExplorerUrl, - } = this.state + } = this.state; - const formChainId = stateChainId.trim().toLowerCase() + const formChainId = stateChainId.trim().toLowerCase(); // Ensure chainId is a 0x-prefixed, lowercase hex string - let chainId = formChainId + let chainId = formChainId; if (!chainId.startsWith('0x')) { - chainId = `0x${parseInt(chainId, 10).toString(16)}` + chainId = `0x${parseInt(chainId, 10).toString(16)}`; } if (!(await this.validateChainIdOnSubmit(formChainId, chainId, rpcUrl))) { this.setState({ isSubmitting: false, - }) - return + }); + return; } // After this point, isSubmitting will be reset in componentDidUpdate @@ -172,48 +172,48 @@ export default class NetworkForm extends PureComponent { await editRpc(propsRpcUrl, rpcUrl, chainId, ticker, networkName, { ...rpcPrefs, blockExplorerUrl: blockExplorerUrl || rpcPrefs.blockExplorerUrl, - }) + }); } else { await setRpcTarget(rpcUrl, chainId, ticker, networkName, { ...rpcPrefs, blockExplorerUrl: blockExplorerUrl || rpcPrefs.blockExplorerUrl, - }) + }); } if (networksTabIsInAddMode) { - onClear() + onClear(); } } catch (error) { this.setState({ isSubmitting: false, - }) - throw error + }); + throw error; } - } + }; onCancel = () => { - const { isFullScreen, networksTabIsInAddMode, onClear } = this.props + const { isFullScreen, networksTabIsInAddMode, onClear } = this.props; if (networksTabIsInAddMode || !isFullScreen) { - onClear() + onClear(); } else { - this.resetForm() + this.resetForm(); } - } + }; onDelete = () => { - const { showConfirmDeleteNetworkModal, rpcUrl, onClear } = this.props + const { showConfirmDeleteNetworkModal, rpcUrl, onClear } = this.props; showConfirmDeleteNetworkModal({ target: rpcUrl, onConfirm: () => { - this.resetForm() - onClear() + this.resetForm(); + onClear(); }, - }) - } + }); + }; isSubmitting() { - return this.state.isSubmitting + return this.state.isSubmitting; } stateIsUnchanged() { @@ -223,7 +223,7 @@ export default class NetworkForm extends PureComponent { ticker, networkName, blockExplorerUrl, - } = this.props + } = this.props; const { rpcUrl: stateRpcUrl, @@ -231,7 +231,7 @@ export default class NetworkForm extends PureComponent { ticker: stateTicker, networkName: stateNetworkName, blockExplorerUrl: stateBlockExplorerUrl, - } = this.state + } = this.state; // These added conditions are in case the saved chainId is invalid, which // was possible in versions <8.1 of the extension. @@ -239,7 +239,7 @@ export default class NetworkForm extends PureComponent { const chainIdIsUnchanged = typeof propsChainId === 'string' && propsChainId.toLowerCase().startsWith('0x') && - stateChainId === this.getDisplayChainId(propsChainId) + stateChainId === this.getDisplayChainId(propsChainId); return ( stateRpcUrl === rpcUrl && @@ -247,7 +247,7 @@ export default class NetworkForm extends PureComponent { stateTicker === ticker && stateNetworkName === networkName && stateBlockExplorerUrl === blockExplorerUrl - ) + ); } renderFormTextField( @@ -258,8 +258,8 @@ export default class NetworkForm extends PureComponent { optionalTextFieldKey, tooltipText, ) { - const { errors } = this.state - const { viewOnly } = this.props + const { errors } = this.state; + const { viewOnly } = this.props; return (
    @@ -288,15 +288,15 @@ export default class NetworkForm extends PureComponent { error={errors[fieldKey]} />
    - ) + ); } setStateWithValue = (stateKey, validator) => { return (e) => { - validator?.(e.target.value, stateKey) - this.setState({ [stateKey]: e.target.value }) - } - } + validator?.(e.target.value, stateKey); + this.setState({ [stateKey]: e.target.value }); + }; + }; setErrorTo = (errorKey, errorVal) => { this.setState({ @@ -304,31 +304,31 @@ export default class NetworkForm extends PureComponent { ...this.state.errors, [errorKey]: errorVal, }, - }) - } + }); + }; validateChainIdOnChange = (chainIdArg = '') => { - const chainId = chainIdArg.trim() - let errorMessage = '' - let radix = 10 + const chainId = chainIdArg.trim(); + let errorMessage = ''; + let radix = 10; if (chainId.startsWith('0x')) { - radix = 16 + radix = 16; if (!/^0x[0-9a-f]+$/iu.test(chainId)) { - errorMessage = this.context.t('invalidHexNumber') + errorMessage = this.context.t('invalidHexNumber'); } else if (!isPrefixedFormattedHexString(chainId)) { - errorMessage = this.context.t('invalidHexNumberLeadingZeros') + errorMessage = this.context.t('invalidHexNumberLeadingZeros'); } } else if (!/^[0-9]+$/u.test(chainId)) { - errorMessage = this.context.t('invalidNumber') + errorMessage = this.context.t('invalidNumber'); } else if (chainId.startsWith('0')) { - errorMessage = this.context.t('invalidNumberLeadingZeros') + errorMessage = this.context.t('invalidNumberLeadingZeros'); } else if (!isSafeChainId(parseInt(chainId, radix))) { - errorMessage = this.context.t('invalidChainIdTooBig') + errorMessage = this.context.t('invalidChainIdTooBig'); } - this.setErrorTo('chainId', errorMessage) - } + this.setErrorTo('chainId', errorMessage); + }; /** * Validates the chain ID by checking it against the `eth_chainId` return @@ -341,20 +341,20 @@ export default class NetworkForm extends PureComponent { * @param {string} rpcUrl - The RPC URL from the form. */ validateChainIdOnSubmit = async (formChainId, parsedChainId, rpcUrl) => { - const { t } = this.context - let errorMessage - let endpointChainId - let providerError + const { t } = this.context; + let errorMessage; + let endpointChainId; + let providerError; try { - endpointChainId = await jsonRpcRequest(rpcUrl, 'eth_chainId') + endpointChainId = await jsonRpcRequest(rpcUrl, 'eth_chainId'); } catch (err) { - log.warn('Failed to fetch the chainId from the endpoint.', err) - providerError = err + log.warn('Failed to fetch the chainId from the endpoint.', err); + providerError = err; } if (providerError || typeof endpointChainId !== 'string') { - errorMessage = t('failedToFetchChainId') + errorMessage = t('failedToFetchChainId'); } else if (parsedChainId !== endpointChainId) { // Here, we are in an error state. The endpoint should always return a // hexadecimal string. If the user entered a decimal string, we attempt @@ -362,12 +362,12 @@ export default class NetworkForm extends PureComponent { // in an error message in the form. if (!formChainId.startsWith('0x')) { try { - endpointChainId = parseInt(endpointChainId, 16).toString(10) + endpointChainId = parseInt(endpointChainId, 16).toString(10); } catch (err) { log.warn( 'Failed to convert endpoint chain ID to decimal', endpointChainId, - ) + ); } } @@ -375,20 +375,20 @@ export default class NetworkForm extends PureComponent { endpointChainId.length <= 12 ? endpointChainId : `${endpointChainId.slice(0, 9)}...`, - ]) + ]); } if (errorMessage) { - this.setErrorTo('chainId', errorMessage) - return false + this.setErrorTo('chainId', errorMessage); + return false; } - return true - } + return true; + }; isValidWhenAppended = (url) => { - const appendedRpc = `http://${url}` - return validUrl.isWebUri(appendedRpc) && !url.match(/^https?:\/\/$/u) - } + const appendedRpc = `http://${url}`; + return validUrl.isWebUri(appendedRpc) && !url.match(/^https?:\/\/$/u); + }; validateBlockExplorerURL = (url, stateKey) => { if (!validUrl.isWebUri(url) && url !== '') { @@ -399,14 +399,14 @@ export default class NetworkForm extends PureComponent { ? 'urlErrorMsg' : 'invalidBlockExplorerURL', ), - ) + ); } else { - this.setErrorTo(stateKey, '') + this.setErrorTo(stateKey, ''); } - } + }; validateUrlRpcUrl = (url, stateKey) => { - const { rpcUrls } = this.props + const { rpcUrls } = this.props; if (!validUrl.isWebUri(url) && url !== '') { this.setErrorTo( @@ -414,26 +414,26 @@ export default class NetworkForm extends PureComponent { this.context.t( this.isValidWhenAppended(url) ? 'urlErrorMsg' : 'invalidRPC', ), - ) + ); } else if (rpcUrls.includes(url)) { - this.setErrorTo(stateKey, this.context.t('urlExistsErrorMsg')) + this.setErrorTo(stateKey, this.context.t('urlExistsErrorMsg')); } else { - this.setErrorTo(stateKey, '') + this.setErrorTo(stateKey, ''); } - } + }; renderWarning() { - const { t } = this.context + const { t } = this.context; return (
    {t('onlyAddTrustedNetworks')}
    - ) + ); } render() { - const { t } = this.context - const { viewOnly, isCurrentRpcTarget, networksTabIsInAddMode } = this.props + const { t } = this.context; + const { viewOnly, isCurrentRpcTarget, networksTabIsInAddMode } = this.props; const { networkName, rpcUrl, @@ -441,17 +441,17 @@ export default class NetworkForm extends PureComponent { ticker, blockExplorerUrl, errors, - } = this.state + } = this.state; const deletable = - !networksTabIsInAddMode && !isCurrentRpcTarget && !viewOnly + !networksTabIsInAddMode && !isCurrentRpcTarget && !viewOnly; const isSubmitDisabled = this.isSubmitting() || this.stateIsUnchanged() || !rpcUrl || !chainId || - Object.values(errors).some((x) => x) + Object.values(errors).some((x) => x); return (
    @@ -519,6 +519,6 @@ export default class NetworkForm extends PureComponent { )}
    - ) + ); } } diff --git a/ui/app/pages/settings/networks-tab/networks-tab.component.js b/ui/app/pages/settings/networks-tab/networks-tab.component.js index bac21f93e..f62a40790 100644 --- a/ui/app/pages/settings/networks-tab/networks-tab.component.js +++ b/ui/app/pages/settings/networks-tab/networks-tab.component.js @@ -1,22 +1,22 @@ -import React, { PureComponent } from 'react' -import PropTypes from 'prop-types' -import classnames from 'classnames' -import { NETWORK_TYPE_RPC } from '../../../../../shared/constants/network' -import Button from '../../../components/ui/button' -import LockIcon from '../../../components/ui/lock-icon' +import React, { PureComponent } from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; +import { NETWORK_TYPE_RPC } from '../../../../../shared/constants/network'; +import Button from '../../../components/ui/button'; +import LockIcon from '../../../components/ui/lock-icon'; import { NETWORKS_ROUTE, NETWORKS_FORM_ROUTE, -} from '../../../helpers/constants/routes' -import ColorIndicator from '../../../components/ui/color-indicator' -import { COLORS, SIZES } from '../../../helpers/constants/design-system' -import NetworkForm from './network-form' +} from '../../../helpers/constants/routes'; +import ColorIndicator from '../../../components/ui/color-indicator'; +import { COLORS, SIZES } from '../../../helpers/constants/design-system'; +import NetworkForm from './network-form'; export default class NetworksTab extends PureComponent { static contextTypes = { t: PropTypes.func.isRequired, metricsEvent: PropTypes.func.isRequired, - } + }; static propTypes = { editRpc: PropTypes.func.isRequired, @@ -35,18 +35,18 @@ export default class NetworksTab extends PureComponent { history: PropTypes.object.isRequired, shouldRenderNetworkForm: PropTypes.bool.isRequired, isFullScreen: PropTypes.bool.isRequired, - } + }; componentWillUnmount() { - this.props.setSelectedSettingsRpcUrl('') + this.props.setSelectedSettingsRpcUrl(''); } isCurrentPath(pathname) { - return this.props.location.pathname === pathname + return this.props.location.pathname === pathname; } renderSubHeader() { - const { setSelectedSettingsRpcUrl, setNetworksTabAddMode } = this.props + const { setSelectedSettingsRpcUrl, setNetworksTabAddMode } = this.props; return (
    @@ -57,16 +57,16 @@ export default class NetworksTab extends PureComponent {
    - ) + ); } renderNetworkListItem(network, selectRpcUrl) { @@ -79,34 +79,34 @@ export default class NetworksTab extends PureComponent { networksTabIsInAddMode, history, isFullScreen, - } = this.props + } = this.props; const { label, labelKey, rpcUrl, providerType: currentProviderType, - } = network + } = network; - const listItemNetworkIsSelected = selectRpcUrl && selectRpcUrl === rpcUrl - const listItemUrlIsProviderUrl = rpcUrl === providerUrl + const listItemNetworkIsSelected = selectRpcUrl && selectRpcUrl === rpcUrl; + const listItemUrlIsProviderUrl = rpcUrl === providerUrl; const listItemTypeIsProviderNonRpcType = - providerType !== NETWORK_TYPE_RPC && currentProviderType === providerType + providerType !== NETWORK_TYPE_RPC && currentProviderType === providerType; const listItemNetworkIsCurrentProvider = !networkIsSelected && !networksTabIsInAddMode && - (listItemUrlIsProviderUrl || listItemTypeIsProviderNonRpcType) + (listItemUrlIsProviderUrl || listItemTypeIsProviderNonRpcType); const displayNetworkListItemAsSelected = - listItemNetworkIsSelected || listItemNetworkIsCurrentProvider + listItemNetworkIsSelected || listItemNetworkIsCurrentProvider; return (
    { - setNetworksTabAddMode(false) - setSelectedSettingsRpcUrl(rpcUrl) + setNetworksTabAddMode(false); + setSelectedSettingsRpcUrl(rpcUrl); if (!isFullScreen) { - history.push(NETWORKS_FORM_ROUTE) + history.push(NETWORKS_FORM_ROUTE); } }} > @@ -130,7 +130,7 @@ export default class NetworksTab extends PureComponent {
    - ) + ); } renderNetworksList() { @@ -140,7 +140,7 @@ export default class NetworksTab extends PureComponent { networkIsSelected, networksTabIsInAddMode, networkDefaultedToProvider, - } = this.props + } = this.props; return (
    )}
    - ) + ); } renderNetworksTabContent() { - const { t } = this.context + const { t } = this.context; const { setRpcTarget, showConfirmDeleteNetworkModal, @@ -195,7 +195,7 @@ export default class NetworksTab extends PureComponent { history, isFullScreen, shouldRenderNetworkForm, - } = this.props + } = this.props; return ( <> @@ -210,10 +210,10 @@ export default class NetworksTab extends PureComponent { chainId={chainId} ticker={ticker} onClear={(shouldUpdateHistory = true) => { - setNetworksTabAddMode(false) - setSelectedSettingsRpcUrl('') + setNetworksTabAddMode(false); + setSelectedSettingsRpcUrl(''); if (shouldUpdateHistory && !isFullScreen) { - history.push(NETWORKS_ROUTE) + history.push(NETWORKS_ROUTE); } }} showConfirmDeleteNetworkModal={showConfirmDeleteNetworkModal} @@ -226,7 +226,7 @@ export default class NetworksTab extends PureComponent { /> ) : null} - ) + ); } render() { @@ -236,7 +236,7 @@ export default class NetworksTab extends PureComponent { history, isFullScreen, shouldRenderNetworkForm, - } = this.props + } = this.props; return (
    @@ -248,10 +248,10 @@ export default class NetworksTab extends PureComponent {
    - ) + ); } } diff --git a/ui/app/pages/settings/networks-tab/networks-tab.constants.js b/ui/app/pages/settings/networks-tab/networks-tab.constants.js index 9a9eb9699..52f6514d7 100644 --- a/ui/app/pages/settings/networks-tab/networks-tab.constants.js +++ b/ui/app/pages/settings/networks-tab/networks-tab.constants.js @@ -9,7 +9,7 @@ import { RINKEBY_CHAIN_ID, ROPSTEN, ROPSTEN_CHAIN_ID, -} from '../../../../../shared/constants/network' +} from '../../../../../shared/constants/network'; const defaultNetworksData = [ { @@ -57,6 +57,6 @@ const defaultNetworksData = [ ticker: 'ETH', blockExplorerUrl: 'https://kovan.etherscan.io', }, -] +]; -export { defaultNetworksData } +export { defaultNetworksData }; diff --git a/ui/app/pages/settings/networks-tab/networks-tab.container.js b/ui/app/pages/settings/networks-tab/networks-tab.container.js index 14f5d3929..75b637159 100644 --- a/ui/app/pages/settings/networks-tab/networks-tab.container.js +++ b/ui/app/pages/settings/networks-tab/networks-tab.container.js @@ -1,6 +1,6 @@ -import { compose } from 'redux' -import { connect } from 'react-redux' -import { withRouter } from 'react-router-dom' +import { compose } from 'redux'; +import { connect } from 'react-redux'; +import { withRouter } from 'react-router-dom'; import { setSelectedSettingsRpcUrl, updateAndSetCustomRpc, @@ -8,31 +8,31 @@ import { setNetworksTabAddMode, editRpc, showModal, -} from '../../../store/actions' -import { NETWORKS_FORM_ROUTE } from '../../../helpers/constants/routes' -import { ENVIRONMENT_TYPE_FULLSCREEN } from '../../../../../shared/constants/app' -import { NETWORK_TYPE_RPC } from '../../../../../shared/constants/network' -import { getEnvironmentType } from '../../../../../app/scripts/lib/util' -import NetworksTab from './networks-tab.component' -import { defaultNetworksData } from './networks-tab.constants' +} from '../../../store/actions'; +import { NETWORKS_FORM_ROUTE } from '../../../helpers/constants/routes'; +import { ENVIRONMENT_TYPE_FULLSCREEN } from '../../../../../shared/constants/app'; +import { NETWORK_TYPE_RPC } from '../../../../../shared/constants/network'; +import { getEnvironmentType } from '../../../../../app/scripts/lib/util'; +import NetworksTab from './networks-tab.component'; +import { defaultNetworksData } from './networks-tab.constants'; const defaultNetworks = defaultNetworksData.map((network) => ({ ...network, viewOnly: true, -})) +})); const mapStateToProps = (state, ownProps) => { const { location: { pathname }, - } = ownProps + } = ownProps; - const environmentType = getEnvironmentType() - const isFullScreen = environmentType === ENVIRONMENT_TYPE_FULLSCREEN + const environmentType = getEnvironmentType(); + const isFullScreen = environmentType === ENVIRONMENT_TYPE_FULLSCREEN; const shouldRenderNetworkForm = - isFullScreen || Boolean(pathname.match(NETWORKS_FORM_ROUTE)) + isFullScreen || Boolean(pathname.match(NETWORKS_FORM_ROUTE)); - const { frequentRpcListDetail, provider } = state.metamask - const { networksTabSelectedRpcUrl, networksTabIsInAddMode } = state.appState + const { frequentRpcListDetail, provider } = state.metamask; + const { networksTabSelectedRpcUrl, networksTabIsInAddMode } = state.appState; const frequentRpcNetworkListDetails = frequentRpcListDetail.map((rpc) => { return { @@ -43,20 +43,20 @@ const mapStateToProps = (state, ownProps) => { chainId: rpc.chainId, ticker: rpc.ticker, blockExplorerUrl: rpc.rpcPrefs?.blockExplorerUrl || '', - } - }) + }; + }); const networksToRender = [ ...defaultNetworks, ...frequentRpcNetworkListDetails, - ] + ]; let selectedNetwork = networksToRender.find( (network) => network.rpcUrl === networksTabSelectedRpcUrl, - ) || {} - const networkIsSelected = Boolean(selectedNetwork.rpcUrl) + ) || {}; + const networkIsSelected = Boolean(selectedNetwork.rpcUrl); - let networkDefaultedToProvider = false + let networkDefaultedToProvider = false; if (!networkIsSelected && !networksTabIsInAddMode) { selectedNetwork = networksToRender.find((network) => { @@ -64,9 +64,9 @@ const mapStateToProps = (state, ownProps) => { network.rpcUrl === provider.rpcUrl || (network.providerType !== NETWORK_TYPE_RPC && network.providerType === provider.type) - ) - }) || {} - networkDefaultedToProvider = true + ); + }) || {}; + networkDefaultedToProvider = true; } return { @@ -79,8 +79,8 @@ const mapStateToProps = (state, ownProps) => { networkDefaultedToProvider, isFullScreen, shouldRenderNetworkForm, - } -} + }; +}; const mapDispatchToProps = (dispatch) => { return { @@ -89,12 +89,12 @@ const mapDispatchToProps = (dispatch) => { setRpcTarget: (newRpc, chainId, ticker, nickname, rpcPrefs) => { return dispatch( updateAndSetCustomRpc(newRpc, chainId, ticker, nickname, rpcPrefs), - ) + ); }, showConfirmDeleteNetworkModal: ({ target, onConfirm }) => { return dispatch( showModal({ name: 'CONFIRM_DELETE_NETWORK', target, onConfirm }), - ) + ); }, displayWarning: (warning) => dispatch(displayWarning(warning)), setNetworksTabAddMode: (isInAddMode) => @@ -102,12 +102,12 @@ const mapDispatchToProps = (dispatch) => { editRpc: (oldRpc, newRpc, chainId, ticker, nickname, rpcPrefs) => { return dispatch( editRpc(oldRpc, newRpc, chainId, ticker, nickname, rpcPrefs), - ) + ); }, - } -} + }; +}; export default compose( withRouter, connect(mapStateToProps, mapDispatchToProps), -)(NetworksTab) +)(NetworksTab); diff --git a/ui/app/pages/settings/security-tab/index.js b/ui/app/pages/settings/security-tab/index.js index 7ffc291a2..8f812e16c 100644 --- a/ui/app/pages/settings/security-tab/index.js +++ b/ui/app/pages/settings/security-tab/index.js @@ -1 +1 @@ -export { default } from './security-tab.container' +export { default } from './security-tab.container'; diff --git a/ui/app/pages/settings/security-tab/security-tab.component.js b/ui/app/pages/settings/security-tab/security-tab.component.js index bf322f528..8eab40ec2 100644 --- a/ui/app/pages/settings/security-tab/security-tab.component.js +++ b/ui/app/pages/settings/security-tab/security-tab.component.js @@ -1,14 +1,14 @@ -import React, { PureComponent } from 'react' -import PropTypes from 'prop-types' -import ToggleButton from '../../../components/ui/toggle-button' -import { REVEAL_SEED_ROUTE } from '../../../helpers/constants/routes' -import Button from '../../../components/ui/button' +import React, { PureComponent } from 'react'; +import PropTypes from 'prop-types'; +import ToggleButton from '../../../components/ui/toggle-button'; +import { REVEAL_SEED_ROUTE } from '../../../helpers/constants/routes'; +import Button from '../../../components/ui/button'; export default class SecurityTab extends PureComponent { static contextTypes = { t: PropTypes.func, metricsEvent: PropTypes.func, - } + }; static propTypes = { warning: PropTypes.string, @@ -19,11 +19,11 @@ export default class SecurityTab extends PureComponent { setShowIncomingTransactionsFeatureFlag: PropTypes.func.isRequired, setUsePhishDetect: PropTypes.func.isRequired, usePhishDetect: PropTypes.bool.isRequired, - } + }; renderSeedWords() { - const { t } = this.context - const { history } = this.props + const { t } = this.context; + const { history } = this.props; return (
    @@ -36,15 +36,15 @@ export default class SecurityTab extends PureComponent { type="danger" large onClick={(event) => { - event.preventDefault() + event.preventDefault(); this.context.metricsEvent({ eventOpts: { category: 'Settings', action: 'Reveal Seed Phrase', name: 'Reveal Seed Phrase', }, - }) - history.push(REVEAL_SEED_ROUTE) + }); + history.push(REVEAL_SEED_ROUTE); }} > {t('revealSeedWords')} @@ -52,12 +52,15 @@ export default class SecurityTab extends PureComponent {
    - ) + ); } renderMetaMetricsOptIn() { - const { t } = this.context - const { participateInMetaMetrics, setParticipateInMetaMetrics } = this.props + const { t } = this.context; + const { + participateInMetaMetrics, + setParticipateInMetaMetrics, + } = this.props; return (
    @@ -78,15 +81,15 @@ export default class SecurityTab extends PureComponent {
    - ) + ); } renderIncomingTransactionsOptIn() { - const { t } = this.context + const { t } = this.context; const { showIncomingTransactions, setShowIncomingTransactionsFeatureFlag, - } = this.props + } = this.props; return (
    @@ -109,12 +112,12 @@ export default class SecurityTab extends PureComponent {
    - ) + ); } renderPhishingDetectionToggle() { - const { t } = this.context - const { usePhishDetect, setUsePhishDetect } = this.props + const { t } = this.context; + const { usePhishDetect, setUsePhishDetect } = this.props; return (
    @@ -135,11 +138,11 @@ export default class SecurityTab extends PureComponent {
    - ) + ); } render() { - const { warning } = this.props + const { warning } = this.props; return (
    @@ -149,6 +152,6 @@ export default class SecurityTab extends PureComponent { {this.renderPhishingDetectionToggle()} {this.renderMetaMetricsOptIn()}
    - ) + ); } } diff --git a/ui/app/pages/settings/security-tab/security-tab.container.js b/ui/app/pages/settings/security-tab/security-tab.container.js index 7860cff2d..e6060f45b 100644 --- a/ui/app/pages/settings/security-tab/security-tab.container.js +++ b/ui/app/pages/settings/security-tab/security-tab.container.js @@ -1,31 +1,31 @@ -import { compose } from 'redux' -import { connect } from 'react-redux' -import { withRouter } from 'react-router-dom' +import { compose } from 'redux'; +import { connect } from 'react-redux'; +import { withRouter } from 'react-router-dom'; import { setFeatureFlag, setParticipateInMetaMetrics, setUsePhishDetect, -} from '../../../store/actions' -import SecurityTab from './security-tab.component' +} from '../../../store/actions'; +import SecurityTab from './security-tab.component'; const mapStateToProps = (state) => { const { appState: { warning }, metamask, - } = state + } = state; const { featureFlags: { showIncomingTransactions } = {}, participateInMetaMetrics, usePhishDetect, - } = metamask + } = metamask; return { warning, showIncomingTransactions, participateInMetaMetrics, usePhishDetect, - } -} + }; +}; const mapDispatchToProps = (dispatch) => { return { @@ -34,10 +34,10 @@ const mapDispatchToProps = (dispatch) => { setShowIncomingTransactionsFeatureFlag: (shouldShow) => dispatch(setFeatureFlag('showIncomingTransactions', shouldShow)), setUsePhishDetect: (val) => dispatch(setUsePhishDetect(val)), - } -} + }; +}; export default compose( withRouter, connect(mapStateToProps, mapDispatchToProps), -)(SecurityTab) +)(SecurityTab); diff --git a/ui/app/pages/settings/security-tab/tests/security-tab.test.js b/ui/app/pages/settings/security-tab/tests/security-tab.test.js index d45a47d35..78b785c4f 100644 --- a/ui/app/pages/settings/security-tab/tests/security-tab.test.js +++ b/ui/app/pages/settings/security-tab/tests/security-tab.test.js @@ -1,11 +1,11 @@ -import assert from 'assert' -import React from 'react' -import sinon from 'sinon' -import { mount } from 'enzyme' -import SecurityTab from '..' +import assert from 'assert'; +import React from 'react'; +import sinon from 'sinon'; +import { mount } from 'enzyme'; +import SecurityTab from '..'; describe('Security Tab', function () { - let wrapper + let wrapper; const props = { revealSeedConfirmation: sinon.spy(), @@ -21,7 +21,7 @@ describe('Security Tab', function () { participateInMetaMetrics: false, setUsePhishDetect: sinon.spy(), usePhishDetect: true, - } + }; beforeEach(function () { wrapper = mount(, { @@ -29,33 +29,33 @@ describe('Security Tab', function () { t: (str) => str, metricsEvent: () => undefined, }, - }) - }) + }); + }); it('navigates to reveal seed words page', function () { - const seedWords = wrapper.find('.button.btn-danger.btn--large') + const seedWords = wrapper.find('.button.btn-danger.btn--large'); - seedWords.simulate('click') - assert(props.history.push.calledOnce) - assert.strictEqual(props.history.push.getCall(0).args[0], '/seed') - }) + seedWords.simulate('click'); + assert(props.history.push.calledOnce); + assert.strictEqual(props.history.push.getCall(0).args[0], '/seed'); + }); it('toggles incoming txs', function () { - const incomingTxs = wrapper.find({ type: 'checkbox' }).at(0) - incomingTxs.simulate('click') - assert(props.setShowIncomingTransactionsFeatureFlag.calledOnce) - }) + const incomingTxs = wrapper.find({ type: 'checkbox' }).at(0); + incomingTxs.simulate('click'); + assert(props.setShowIncomingTransactionsFeatureFlag.calledOnce); + }); it('toggles phishing detection', function () { - const phishDetect = wrapper.find({ type: 'checkbox' }).at(1) - phishDetect.simulate('click') - assert(props.setUsePhishDetect.calledOnce) - }) + const phishDetect = wrapper.find({ type: 'checkbox' }).at(1); + phishDetect.simulate('click'); + assert(props.setUsePhishDetect.calledOnce); + }); it('toggles metaMetrics', function () { - const metaMetrics = wrapper.find({ type: 'checkbox' }).at(2) + const metaMetrics = wrapper.find({ type: 'checkbox' }).at(2); - metaMetrics.simulate('click') - assert(props.setParticipateInMetaMetrics.calledOnce) - }) -}) + metaMetrics.simulate('click'); + assert(props.setParticipateInMetaMetrics.calledOnce); + }); +}); diff --git a/ui/app/pages/settings/settings-tab/index.js b/ui/app/pages/settings/settings-tab/index.js index 9fdaafd3f..4c8fcab38 100644 --- a/ui/app/pages/settings/settings-tab/index.js +++ b/ui/app/pages/settings/settings-tab/index.js @@ -1 +1 @@ -export { default } from './settings-tab.container' +export { default } from './settings-tab.container'; diff --git a/ui/app/pages/settings/settings-tab/settings-tab.component.js b/ui/app/pages/settings/settings-tab/settings-tab.component.js index 65f926c3f..6c1452c02 100644 --- a/ui/app/pages/settings/settings-tab/settings-tab.component.js +++ b/ui/app/pages/settings/settings-tab/settings-tab.component.js @@ -1,35 +1,35 @@ -import React, { PureComponent } from 'react' -import PropTypes from 'prop-types' -import availableCurrencies from '../../../helpers/constants/available-conversions.json' -import SimpleDropdown from '../../../components/app/dropdowns/simple-dropdown' -import ToggleButton from '../../../components/ui/toggle-button' -import locales from '../../../../../app/_locales/index.json' +import React, { PureComponent } from 'react'; +import PropTypes from 'prop-types'; +import availableCurrencies from '../../../helpers/constants/available-conversions.json'; +import SimpleDropdown from '../../../components/app/dropdowns/simple-dropdown'; +import ToggleButton from '../../../components/ui/toggle-button'; +import locales from '../../../../../app/_locales/index.json'; const sortedCurrencies = availableCurrencies.sort((a, b) => { - return a.name.toLocaleLowerCase().localeCompare(b.name.toLocaleLowerCase()) -}) + return a.name.toLocaleLowerCase().localeCompare(b.name.toLocaleLowerCase()); +}); const currencyOptions = sortedCurrencies.map(({ code, name }) => { return { displayValue: `${code.toUpperCase()} - ${name}`, key: code, value: code, - } -}) + }; +}); const localeOptions = locales.map((locale) => { return { displayValue: `${locale.name}`, key: locale.code, value: locale.code, - } -}) + }; +}); export default class SettingsTab extends PureComponent { static contextTypes = { t: PropTypes.func, metricsEvent: PropTypes.func, - } + }; static propTypes = { setUseBlockie: PropTypes.func, @@ -43,11 +43,11 @@ export default class SettingsTab extends PureComponent { nativeCurrency: PropTypes.string, useNativeCurrencyAsPrimaryCurrency: PropTypes.bool, setUseNativeCurrencyAsPrimaryCurrencyPreference: PropTypes.func, - } + }; renderCurrentConversion() { - const { t } = this.context - const { currentCurrency, conversionDate, setCurrentCurrency } = this.props + const { t } = this.context; + const { currentCurrency, conversionDate, setCurrentCurrency } = this.props; return (
    @@ -68,16 +68,16 @@ export default class SettingsTab extends PureComponent {
    - ) + ); } renderCurrentLocale() { - const { t } = this.context - const { updateCurrentLocale, currentLocale } = this.props + const { t } = this.context; + const { updateCurrentLocale, currentLocale } = this.props; const currentLocaleMeta = locales.find( (locale) => locale.code === currentLocale, - ) - const currentLocaleName = currentLocaleMeta ? currentLocaleMeta.name : '' + ); + const currentLocaleName = currentLocaleMeta ? currentLocaleMeta.name : ''; return (
    @@ -100,12 +100,12 @@ export default class SettingsTab extends PureComponent {
    - ) + ); } renderBlockieOptIn() { - const { t } = this.context - const { useBlockie, setUseBlockie } = this.props + const { t } = this.context; + const { useBlockie, setUseBlockie } = this.props; return (
    @@ -123,16 +123,16 @@ export default class SettingsTab extends PureComponent {
    - ) + ); } renderUsePrimaryCurrencyOptions() { - const { t } = this.context + const { t } = this.context; const { nativeCurrency, setUseNativeCurrencyAsPrimaryCurrencyPreference, useNativeCurrencyAsPrimaryCurrency, - } = this.props + } = this.props; return (
    @@ -181,11 +181,11 @@ export default class SettingsTab extends PureComponent {
    - ) + ); } render() { - const { warning } = this.props + const { warning } = this.props; return (
    @@ -195,6 +195,6 @@ export default class SettingsTab extends PureComponent { {this.renderCurrentLocale()} {this.renderBlockieOptIn()}
    - ) + ); } } diff --git a/ui/app/pages/settings/settings-tab/settings-tab.container.js b/ui/app/pages/settings/settings-tab/settings-tab.container.js index 3ebf2627d..ce8de1363 100644 --- a/ui/app/pages/settings/settings-tab/settings-tab.container.js +++ b/ui/app/pages/settings/settings-tab/settings-tab.container.js @@ -1,27 +1,27 @@ -import { connect } from 'react-redux' +import { connect } from 'react-redux'; import { setCurrentCurrency, setUseBlockie, updateCurrentLocale, setUseNativeCurrencyAsPrimaryCurrencyPreference, setParticipateInMetaMetrics, -} from '../../../store/actions' -import { getPreferences } from '../../../selectors' -import SettingsTab from './settings-tab.component' +} from '../../../store/actions'; +import { getPreferences } from '../../../selectors'; +import SettingsTab from './settings-tab.component'; const mapStateToProps = (state) => { const { appState: { warning }, metamask, - } = state + } = state; const { currentCurrency, conversionDate, nativeCurrency, useBlockie, currentLocale, - } = metamask - const { useNativeCurrencyAsPrimaryCurrency } = getPreferences(state) + } = metamask; + const { useNativeCurrencyAsPrimaryCurrency } = getPreferences(state); return { warning, @@ -31,8 +31,8 @@ const mapStateToProps = (state) => { nativeCurrency, useBlockie, useNativeCurrencyAsPrimaryCurrency, - } -} + }; +}; const mapDispatchToProps = (dispatch) => { return { @@ -40,11 +40,11 @@ const mapDispatchToProps = (dispatch) => { setUseBlockie: (value) => dispatch(setUseBlockie(value)), updateCurrentLocale: (key) => dispatch(updateCurrentLocale(key)), setUseNativeCurrencyAsPrimaryCurrencyPreference: (value) => { - return dispatch(setUseNativeCurrencyAsPrimaryCurrencyPreference(value)) + return dispatch(setUseNativeCurrencyAsPrimaryCurrencyPreference(value)); }, setParticipateInMetaMetrics: (val) => dispatch(setParticipateInMetaMetrics(val)), - } -} + }; +}; -export default connect(mapStateToProps, mapDispatchToProps)(SettingsTab) +export default connect(mapStateToProps, mapDispatchToProps)(SettingsTab); diff --git a/ui/app/pages/settings/settings-tab/tests/settings-tab.test.js b/ui/app/pages/settings/settings-tab/tests/settings-tab.test.js index 31b8d96c6..1d1a0b42c 100644 --- a/ui/app/pages/settings/settings-tab/tests/settings-tab.test.js +++ b/ui/app/pages/settings/settings-tab/tests/settings-tab.test.js @@ -1,11 +1,11 @@ -import assert from 'assert' -import React from 'react' -import sinon from 'sinon' -import { mount } from 'enzyme' -import SettingsTab from '..' +import assert from 'assert'; +import React from 'react'; +import sinon from 'sinon'; +import { mount } from 'enzyme'; +import SettingsTab from '..'; describe('Settings Tab', function () { - let wrapper + let wrapper; const props = { setCurrentCurrency: sinon.spy(), @@ -20,40 +20,40 @@ describe('Settings Tab', function () { conversionDate: 1, nativeCurrency: 'eth', useNativeCurrencyAsPrimaryCurrency: true, - } + }; beforeEach(function () { wrapper = mount(, { context: { t: (str) => str, }, - }) - }) + }); + }); it('selects currency', async function () { - const selectCurrency = wrapper.find({ placeholder: 'selectCurrency' }) + const selectCurrency = wrapper.find({ placeholder: 'selectCurrency' }); - selectCurrency.props().onSelect('eur') - assert(props.setCurrentCurrency.calledOnce) - }) + selectCurrency.props().onSelect('eur'); + assert(props.setCurrentCurrency.calledOnce); + }); it('selects locale', async function () { - const selectLocale = wrapper.find({ placeholder: 'selectLocale' }) + const selectLocale = wrapper.find({ placeholder: 'selectLocale' }); - await selectLocale.props().onSelect('ja') - assert(props.updateCurrentLocale.calledOnce) - }) + await selectLocale.props().onSelect('ja'); + assert(props.updateCurrentLocale.calledOnce); + }); it('sets fiat primary currency', function () { - const selectFiat = wrapper.find('#fiat-primary-currency') + const selectFiat = wrapper.find('#fiat-primary-currency'); - selectFiat.simulate('change') - assert(props.setUseNativeCurrencyAsPrimaryCurrencyPreference.calledOnce) - }) + selectFiat.simulate('change'); + assert(props.setUseNativeCurrencyAsPrimaryCurrencyPreference.calledOnce); + }); it('toggles blockies', function () { - const toggleBlockies = wrapper.find({ type: 'checkbox' }) + const toggleBlockies = wrapper.find({ type: 'checkbox' }); - toggleBlockies.simulate('click') - assert(props.setUseBlockie.calledOnce) - }) -}) + toggleBlockies.simulate('click'); + assert(props.setUseBlockie.calledOnce); + }); +}); diff --git a/ui/app/pages/settings/settings.component.js b/ui/app/pages/settings/settings.component.js index 6229b95fa..2b02eccfd 100644 --- a/ui/app/pages/settings/settings.component.js +++ b/ui/app/pages/settings/settings.component.js @@ -1,8 +1,8 @@ -import React, { PureComponent } from 'react' -import PropTypes from 'prop-types' -import { Switch, Route, matchPath } from 'react-router-dom' -import classnames from 'classnames' -import TabBar from '../../components/app/tab-bar' +import React, { PureComponent } from 'react'; +import PropTypes from 'prop-types'; +import { Switch, Route, matchPath } from 'react-router-dom'; +import classnames from 'classnames'; +import TabBar from '../../components/app/tab-bar'; import { ALERTS_ROUTE, ADVANCED_ROUTE, @@ -18,14 +18,14 @@ import { CONTACT_MY_ACCOUNTS_ROUTE, CONTACT_MY_ACCOUNTS_VIEW_ROUTE, CONTACT_MY_ACCOUNTS_EDIT_ROUTE, -} from '../../helpers/constants/routes' -import SettingsTab from './settings-tab' -import AlertsTab from './alerts-tab' -import NetworksTab from './networks-tab' -import AdvancedTab from './advanced-tab' -import InfoTab from './info-tab' -import SecurityTab from './security-tab' -import ContactListTab from './contact-list-tab' +} from '../../helpers/constants/routes'; +import SettingsTab from './settings-tab'; +import AlertsTab from './alerts-tab'; +import NetworksTab from './networks-tab'; +import AdvancedTab from './advanced-tab'; +import InfoTab from './info-tab'; +import SecurityTab from './security-tab'; +import ContactListTab from './contact-list-tab'; class SettingsPage extends PureComponent { static propTypes = { @@ -40,11 +40,11 @@ class SettingsPage extends PureComponent { breadCrumbTextKey: PropTypes.string, initialBreadCrumbKey: PropTypes.string, mostRecentOverviewPage: PropTypes.string.isRequired, - } + }; static contextTypes = { t: PropTypes.func, - } + }; render() { const { @@ -52,7 +52,7 @@ class SettingsPage extends PureComponent { backRoute, currentPath, mostRecentOverviewPage, - } = this.props + } = this.props; return (
    - ) + ); } renderTitle() { - const { t } = this.context - const { isPopup, pathnameI18nKey, addressName } = this.props + const { t } = this.context; + const { isPopup, pathnameI18nKey, addressName } = this.props; - let titleText + let titleText; if (isPopup && addressName) { - titleText = addressName + titleText = addressName; } else if (pathnameI18nKey && isPopup) { - titleText = t(pathnameI18nKey) + titleText = t(pathnameI18nKey); } else { - titleText = t('settings') + titleText = t('settings'); } - return
    {titleText}
    + return
    {titleText}
    ; } renderSubHeader() { - const { t } = this.context + const { t } = this.context; const { currentPath, isPopup, @@ -115,16 +115,16 @@ class SettingsPage extends PureComponent { breadCrumbTextKey, history, initialBreadCrumbKey, - } = this.props + } = this.props; - let subheaderText + let subheaderText; if (isPopup && isAddressEntryPage) { - subheaderText = t('settings') + subheaderText = t('settings'); } else if (initialBreadCrumbKey) { - subheaderText = t(initialBreadCrumbKey) + subheaderText = t(initialBreadCrumbKey); } else { - subheaderText = t(pathnameI18nKey || 'general') + subheaderText = t(pathnameI18nKey || 'general'); } return ( @@ -154,12 +154,12 @@ class SettingsPage extends PureComponent { )} ) - ) + ); } renderTabs() { - const { history, currentPath } = this.props - const { t } = this.context + const { history, currentPath } = this.props; + const { t } = this.context; return ( { if (key === GENERAL_ROUTE && currentPath === SETTINGS_ROUTE) { - return true + return true; } - return matchPath(currentPath, { path: key, exact: true }) + return matchPath(currentPath, { path: key, exact: true }); }} onSelect={(key) => history.push(key)} /> - ) + ); } renderContent() { @@ -249,8 +249,8 @@ class SettingsPage extends PureComponent { /> - ) + ); } } -export default SettingsPage +export default SettingsPage; diff --git a/ui/app/pages/settings/settings.container.js b/ui/app/pages/settings/settings.container.js index d35fbbe6d..f965e525c 100644 --- a/ui/app/pages/settings/settings.container.js +++ b/ui/app/pages/settings/settings.container.js @@ -1,11 +1,11 @@ -import { compose } from 'redux' -import { connect } from 'react-redux' -import { withRouter } from 'react-router-dom' -import { getAddressBookEntryName } from '../../selectors' -import { isValidAddress } from '../../helpers/utils/util' -import { ENVIRONMENT_TYPE_POPUP } from '../../../../shared/constants/app' -import { getEnvironmentType } from '../../../../app/scripts/lib/util' -import { getMostRecentOverviewPage } from '../../ducks/history/history' +import { compose } from 'redux'; +import { connect } from 'react-redux'; +import { withRouter } from 'react-router-dom'; +import { getAddressBookEntryName } from '../../selectors'; +import { isValidAddress } from '../../helpers/utils/util'; +import { ENVIRONMENT_TYPE_POPUP } from '../../../../shared/constants/app'; +import { getEnvironmentType } from '../../../../app/scripts/lib/util'; +import { getMostRecentOverviewPage } from '../../ducks/history/history'; import { ABOUT_US_ROUTE, @@ -23,8 +23,8 @@ import { NETWORKS_ROUTE, SECURITY_ROUTE, SETTINGS_ROUTE, -} from '../../helpers/constants/routes' -import Settings from './settings.component' +} from '../../helpers/constants/routes'; +import Settings from './settings.component'; const ROUTES_TO_I18N_KEYS = { [ABOUT_US_ROUTE]: 'about', @@ -39,51 +39,51 @@ const ROUTES_TO_I18N_KEYS = { [NETWORKS_ROUTE]: 'networks', [NETWORKS_FORM_ROUTE]: 'networks', [SECURITY_ROUTE]: 'securityAndPrivacy', -} +}; const mapStateToProps = (state, ownProps) => { - const { location } = ownProps - const { pathname } = location - const pathNameTail = pathname.match(/[^/]+$/u)[0] + const { location } = ownProps; + const { pathname } = location; + const pathNameTail = pathname.match(/[^/]+$/u)[0]; - const isAddressEntryPage = pathNameTail.includes('0x') - const isMyAccountsPage = pathname.match('my-accounts') - const isAddContactPage = Boolean(pathname.match(CONTACT_ADD_ROUTE)) - const isEditContactPage = Boolean(pathname.match(CONTACT_EDIT_ROUTE)) + const isAddressEntryPage = pathNameTail.includes('0x'); + const isMyAccountsPage = pathname.match('my-accounts'); + const isAddContactPage = Boolean(pathname.match(CONTACT_ADD_ROUTE)); + const isEditContactPage = Boolean(pathname.match(CONTACT_EDIT_ROUTE)); const isEditMyAccountsContactPage = Boolean( pathname.match(CONTACT_MY_ACCOUNTS_EDIT_ROUTE), - ) - const isNetworksFormPage = Boolean(pathname.match(NETWORKS_FORM_ROUTE)) + ); + const isNetworksFormPage = Boolean(pathname.match(NETWORKS_FORM_ROUTE)); - const isPopup = getEnvironmentType() === ENVIRONMENT_TYPE_POPUP - const pathnameI18nKey = ROUTES_TO_I18N_KEYS[pathname] + const isPopup = getEnvironmentType() === ENVIRONMENT_TYPE_POPUP; + const pathnameI18nKey = ROUTES_TO_I18N_KEYS[pathname]; - let backRoute = SETTINGS_ROUTE + let backRoute = SETTINGS_ROUTE; if (isMyAccountsPage && isAddressEntryPage) { - backRoute = CONTACT_MY_ACCOUNTS_ROUTE + backRoute = CONTACT_MY_ACCOUNTS_ROUTE; } else if (isEditContactPage) { - backRoute = `${CONTACT_VIEW_ROUTE}/${pathNameTail}` + backRoute = `${CONTACT_VIEW_ROUTE}/${pathNameTail}`; } else if (isEditMyAccountsContactPage) { - backRoute = `${CONTACT_MY_ACCOUNTS_VIEW_ROUTE}/${pathNameTail}` + backRoute = `${CONTACT_MY_ACCOUNTS_VIEW_ROUTE}/${pathNameTail}`; } else if (isAddressEntryPage || isMyAccountsPage || isAddContactPage) { - backRoute = CONTACT_LIST_ROUTE + backRoute = CONTACT_LIST_ROUTE; } else if (isNetworksFormPage) { - backRoute = NETWORKS_ROUTE + backRoute = NETWORKS_ROUTE; } - let initialBreadCrumbRoute - let breadCrumbTextKey - let initialBreadCrumbKey + let initialBreadCrumbRoute; + let breadCrumbTextKey; + let initialBreadCrumbKey; if (isMyAccountsPage) { - initialBreadCrumbRoute = CONTACT_LIST_ROUTE - breadCrumbTextKey = 'myWalletAccounts' - initialBreadCrumbKey = ROUTES_TO_I18N_KEYS[initialBreadCrumbRoute] + initialBreadCrumbRoute = CONTACT_LIST_ROUTE; + breadCrumbTextKey = 'myWalletAccounts'; + initialBreadCrumbKey = ROUTES_TO_I18N_KEYS[initialBreadCrumbRoute]; } const addressName = getAddressBookEntryName( state, isValidAddress(pathNameTail) ? pathNameTail : '', - ) + ); return { isAddressEntryPage, @@ -97,7 +97,7 @@ const mapStateToProps = (state, ownProps) => { breadCrumbTextKey, initialBreadCrumbKey, mostRecentOverviewPage: getMostRecentOverviewPage(state), - } -} + }; +}; -export default compose(withRouter, connect(mapStateToProps))(Settings) +export default compose(withRouter, connect(mapStateToProps))(Settings); diff --git a/ui/app/pages/swaps/actionable-message/actionable-message.js b/ui/app/pages/swaps/actionable-message/actionable-message.js index bdb46c371..cf24ff9f6 100644 --- a/ui/app/pages/swaps/actionable-message/actionable-message.js +++ b/ui/app/pages/swaps/actionable-message/actionable-message.js @@ -1,6 +1,6 @@ -import React from 'react' -import PropTypes from 'prop-types' -import classnames from 'classnames' +import React from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; export default function ActionableMessage({ message = '', @@ -38,7 +38,7 @@ export default function ActionableMessage({ )} - ) + ); } ActionableMessage.propTypes = { @@ -52,4 +52,4 @@ ActionableMessage.propTypes = { onClick: PropTypes.func, }), className: PropTypes.string, -} +}; diff --git a/ui/app/pages/swaps/actionable-message/actionable-message.stories.js b/ui/app/pages/swaps/actionable-message/actionable-message.stories.js index 66ab6031d..b56b79e56 100644 --- a/ui/app/pages/swaps/actionable-message/actionable-message.stories.js +++ b/ui/app/pages/swaps/actionable-message/actionable-message.stories.js @@ -1,11 +1,11 @@ -import React from 'react' -import { action } from '@storybook/addon-actions' -import { text } from '@storybook/addon-knobs' -import ActionableMessage from '.' +import React from 'react'; +import { action } from '@storybook/addon-actions'; +import { text } from '@storybook/addon-knobs'; +import ActionableMessage from '.'; export default { title: 'ActionableMessage', -} +}; export const NoAction = () => (
    @@ -16,7 +16,7 @@ export const NoAction = () => ( )} />
    -) +); export const OneAction = () => (
    @@ -31,7 +31,7 @@ export const OneAction = () => ( }} />
    -) +); export const TwoActions = () => (
    @@ -51,7 +51,7 @@ export const TwoActions = () => ( className="actionable-message--warning" />
    -) +); export const LeftAligned = () => (
    @@ -67,4 +67,4 @@ export const LeftAligned = () => ( className="actionable-message--left-aligned" />
    -) +); diff --git a/ui/app/pages/swaps/actionable-message/index.js b/ui/app/pages/swaps/actionable-message/index.js index c6edbc359..83a781bcd 100644 --- a/ui/app/pages/swaps/actionable-message/index.js +++ b/ui/app/pages/swaps/actionable-message/index.js @@ -1 +1 @@ -export { default } from './actionable-message' +export { default } from './actionable-message'; diff --git a/ui/app/pages/swaps/awaiting-swap/awaiting-swap.js b/ui/app/pages/swaps/awaiting-swap/awaiting-swap.js index 5a35c724e..b5908d0ee 100644 --- a/ui/app/pages/swaps/awaiting-swap/awaiting-swap.js +++ b/ui/app/pages/swaps/awaiting-swap/awaiting-swap.js @@ -1,12 +1,12 @@ -import EventEmitter from 'events' -import React, { useContext, useRef, useState } from 'react' -import { useDispatch, useSelector } from 'react-redux' -import PropTypes from 'prop-types' -import { useHistory } from 'react-router-dom' -import { I18nContext } from '../../../contexts/i18n' -import { useNewMetricEvent } from '../../../hooks/useMetricEvent' -import { MetaMetricsContext } from '../../../contexts/metametrics.new' -import { getCurrentCurrency, getUSDConversionRate } from '../../../selectors' +import EventEmitter from 'events'; +import React, { useContext, useRef, useState } from 'react'; +import { useDispatch, useSelector } from 'react-redux'; +import PropTypes from 'prop-types'; +import { useHistory } from 'react-router-dom'; +import { I18nContext } from '../../../contexts/i18n'; +import { useNewMetricEvent } from '../../../hooks/useMetricEvent'; +import { MetaMetricsContext } from '../../../contexts/metametrics.new'; +import { getCurrentCurrency, getUSDConversionRate } from '../../../selectors'; import { getUsedQuote, getFetchParams, @@ -16,25 +16,25 @@ import { navigateBackToBuildQuote, prepareForRetryGetQuotes, prepareToLeaveSwaps, -} from '../../../ducks/swaps/swaps' -import Mascot from '../../../components/ui/mascot' -import PulseLoader from '../../../components/ui/pulse-loader' -import { getBlockExplorerUrlForTx } from '../../../helpers/utils/transactions.util' +} from '../../../ducks/swaps/swaps'; +import Mascot from '../../../components/ui/mascot'; +import PulseLoader from '../../../components/ui/pulse-loader'; +import { getBlockExplorerUrlForTx } from '../../../helpers/utils/transactions.util'; import { QUOTES_EXPIRED_ERROR, SWAP_FAILED_ERROR, ERROR_FETCHING_QUOTES, QUOTES_NOT_AVAILABLE_ERROR, OFFLINE_FOR_MAINTENANCE, -} from '../../../helpers/constants/swaps' -import { ASSET_ROUTE, DEFAULT_ROUTE } from '../../../helpers/constants/routes' +} from '../../../helpers/constants/swaps'; +import { ASSET_ROUTE, DEFAULT_ROUTE } from '../../../helpers/constants/routes'; -import { getRenderableNetworkFeesForQuote } from '../swaps.util' -import SwapsFooter from '../swaps-footer' -import SwapFailureIcon from './swap-failure-icon' -import SwapSuccessIcon from './swap-success-icon' -import QuotesTimeoutIcon from './quotes-timeout-icon' -import ViewOnEtherScanLink from './view-on-ether-scan-link' +import { getRenderableNetworkFeesForQuote } from '../swaps.util'; +import SwapsFooter from '../swaps-footer'; +import SwapFailureIcon from './swap-failure-icon'; +import SwapSuccessIcon from './swap-success-icon'; +import QuotesTimeoutIcon from './quotes-timeout-icon'; +import ViewOnEtherScanLink from './view-on-ether-scan-link'; export default function AwaitingSwap({ swapComplete, @@ -47,25 +47,25 @@ export default function AwaitingSwap({ inputValue, maxSlippage, }) { - const t = useContext(I18nContext) - const metaMetricsEvent = useContext(MetaMetricsContext) - const history = useHistory() - const dispatch = useDispatch() - const animationEventEmitter = useRef(new EventEmitter()) + const t = useContext(I18nContext); + const metaMetricsEvent = useContext(MetaMetricsContext); + const history = useHistory(); + const dispatch = useDispatch(); + const animationEventEmitter = useRef(new EventEmitter()); - const fetchParams = useSelector(getFetchParams) - const { destinationTokenInfo, sourceTokenInfo } = fetchParams?.metaData || {} - const usedQuote = useSelector(getUsedQuote) - const approveTxParams = useSelector(getApproveTxParams) - const swapsGasPrice = useSelector(getUsedSwapsGasPrice) - const currentCurrency = useSelector(getCurrentCurrency) - const usdConversionRate = useSelector(getUSDConversionRate) + const fetchParams = useSelector(getFetchParams); + const { destinationTokenInfo, sourceTokenInfo } = fetchParams?.metaData || {}; + const usedQuote = useSelector(getUsedQuote); + const approveTxParams = useSelector(getApproveTxParams); + const swapsGasPrice = useSelector(getUsedSwapsGasPrice); + const currentCurrency = useSelector(getCurrentCurrency); + const usdConversionRate = useSelector(getUSDConversionRate); const [trackedQuotesExpiredEvent, setTrackedQuotesExpiredEvent] = useState( false, - ) + ); - let feeinUnformattedFiat + let feeinUnformattedFiat; if (usedQuote && swapsGasPrice) { const renderableNetworkFees = getRenderableNetworkFeesForQuote( @@ -77,8 +77,8 @@ export default function AwaitingSwap({ usedQuote?.trade?.value, sourceTokenInfo?.symbol, usedQuote.sourceAmount, - ) - feeinUnformattedFiat = renderableNetworkFees.rawNetworkFees + ); + feeinUnformattedFiat = renderableNetworkFees.rawNetworkFees; } const quotesExpiredEvent = useNewMetricEvent({ @@ -93,58 +93,58 @@ export default function AwaitingSwap({ gas_fees: feeinUnformattedFiat, }, category: 'swaps', - }) + }); const blockExplorerUrl = - txHash && getBlockExplorerUrlForTx(networkId, txHash, rpcPrefs) + txHash && getBlockExplorerUrlForTx(networkId, txHash, rpcPrefs); - let headerText - let statusImage - let descriptionText - let submitText - let content + let headerText; + let statusImage; + let descriptionText; + let submitText; + let content; if (errorKey === OFFLINE_FOR_MAINTENANCE) { - headerText = t('offlineForMaintenance') - descriptionText = t('metamaskSwapsOfflineDescription') - submitText = t('close') - statusImage = + headerText = t('offlineForMaintenance'); + descriptionText = t('metamaskSwapsOfflineDescription'); + submitText = t('close'); + statusImage = ; } else if (errorKey === SWAP_FAILED_ERROR) { - headerText = t('swapFailedErrorTitle') - descriptionText = t('swapFailedErrorDescription') - submitText = t('tryAgain') - statusImage = + headerText = t('swapFailedErrorTitle'); + descriptionText = t('swapFailedErrorDescription'); + submitText = t('tryAgain'); + statusImage = ; content = blockExplorerUrl && ( - ) + ); } else if (errorKey === QUOTES_EXPIRED_ERROR) { - headerText = t('swapQuotesExpiredErrorTitle') - descriptionText = t('swapQuotesExpiredErrorDescription') - submitText = t('tryAgain') - statusImage = + headerText = t('swapQuotesExpiredErrorTitle'); + descriptionText = t('swapQuotesExpiredErrorDescription'); + submitText = t('tryAgain'); + statusImage = ; if (!trackedQuotesExpiredEvent) { - setTrackedQuotesExpiredEvent(true) - quotesExpiredEvent() + setTrackedQuotesExpiredEvent(true); + quotesExpiredEvent(); } } else if (errorKey === ERROR_FETCHING_QUOTES) { - headerText = t('swapFetchingQuotesErrorTitle') - descriptionText = t('swapFetchingQuotesErrorDescription') - submitText = t('back') - statusImage = + headerText = t('swapFetchingQuotesErrorTitle'); + descriptionText = t('swapFetchingQuotesErrorDescription'); + submitText = t('back'); + statusImage = ; } else if (errorKey === QUOTES_NOT_AVAILABLE_ERROR) { - headerText = t('swapQuotesNotAvailableErrorTitle') - descriptionText = t('swapQuotesNotAvailableErrorDescription') - submitText = t('tryAgain') - statusImage = + headerText = t('swapQuotesNotAvailableErrorTitle'); + descriptionText = t('swapQuotesNotAvailableErrorDescription'); + submitText = t('tryAgain'); + statusImage = ; } else if (!errorKey && !swapComplete) { - headerText = t('swapProcessing') - statusImage = - submitText = t('swapsViewInActivity') + headerText = t('swapProcessing'); + statusImage = ; + submitText = t('swapsViewInActivity'); descriptionText = t('swapOnceTransactionHasProcess', [ {destinationTokenInfo.symbol} , - ]) + ]); content = blockExplorerUrl && ( - ) + ); } else if (!errorKey && swapComplete) { - headerText = t('swapTransactionComplete') - statusImage = - submitText = t('swapViewToken', [destinationTokenInfo.symbol]) + headerText = t('swapTransactionComplete'); + statusImage = ; + submitText = t('swapViewToken', [destinationTokenInfo.symbol]); descriptionText = t('swapTokenAvailable', [ {`${tokensReceived || ''} ${destinationTokenInfo.symbol}`} , - ]) + ]); content = blockExplorerUrl && ( - ) + ); } return ( @@ -199,10 +199,10 @@ export default function AwaitingSwap({ { if (errorKey === OFFLINE_FOR_MAINTENANCE) { - await dispatch(prepareToLeaveSwaps()) - history.push(DEFAULT_ROUTE) + await dispatch(prepareToLeaveSwaps()); + history.push(DEFAULT_ROUTE); } else if (errorKey === QUOTES_EXPIRED_ERROR) { - dispatch(prepareForRetryGetQuotes()) + dispatch(prepareForRetryGetQuotes()); await dispatch( fetchQuotesAndSetQuoteState( history, @@ -210,13 +210,13 @@ export default function AwaitingSwap({ maxSlippage, metaMetricsEvent, ), - ) + ); } else if (errorKey) { - await dispatch(navigateBackToBuildQuote(history)) + await dispatch(navigateBackToBuildQuote(history)); } else if (destinationTokenInfo?.symbol === 'ETH') { - history.push(DEFAULT_ROUTE) + history.push(DEFAULT_ROUTE); } else { - history.push(`${ASSET_ROUTE}/${destinationTokenInfo?.address}`) + history.push(`${ASSET_ROUTE}/${destinationTokenInfo?.address}`); } }} onCancel={async () => await dispatch(navigateBackToBuildQuote(history))} @@ -225,7 +225,7 @@ export default function AwaitingSwap({ hideCancel={errorKey !== QUOTES_EXPIRED_ERROR} /> - ) + ); } AwaitingSwap.propTypes = { @@ -244,4 +244,4 @@ AwaitingSwap.propTypes = { submittingSwap: PropTypes.bool, inputValue: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), maxSlippage: PropTypes.number, -} +}; diff --git a/ui/app/pages/swaps/awaiting-swap/index.js b/ui/app/pages/swaps/awaiting-swap/index.js index c82d6690c..12efcc4aa 100644 --- a/ui/app/pages/swaps/awaiting-swap/index.js +++ b/ui/app/pages/swaps/awaiting-swap/index.js @@ -1 +1 @@ -export { default } from './awaiting-swap' +export { default } from './awaiting-swap'; diff --git a/ui/app/pages/swaps/awaiting-swap/quotes-timeout-icon.js b/ui/app/pages/swaps/awaiting-swap/quotes-timeout-icon.js index ae21dbee8..7a2783e4b 100644 --- a/ui/app/pages/swaps/awaiting-swap/quotes-timeout-icon.js +++ b/ui/app/pages/swaps/awaiting-swap/quotes-timeout-icon.js @@ -1,4 +1,4 @@ -import React from 'react' +import React from 'react'; export default function QuotesTimeoutIcon() { return ( @@ -14,5 +14,5 @@ export default function QuotesTimeoutIcon() { fill="#037DD6" /> - ) + ); } diff --git a/ui/app/pages/swaps/awaiting-swap/swap-failure-icon.js b/ui/app/pages/swaps/awaiting-swap/swap-failure-icon.js index a195663f5..a5cb34480 100644 --- a/ui/app/pages/swaps/awaiting-swap/swap-failure-icon.js +++ b/ui/app/pages/swaps/awaiting-swap/swap-failure-icon.js @@ -1,4 +1,4 @@ -import React from 'react' +import React from 'react'; export default function SwapFailureIcon() { return ( @@ -14,5 +14,5 @@ export default function SwapFailureIcon() { fill="#D73A49" /> - ) + ); } diff --git a/ui/app/pages/swaps/awaiting-swap/swap-success-icon.js b/ui/app/pages/swaps/awaiting-swap/swap-success-icon.js index 471e4414f..ffe46d5cb 100644 --- a/ui/app/pages/swaps/awaiting-swap/swap-success-icon.js +++ b/ui/app/pages/swaps/awaiting-swap/swap-success-icon.js @@ -1,4 +1,4 @@ -import React from 'react' +import React from 'react'; export default function SwapSuccessIcon() { return ( @@ -14,5 +14,5 @@ export default function SwapSuccessIcon() { fill="#28A745" /> - ) + ); } diff --git a/ui/app/pages/swaps/awaiting-swap/view-on-ether-scan-link/index.js b/ui/app/pages/swaps/awaiting-swap/view-on-ether-scan-link/index.js index a8767653a..6aa4a3347 100644 --- a/ui/app/pages/swaps/awaiting-swap/view-on-ether-scan-link/index.js +++ b/ui/app/pages/swaps/awaiting-swap/view-on-ether-scan-link/index.js @@ -1 +1 @@ -export { default } from './view-on-ether-scan-link' +export { default } from './view-on-ether-scan-link'; diff --git a/ui/app/pages/swaps/awaiting-swap/view-on-ether-scan-link/view-on-ether-scan-link.js b/ui/app/pages/swaps/awaiting-swap/view-on-ether-scan-link/view-on-ether-scan-link.js index 10354800c..bb3d07cda 100644 --- a/ui/app/pages/swaps/awaiting-swap/view-on-ether-scan-link/view-on-ether-scan-link.js +++ b/ui/app/pages/swaps/awaiting-swap/view-on-ether-scan-link/view-on-ether-scan-link.js @@ -1,14 +1,14 @@ -import React, { useContext } from 'react' -import PropTypes from 'prop-types' -import classnames from 'classnames' -import { I18nContext } from '../../../../contexts/i18n' +import React, { useContext } from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; +import { I18nContext } from '../../../../contexts/i18n'; export default function ViewOnEtherScanLink({ txHash, blockExplorerUrl, isCustomBlockExplorerUrl, }) { - const t = useContext(I18nContext) + const t = useContext(I18nContext); return (
    - ) + ); } ViewOnEtherScanLink.propTypes = { txHash: PropTypes.string, blockExplorerUrl: PropTypes.string, isCustomBlockExplorerUrl: PropTypes.bool, -} +}; diff --git a/ui/app/pages/swaps/build-quote/build-quote.js b/ui/app/pages/swaps/build-quote/build-quote.js index c8ce65e88..4b0975673 100644 --- a/ui/app/pages/swaps/build-quote/build-quote.js +++ b/ui/app/pages/swaps/build-quote/build-quote.js @@ -1,19 +1,19 @@ -import React, { useContext, useEffect, useState, useCallback } from 'react' -import PropTypes from 'prop-types' -import { useDispatch, useSelector } from 'react-redux' -import classnames from 'classnames' -import { uniqBy } from 'lodash' -import { useHistory } from 'react-router-dom' -import { MetaMetricsContext } from '../../../contexts/metametrics.new' -import { useTokensToSearch } from '../../../hooks/useTokensToSearch' -import { useEqualityCheck } from '../../../hooks/useEqualityCheck' -import { useSwapsEthToken } from '../../../hooks/useSwapsEthToken' -import { I18nContext } from '../../../contexts/i18n' -import DropdownInputPair from '../dropdown-input-pair' -import DropdownSearchList from '../dropdown-search-list' -import SlippageButtons from '../slippage-buttons' -import { getTokens } from '../../../ducks/metamask/metamask' -import InfoTooltip from '../../../components/ui/info-tooltip' +import React, { useContext, useEffect, useState, useCallback } from 'react'; +import PropTypes from 'prop-types'; +import { useDispatch, useSelector } from 'react-redux'; +import classnames from 'classnames'; +import { uniqBy } from 'lodash'; +import { useHistory } from 'react-router-dom'; +import { MetaMetricsContext } from '../../../contexts/metametrics.new'; +import { useTokensToSearch } from '../../../hooks/useTokensToSearch'; +import { useEqualityCheck } from '../../../hooks/useEqualityCheck'; +import { useSwapsEthToken } from '../../../hooks/useSwapsEthToken'; +import { I18nContext } from '../../../contexts/i18n'; +import DropdownInputPair from '../dropdown-input-pair'; +import DropdownSearchList from '../dropdown-search-list'; +import SlippageButtons from '../slippage-buttons'; +import { getTokens } from '../../../ducks/metamask/metamask'; +import InfoTooltip from '../../../components/ui/info-tooltip'; import { fetchQuotesAndSetQuoteState, @@ -24,30 +24,30 @@ import { getBalanceError, getTopAssets, getFetchParams, -} from '../../../ducks/swaps/swaps' +} from '../../../ducks/swaps/swaps'; import { getValueFromWeiHex, hexToDecimal, -} from '../../../helpers/utils/conversions.util' -import { calcTokenAmount } from '../../../helpers/utils/token-util' -import { usePrevious } from '../../../hooks/usePrevious' -import { useTokenTracker } from '../../../hooks/useTokenTracker' -import { useTokenFiatAmount } from '../../../hooks/useTokenFiatAmount' -import { useEthFiatAmount } from '../../../hooks/useEthFiatAmount' +} from '../../../helpers/utils/conversions.util'; +import { calcTokenAmount } from '../../../helpers/utils/token-util'; +import { usePrevious } from '../../../hooks/usePrevious'; +import { useTokenTracker } from '../../../hooks/useTokenTracker'; +import { useTokenFiatAmount } from '../../../hooks/useTokenFiatAmount'; +import { useEthFiatAmount } from '../../../hooks/useEthFiatAmount'; -import { ETH_SWAPS_TOKEN_OBJECT } from '../../../helpers/constants/swaps' +import { ETH_SWAPS_TOKEN_OBJECT } from '../../../helpers/constants/swaps'; -import { resetSwapsPostFetchState, removeToken } from '../../../store/actions' -import { fetchTokenPrice, fetchTokenBalance } from '../swaps.util' -import SwapsFooter from '../swaps-footer' +import { resetSwapsPostFetchState, removeToken } from '../../../store/actions'; +import { fetchTokenPrice, fetchTokenBalance } from '../swaps.util'; +import SwapsFooter from '../swaps-footer'; const fuseSearchKeys = [ { name: 'name', weight: 0.499 }, { name: 'symbol', weight: 0.499 }, { name: 'address', weight: 0.002 }, -] +]; -const MAX_ALLOWED_SLIPPAGE = 15 +const MAX_ALLOWED_SLIPPAGE = 15; export default function BuildQuote({ inputValue, @@ -57,39 +57,39 @@ export default function BuildQuote({ maxSlippage, selectedAccountAddress, }) { - const t = useContext(I18nContext) - const dispatch = useDispatch() - const history = useHistory() - const metaMetricsEvent = useContext(MetaMetricsContext) + const t = useContext(I18nContext); + const dispatch = useDispatch(); + const history = useHistory(); + const metaMetricsEvent = useContext(MetaMetricsContext); const [fetchedTokenExchangeRate, setFetchedTokenExchangeRate] = useState( undefined, - ) + ); - const balanceError = useSelector(getBalanceError) - const fetchParams = useSelector(getFetchParams) + const balanceError = useSelector(getBalanceError); + const fetchParams = useSelector(getFetchParams); const { sourceTokenInfo = {}, destinationTokenInfo = {} } = - fetchParams?.metaData || {} - const tokens = useSelector(getTokens) - const topAssets = useSelector(getTopAssets) - const fromToken = useSelector(getFromToken) - const toToken = useSelector(getToToken) || destinationTokenInfo - const swapsEthToken = useSwapsEthToken() + fetchParams?.metaData || {}; + const tokens = useSelector(getTokens); + const topAssets = useSelector(getTopAssets); + const fromToken = useSelector(getFromToken); + const toToken = useSelector(getToToken) || destinationTokenInfo; + const swapsEthToken = useSwapsEthToken(); const fetchParamsFromToken = - sourceTokenInfo?.symbol === 'ETH' ? swapsEthToken : sourceTokenInfo + sourceTokenInfo?.symbol === 'ETH' ? swapsEthToken : sourceTokenInfo; - const { loading, tokensWithBalances } = useTokenTracker(tokens) + const { loading, tokensWithBalances } = useTokenTracker(tokens); // If the fromToken was set in a call to `onFromSelect` (see below), and that from token has a balance // but is not in tokensWithBalances or tokens, then we want to add it to the usersTokens array so that // the balance of the token can appear in the from token selection dropdown const fromTokenArray = - fromToken?.symbol !== 'ETH' && fromToken?.balance ? [fromToken] : [] + fromToken?.symbol !== 'ETH' && fromToken?.balance ? [fromToken] : []; const usersTokens = uniqBy( [...tokensWithBalances, ...tokens, ...fromTokenArray], 'address', - ) - const memoizedUsersTokens = useEqualityCheck(usersTokens) + ); + const memoizedUsersTokens = useEqualityCheck(usersTokens); const selectedFromToken = useTokensToSearch({ providedTokens: @@ -99,15 +99,15 @@ export default function BuildQuote({ usersTokens: memoizedUsersTokens, onlyEth: (fromToken || fetchParamsFromToken)?.symbol === 'ETH', singleToken: true, - })[0] + })[0]; const tokensToSearch = useTokensToSearch({ usersTokens: memoizedUsersTokens, topTokens: topAssets, - }) + }); const selectedToToken = tokensToSearch.find(({ address }) => address === toToken?.address) || - toToken + toToken; const { address: fromTokenAddress, @@ -115,13 +115,13 @@ export default function BuildQuote({ string: fromTokenString, decimals: fromTokenDecimals, balance: rawFromTokenBalance, - } = selectedFromToken || {} + } = selectedFromToken || {}; const fromTokenBalance = rawFromTokenBalance && - calcTokenAmount(rawFromTokenBalance, fromTokenDecimals).toString(10) + calcTokenAmount(rawFromTokenBalance, fromTokenDecimals).toString(10); - const prevFromTokenBalance = usePrevious(fromTokenBalance) + const prevFromTokenBalance = usePrevious(fromTokenBalance); const swapFromTokenFiatValue = useTokenFiatAmount( fromTokenAddress, @@ -131,14 +131,14 @@ export default function BuildQuote({ showFiat: true, }, true, - ) + ); const swapFromEthFiatValue = useEthFiatAmount( inputValue || 0, { showFiat: true }, true, - ) + ); const swapFromFiatValue = - fromTokenSymbol === 'ETH' ? swapFromEthFiatValue : swapFromTokenFiatValue + fromTokenSymbol === 'ETH' ? swapFromEthFiatValue : swapFromTokenFiatValue; const onFromSelect = (token) => { if ( @@ -148,11 +148,11 @@ export default function BuildQuote({ ) { fetchTokenPrice(token.address).then((rate) => { if (rate !== null && rate !== undefined) { - setFetchedTokenExchangeRate(rate) + setFetchedTokenExchangeRate(rate); } - }) + }); } else { - setFetchedTokenExchangeRate(null) + setFetchedTokenExchangeRate(null); } if ( token?.address && @@ -163,63 +163,63 @@ export default function BuildQuote({ fetchTokenBalance(token.address, selectedAccountAddress).then( (fetchedBalance) => { if (fetchedBalance?.balance) { - const balanceAsDecString = fetchedBalance.balance.toString(10) + const balanceAsDecString = fetchedBalance.balance.toString(10); const userTokenBalance = calcTokenAmount( balanceAsDecString, token.decimals, - ) + ); dispatch( setSwapsFromToken({ ...token, string: userTokenBalance.toString(10), balance: balanceAsDecString, }), - ) + ); } }, - ) + ); } - dispatch(setSwapsFromToken(token)) + dispatch(setSwapsFromToken(token)); onInputChange( token?.address ? inputValue : '', token.string, token.decimals, - ) - } + ); + }; - const { destinationTokenAddedForSwap } = fetchParams || {} - const { address: toAddress } = toToken || {} + const { destinationTokenAddedForSwap } = fetchParams || {}; + const { address: toAddress } = toToken || {}; const onToSelect = useCallback( (token) => { if (destinationTokenAddedForSwap && token.address !== toAddress) { - dispatch(removeToken(toAddress)) + dispatch(removeToken(toAddress)); } - dispatch(setSwapToToken(token)) + dispatch(setSwapToToken(token)); }, [dispatch, destinationTokenAddedForSwap, toAddress], - ) + ); const hideDropdownItemIf = useCallback( (item) => item.address === fromTokenAddress, [fromTokenAddress], - ) + ); const tokensWithBalancesFromToken = tokensWithBalances.find( (token) => token.address === fromToken?.address, - ) + ); const previousTokensWithBalancesFromToken = usePrevious( tokensWithBalancesFromToken, - ) + ); useEffect(() => { const notEth = - tokensWithBalancesFromToken?.address !== ETH_SWAPS_TOKEN_OBJECT.address + tokensWithBalancesFromToken?.address !== ETH_SWAPS_TOKEN_OBJECT.address; const addressesAreTheSame = tokensWithBalancesFromToken?.address === - previousTokensWithBalancesFromToken?.address + previousTokensWithBalancesFromToken?.address; const balanceHasChanged = tokensWithBalancesFromToken?.balance !== - previousTokensWithBalancesFromToken?.balance + previousTokensWithBalancesFromToken?.balance; if (notEth && addressesAreTheSame && balanceHasChanged) { dispatch( setSwapsFromToken({ @@ -227,14 +227,14 @@ export default function BuildQuote({ balance: tokensWithBalancesFromToken?.balance, string: tokensWithBalancesFromToken?.string, }), - ) + ); } }, [ dispatch, tokensWithBalancesFromToken, previousTokensWithBalancesFromToken, fromToken, - ]) + ]); // If the eth balance changes while on build quote, we update the selected from token useEffect(() => { @@ -252,19 +252,19 @@ export default function BuildQuote({ toDenomination: 'ETH', }), }), - ) + ); } - }, [dispatch, fromToken, ethBalance]) + }, [dispatch, fromToken, ethBalance]); useEffect(() => { if (prevFromTokenBalance !== fromTokenBalance) { - onInputChange(inputValue, fromTokenBalance) + onInputChange(inputValue, fromTokenBalance); } - }, [onInputChange, prevFromTokenBalance, inputValue, fromTokenBalance]) + }, [onInputChange, prevFromTokenBalance, inputValue, fromTokenBalance]); useEffect(() => { - dispatch(resetSwapsPostFetchState()) - }, [dispatch]) + dispatch(resetSwapsPostFetchState()); + }, [dispatch]); return (
    @@ -286,7 +286,7 @@ export default function BuildQuote({ onSelect={onFromSelect} itemsToSearch={tokensToSearch} onInputChange={(value) => { - onInputChange(value, fromTokenBalance) + onInputChange(value, fromTokenBalance); }} inputValue={inputValue} leftValue={inputValue && swapFromFiatValue} @@ -332,8 +332,8 @@ export default function BuildQuote({
    - ) + ); } BuildQuote.propTypes = { @@ -431,4 +431,4 @@ BuildQuote.propTypes = { ethBalance: PropTypes.string, setMaxSlippage: PropTypes.func, selectedAccountAddress: PropTypes.string, -} +}; diff --git a/ui/app/pages/swaps/build-quote/build-quote.stories.js b/ui/app/pages/swaps/build-quote/build-quote.stories.js index 9a6eaf221..65f16ab83 100644 --- a/ui/app/pages/swaps/build-quote/build-quote.stories.js +++ b/ui/app/pages/swaps/build-quote/build-quote.stories.js @@ -1,8 +1,8 @@ -import React, { useState } from 'react' -import { action } from '@storybook/addon-actions' -import { boolean } from '@storybook/addon-knobs' -import DropdownInputPair from '../dropdown-input-pair' -import DropdownSearchList from '../dropdown-search-list' +import React, { useState } from 'react'; +import { action } from '@storybook/addon-actions'; +import { boolean } from '@storybook/addon-knobs'; +import DropdownInputPair from '../dropdown-input-pair'; +import DropdownSearchList from '../dropdown-search-list'; const tokens = [ { @@ -113,7 +113,7 @@ const tokens = [ decimals: 8, address: '0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599', }, -] +]; const tokensToSearch = tokens.map((token) => ({ ...token, @@ -123,18 +123,18 @@ const tokensToSearch = tokens.map((token) => ({ Math.floor(Math.random() * 6), )} ${token.symbol}`, rightSecondaryLabel: `$${(Math.random() * 1000).toFixed(2)}`, -})) +})); export default { title: 'BuildQuote', -} +}; export const Default = () => { - const [inputValue, onInputChange] = useState(null) - const [selectedFromToken, setSelectedFromToken] = useState(null) - const formattedSwapFromFiatValue = `$${(Number(inputValue) * 4).toFixed(2)}` - const loading = boolean('loading', false) - const selectedFromTokenIsNull = boolean('selectedFromTokenIsNull', false) + const [inputValue, onInputChange] = useState(null); + const [selectedFromToken, setSelectedFromToken] = useState(null); + const formattedSwapFromFiatValue = `$${(Number(inputValue) * 4).toFixed(2)}`; + const loading = boolean('loading', false); + const selectedFromTokenIsNull = boolean('selectedFromTokenIsNull', false); return (
    { />
    - ) -} + ); +}; diff --git a/ui/app/pages/swaps/build-quote/index.js b/ui/app/pages/swaps/build-quote/index.js index e8af5e4e8..772229f2a 100644 --- a/ui/app/pages/swaps/build-quote/index.js +++ b/ui/app/pages/swaps/build-quote/index.js @@ -1 +1 @@ -export { default } from './build-quote' +export { default } from './build-quote'; diff --git a/ui/app/pages/swaps/countdown-timer/countdown-timer.js b/ui/app/pages/swaps/countdown-timer/countdown-timer.js index 393a51849..879eeff82 100644 --- a/ui/app/pages/swaps/countdown-timer/countdown-timer.js +++ b/ui/app/pages/swaps/countdown-timer/countdown-timer.js @@ -1,31 +1,31 @@ -import React, { useState, useEffect, useContext, useRef } from 'react' -import { useSelector } from 'react-redux' -import PropTypes from 'prop-types' -import classnames from 'classnames' -import { Duration } from 'luxon' -import { I18nContext } from '../../../contexts/i18n' -import InfoTooltip from '../../../components/ui/info-tooltip' -import { getSwapsQuoteRefreshTime } from '../../../ducks/swaps/swaps' +import React, { useState, useEffect, useContext, useRef } from 'react'; +import { useSelector } from 'react-redux'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; +import { Duration } from 'luxon'; +import { I18nContext } from '../../../contexts/i18n'; +import InfoTooltip from '../../../components/ui/info-tooltip'; +import { getSwapsQuoteRefreshTime } from '../../../ducks/swaps/swaps'; // Return the mm:ss start time of the countdown timer. // If time has elapsed between `timeStarted` the time current time, // then that elapsed time will be subtracted from the timer before // rendering function getNewTimer(currentTime, timeStarted, timeBaseStart) { - const timeAlreadyElapsed = currentTime - timeStarted - return timeBaseStart - timeAlreadyElapsed + const timeAlreadyElapsed = currentTime - timeStarted; + return timeBaseStart - timeAlreadyElapsed; } function decreaseTimerByOne(timer) { - return Math.max(timer - 1000, 0) + return Math.max(timer - 1000, 0); } function timeBelowWarningTime(timer, warningTime) { - const [warningTimeMinutes, warningTimeSeconds] = warningTime.split(':') + const [warningTimeMinutes, warningTimeSeconds] = warningTime.split(':'); return ( timer <= (Number(warningTimeMinutes) * 60 + Number(warningTimeSeconds)) * 1000 - ) + ); } export default function CountdownTimer({ @@ -36,59 +36,59 @@ export default function CountdownTimer({ labelKey, infoTooltipLabelKey, }) { - const t = useContext(I18nContext) - const intervalRef = useRef() - const initialTimeStartedRef = useRef() + const t = useContext(I18nContext); + const intervalRef = useRef(); + const initialTimeStartedRef = useRef(); - const swapsQuoteRefreshTime = useSelector(getSwapsQuoteRefreshTime) - const timerStart = Number(timerBase) || swapsQuoteRefreshTime + const swapsQuoteRefreshTime = useSelector(getSwapsQuoteRefreshTime); + const timerStart = Number(timerBase) || swapsQuoteRefreshTime; - const [currentTime, setCurrentTime] = useState(() => Date.now()) + const [currentTime, setCurrentTime] = useState(() => Date.now()); const [timer, setTimer] = useState(() => getNewTimer(currentTime, timeStarted, timerStart), - ) + ); useEffect(() => { if (intervalRef.current === undefined) { intervalRef.current = setInterval(() => { - setTimer(decreaseTimerByOne) - }, 1000) + setTimer(decreaseTimerByOne); + }, 1000); } return function cleanup() { - clearInterval(intervalRef.current) - } - }, []) + clearInterval(intervalRef.current); + }; + }, []); // Reset the timer that timer has hit '0:00' and the timeStarted prop has changed useEffect(() => { if (!initialTimeStartedRef.current) { - initialTimeStartedRef.current = timeStarted || Date.now() + initialTimeStartedRef.current = timeStarted || Date.now(); } if (timer === 0 && timeStarted !== initialTimeStartedRef.current) { - initialTimeStartedRef.current = timeStarted - const newCurrentTime = Date.now() - setCurrentTime(newCurrentTime) - setTimer(getNewTimer(newCurrentTime, timeStarted, timerStart)) + initialTimeStartedRef.current = timeStarted; + const newCurrentTime = Date.now(); + setCurrentTime(newCurrentTime); + setTimer(getNewTimer(newCurrentTime, timeStarted, timerStart)); - clearInterval(intervalRef.current) + clearInterval(intervalRef.current); intervalRef.current = setInterval(() => { - setTimer(decreaseTimerByOne) - }, 1000) + setTimer(decreaseTimerByOne); + }, 1000); } - }, [timeStarted, timer, timerStart]) + }, [timeStarted, timer, timerStart]); - const formattedTimer = Duration.fromMillis(timer).toFormat('m:ss') - let time + const formattedTimer = Duration.fromMillis(timer).toFormat('m:ss'); + let time; if (timeOnly) { - time =
    {formattedTimer}
    + time =
    {formattedTimer}
    ; } else if (labelKey) { time = t(labelKey, [
    {formattedTimer}
    , - ]) + ]); } return ( @@ -105,7 +105,7 @@ export default function CountdownTimer({ ) : null} - ) + ); } CountdownTimer.propTypes = { @@ -115,4 +115,4 @@ CountdownTimer.propTypes = { warningTime: PropTypes.string, labelKey: PropTypes.string, infoTooltipLabelKey: PropTypes.string, -} +}; diff --git a/ui/app/pages/swaps/countdown-timer/countdown-timer.stories.js b/ui/app/pages/swaps/countdown-timer/countdown-timer.stories.js index 6970a045a..10d89ac7d 100644 --- a/ui/app/pages/swaps/countdown-timer/countdown-timer.stories.js +++ b/ui/app/pages/swaps/countdown-timer/countdown-timer.stories.js @@ -1,19 +1,19 @@ -import React from 'react' -import { number } from '@storybook/addon-knobs' -import CountdownTimer from './countdown-timer' +import React from 'react'; +import { number } from '@storybook/addon-knobs'; +import CountdownTimer from './countdown-timer'; export default { title: 'CountdownTimer', -} +}; const getTimeStartedFromDecrimentSeconds = (seconds) => - Date.now() - seconds * 1000 + Date.now() - seconds * 1000; export const Default = () => { const timeStartedSecondDecriment = number( 'Set timeStarted to curren time minus X seconds', 10, - ) + ); return ( { )} timeOnly /> - ) -} + ); +}; export const CustomTimerBase = () => { const timeStartedSecondDecriment = number( 'Set timeStarted to curren time minus X seconds', 10, - ) + ); return ( { timerBase={150000} timeOnly /> - ) -} + ); +}; // Label keys used in below stories are just for demonstration purposes export const WithLabelInfoTooltipAndWarning = () => { const timeStartedSecondDecriment = number( 'Set timeStarted to curren time minus X seconds', 0, - ) + ); return ( { infoTooltipLabelKey="disconnectAllAccountsConfirmationDescription" warningTime="0:15" /> - ) -} + ); +}; diff --git a/ui/app/pages/swaps/countdown-timer/index.js b/ui/app/pages/swaps/countdown-timer/index.js index 162b37c92..d45f24fff 100644 --- a/ui/app/pages/swaps/countdown-timer/index.js +++ b/ui/app/pages/swaps/countdown-timer/index.js @@ -1 +1 @@ -export { default } from './countdown-timer' +export { default } from './countdown-timer'; diff --git a/ui/app/pages/swaps/dropdown-input-pair/dropdown-input-pair.js b/ui/app/pages/swaps/dropdown-input-pair/dropdown-input-pair.js index 5299ba3ae..92aa5190b 100644 --- a/ui/app/pages/swaps/dropdown-input-pair/dropdown-input-pair.js +++ b/ui/app/pages/swaps/dropdown-input-pair/dropdown-input-pair.js @@ -1,8 +1,8 @@ -import React, { useState, useRef, useEffect } from 'react' -import PropTypes from 'prop-types' -import classnames from 'classnames' -import DropdownSearchList from '../dropdown-search-list' -import TextField from '../../../components/ui/text-field' +import React, { useState, useRef, useEffect } from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; +import DropdownSearchList from '../dropdown-search-list'; +import TextField from '../../../components/ui/text-field'; const characterWidthMap = { 1: 5.86, @@ -16,16 +16,16 @@ const characterWidthMap = { 9: 10.06, 0: 11.22, '.': 4.55, -} +}; const getInputWidth = (value) => { - const valueString = String(value) - const charArray = valueString.split('') + const valueString = String(value); + const charArray = valueString.split(''); return charArray.reduce( (inputWidth, _char) => inputWidth + characterWidthMap[_char], 12, - ) -} + ); +}; export default function DropdownInputPair({ itemsToSearch = [], onInputChange, @@ -41,34 +41,34 @@ export default function DropdownInputPair({ listContainerClassName, autoFocus, }) { - const [isOpen, setIsOpen] = useState(false) - const open = () => setIsOpen(true) - const close = () => setIsOpen(false) - const inputRef = useRef() + const [isOpen, setIsOpen] = useState(false); + const open = () => setIsOpen(true); + const close = () => setIsOpen(false); + const inputRef = useRef(); const onTextFieldChange = (event) => { - event.stopPropagation() + event.stopPropagation(); // Automatically prefix value with 0. if user begins typing . - const valueToUse = event.target.value === '.' ? '0.' : event.target.value + const valueToUse = event.target.value === '.' ? '0.' : event.target.value; // Regex that validates strings with only numbers, 'x.', '.x', and 'x.x' - const regexp = /^(\.\d+|\d+(\.\d+)?|\d+\.)$/u + const regexp = /^(\.\d+|\d+(\.\d+)?|\d+\.)$/u; // If the value is either empty or contains only numbers and '.' and only has one '.', update input to match if (valueToUse === '' || regexp.test(valueToUse)) { - onInputChange(valueToUse) + onInputChange(valueToUse); } else { // otherwise, use the previously set inputValue (effectively denying the user from inputting the last char) // or an empty string if we do not yet have an inputValue - onInputChange(inputValue || '') + onInputChange(inputValue || ''); } - } - const [applyTwoLineStyle, setApplyTwoLineStyle] = useState(null) + }; + const [applyTwoLineStyle, setApplyTwoLineStyle] = useState(null); useEffect(() => { setApplyTwoLineStyle( (inputRef?.current?.getBoundingClientRect()?.width || 0) + getInputWidth(inputValue || '') > 137, - ) - }, [inputValue, inputRef]) + ); + }, [inputValue, inputRef]); return (
    @@ -118,7 +118,7 @@ export default function DropdownInputPair({
    )} - ) + ); } DropdownInputPair.propTypes = { @@ -135,4 +135,4 @@ DropdownInputPair.propTypes = { hideItemIf: PropTypes.func, listContainerClassName: PropTypes.string, autoFocus: PropTypes.bool, -} +}; diff --git a/ui/app/pages/swaps/dropdown-input-pair/dropdown-input-pair.stories.js b/ui/app/pages/swaps/dropdown-input-pair/dropdown-input-pair.stories.js index c3ea2575d..16b32c3ef 100644 --- a/ui/app/pages/swaps/dropdown-input-pair/dropdown-input-pair.stories.js +++ b/ui/app/pages/swaps/dropdown-input-pair/dropdown-input-pair.stories.js @@ -1,5 +1,5 @@ -import React, { useState } from 'react' -import DropdownInputPair from '.' +import React, { useState } from 'react'; +import DropdownInputPair from '.'; const tokens = [ { @@ -110,11 +110,11 @@ const tokens = [ decimals: 8, address: '0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599', }, -] +]; export default { title: 'DropdownInputPair', -} +}; const tokensToSearch = tokens.map((token) => ({ ...token, @@ -124,10 +124,10 @@ const tokensToSearch = tokens.map((token) => ({ Math.floor(Math.random() * 6), )} ${token.symbol}`, rightSecondaryLabel: `$${(Math.random() * 1000).toFixed(2)}`, -})) +})); export const Basic = () => { - const [inputValue, setInputValue] = useState() + const [inputValue, setInputValue] = useState(); return (
    { inputValue={inputValue} />
    - ) -} + ); +}; diff --git a/ui/app/pages/swaps/dropdown-input-pair/index.js b/ui/app/pages/swaps/dropdown-input-pair/index.js index 84a01f835..d89fc83b8 100644 --- a/ui/app/pages/swaps/dropdown-input-pair/index.js +++ b/ui/app/pages/swaps/dropdown-input-pair/index.js @@ -1 +1 @@ -export { default } from './dropdown-input-pair' +export { default } from './dropdown-input-pair'; diff --git a/ui/app/pages/swaps/dropdown-search-list/dropdown-search-list.js b/ui/app/pages/swaps/dropdown-search-list/dropdown-search-list.js index b6d85400d..5577d3517 100644 --- a/ui/app/pages/swaps/dropdown-search-list/dropdown-search-list.js +++ b/ui/app/pages/swaps/dropdown-search-list/dropdown-search-list.js @@ -4,14 +4,14 @@ import React, { useEffect, useContext, useRef, -} from 'react' -import PropTypes from 'prop-types' -import classnames from 'classnames' -import { isEqual } from 'lodash' -import { I18nContext } from '../../../contexts/i18n' -import SearchableItemList from '../searchable-item-list' -import PulseLoader from '../../../components/ui/pulse-loader' -import UrlIcon from '../../../components/ui/url-icon' +} from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; +import { isEqual } from 'lodash'; +import { I18nContext } from '../../../contexts/i18n'; +import SearchableItemList from '../searchable-item-list'; +import PulseLoader from '../../../components/ui/pulse-loader'; +import UrlIcon from '../../../components/ui/url-icon'; export default function DropdownSearchList({ searchListClassName, @@ -32,54 +32,54 @@ export default function DropdownSearchList({ hideItemIf, listContainerClassName, }) { - const t = useContext(I18nContext) - const [isOpen, setIsOpen] = useState(false) - const [selectedItem, setSelectedItem] = useState(startingItem) + const t = useContext(I18nContext); + const [isOpen, setIsOpen] = useState(false); + const [selectedItem, setSelectedItem] = useState(startingItem); const close = useCallback(() => { - setIsOpen(false) - onClose?.() - }, [onClose]) + setIsOpen(false); + onClose?.(); + }, [onClose]); const onClickItem = useCallback( (item) => { - onSelect?.(item) - setSelectedItem(item) - close() + onSelect?.(item); + setSelectedItem(item); + close(); }, [onSelect, close], - ) + ); const onClickSelector = useCallback(() => { if (!isOpen) { - setIsOpen(true) - onOpen?.() + setIsOpen(true); + onOpen?.(); } - }, [isOpen, onOpen]) + }, [isOpen, onOpen]); - const prevExternallySelectedItemRef = useRef() + const prevExternallySelectedItemRef = useRef(); useEffect(() => { - prevExternallySelectedItemRef.current = externallySelectedItem - }) - const prevExternallySelectedItem = prevExternallySelectedItemRef.current + prevExternallySelectedItemRef.current = externallySelectedItem; + }); + const prevExternallySelectedItem = prevExternallySelectedItemRef.current; useEffect(() => { if ( externallySelectedItem && !isEqual(externallySelectedItem, selectedItem) ) { - setSelectedItem(externallySelectedItem) + setSelectedItem(externallySelectedItem); } else if (prevExternallySelectedItem && !externallySelectedItem) { - setSelectedItem(null) + setSelectedItem(null); } - }, [externallySelectedItem, selectedItem, prevExternallySelectedItem]) + }, [externallySelectedItem, selectedItem, prevExternallySelectedItem]); const onKeyUp = (e) => { if (e.key === 'Escape') { - close() + close(); } else if (e.key === 'Enter') { - onClickSelector(e) + onClickSelector(e); } - } + }; return (
    { - event.stopPropagation() - setIsOpen(false) - onClose?.() + event.stopPropagation(); + setIsOpen(false); + onClose?.(); }} /> )}
    - ) + ); } DropdownSearchList.propTypes = { @@ -197,4 +197,4 @@ DropdownSearchList.propTypes = { hideRightLabels: PropTypes.bool, hideItemIf: PropTypes.func, listContainerClassName: PropTypes.string, -} +}; diff --git a/ui/app/pages/swaps/dropdown-search-list/dropdown-search-list.stories.js b/ui/app/pages/swaps/dropdown-search-list/dropdown-search-list.stories.js index d88977753..dacbc21a6 100644 --- a/ui/app/pages/swaps/dropdown-search-list/dropdown-search-list.stories.js +++ b/ui/app/pages/swaps/dropdown-search-list/dropdown-search-list.stories.js @@ -1,5 +1,5 @@ -import React from 'react' -import DropdownSearchList from '.' +import React from 'react'; +import DropdownSearchList from '.'; const tokens = [ { @@ -110,11 +110,11 @@ const tokens = [ decimals: 8, address: '0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599', }, -] +]; export default { title: 'DropdownSearchList', -} +}; const tokensToSearch = tokens.map((token) => ({ ...token, @@ -124,7 +124,7 @@ const tokensToSearch = tokens.map((token) => ({ Math.floor(Math.random() * 6), )} ${token.symbol}`, rightSecondaryLabel: `$${(Math.random() * 1000).toFixed(2)}`, -})) +})); export const TokenSearchDropdown = () => { return ( @@ -141,5 +141,5 @@ export const TokenSearchDropdown = () => { defaultToAll /> - ) -} + ); +}; diff --git a/ui/app/pages/swaps/dropdown-search-list/index.js b/ui/app/pages/swaps/dropdown-search-list/index.js index e507fe144..3dd2e4ecf 100644 --- a/ui/app/pages/swaps/dropdown-search-list/index.js +++ b/ui/app/pages/swaps/dropdown-search-list/index.js @@ -1 +1 @@ -export { default } from './dropdown-search-list' +export { default } from './dropdown-search-list'; diff --git a/ui/app/pages/swaps/exchange-rate-display/exchange-rate-display.js b/ui/app/pages/swaps/exchange-rate-display/exchange-rate-display.js index e70ffd8e7..495990215 100644 --- a/ui/app/pages/swaps/exchange-rate-display/exchange-rate-display.js +++ b/ui/app/pages/swaps/exchange-rate-display/exchange-rate-display.js @@ -1,9 +1,9 @@ -import React, { useState } from 'react' -import PropTypes from 'prop-types' -import BigNumber from 'bignumber.js' -import classnames from 'classnames' -import { calcTokenAmount } from '../../../helpers/utils/token-util' -import { formatSwapsValueForDisplay } from '../swaps.util' +import React, { useState } from 'react'; +import PropTypes from 'prop-types'; +import BigNumber from 'bignumber.js'; +import classnames from 'classnames'; +import { calcTokenAmount } from '../../../helpers/utils/token-util'; +import { formatSwapsValueForDisplay } from '../swaps.util'; export default function ExchangeRateDisplay({ primaryTokenValue, @@ -16,49 +16,49 @@ export default function ExchangeRateDisplay({ boldSymbols = true, className, }) { - const [showPrimaryToSecondary, setShowPrimaryToSecondary] = useState(true) - const [rotating, setRotating] = useState(false) + const [showPrimaryToSecondary, setShowPrimaryToSecondary] = useState(true); + const [rotating, setRotating] = useState(false); const primaryTokenAmount = calcTokenAmount( primaryTokenValue, primaryTokenDecimals, - ) + ); const secondaryTokenAmount = calcTokenAmount( secondaryTokenValue, secondaryTokenDecimals, - ) + ); const conversionRateFromPrimaryToSecondary = new BigNumber( secondaryTokenAmount, ) .div(primaryTokenAmount) .round(9) - .toString(10) + .toString(10); const conversionRateFromSecondaryToPrimary = new BigNumber(primaryTokenAmount) .div(secondaryTokenAmount) .round(9) - .toString(10) + .toString(10); const baseSymbol = showPrimaryToSecondary ? primaryTokenSymbol - : secondaryTokenSymbol + : secondaryTokenSymbol; const ratiodSymbol = showPrimaryToSecondary ? secondaryTokenSymbol - : primaryTokenSymbol + : primaryTokenSymbol; const rate = showPrimaryToSecondary ? conversionRateFromPrimaryToSecondary - : conversionRateFromSecondaryToPrimary - let rateToDisplay - let comparisonSymbol = '=' + : conversionRateFromSecondaryToPrimary; + let rateToDisplay; + let comparisonSymbol = '='; if (new BigNumber(rate, 10).lt('0.00000001', 10)) { - rateToDisplay = '0.000000001' - comparisonSymbol = '<' + rateToDisplay = '0.000000001'; + comparisonSymbol = '<'; } else if (new BigNumber(rate, 10).lt('0.000001', 10)) { - rateToDisplay = rate + rateToDisplay = rate; } else { - rateToDisplay = formatSwapsValueForDisplay(rate) + rateToDisplay = formatSwapsValueForDisplay(rate); } return ( @@ -81,8 +81,8 @@ export default function ExchangeRateDisplay({ 'exchange-rate-display__switch-arrows-rotate': rotating, })} onClick={() => { - setShowPrimaryToSecondary(!showPrimaryToSecondary) - setRotating(true) + setShowPrimaryToSecondary(!showPrimaryToSecondary); + setRotating(true); }} onAnimationEnd={() => setRotating(false)} > @@ -100,7 +100,7 @@ export default function ExchangeRateDisplay({ - ) + ); } ExchangeRateDisplay.propTypes = { @@ -125,4 +125,4 @@ ExchangeRateDisplay.propTypes = { className: PropTypes.string, arrowColor: PropTypes.string, boldSymbols: PropTypes.bool, -} +}; diff --git a/ui/app/pages/swaps/exchange-rate-display/exchange-rate-display.stories.js b/ui/app/pages/swaps/exchange-rate-display/exchange-rate-display.stories.js index b28fa3772..d3193d6b5 100644 --- a/ui/app/pages/swaps/exchange-rate-display/exchange-rate-display.stories.js +++ b/ui/app/pages/swaps/exchange-rate-display/exchange-rate-display.stories.js @@ -1,10 +1,10 @@ -import React from 'react' -import { text, number } from '@storybook/addon-knobs' -import ExchangeRateDisplay from './exchange-rate-display' +import React from 'react'; +import { text, number } from '@storybook/addon-knobs'; +import ExchangeRateDisplay from './exchange-rate-display'; export default { title: 'ExchangeRateDisplay', -} +}; export const Default = () => { return ( @@ -16,8 +16,8 @@ export const Default = () => { secondaryTokenDecimals={number('secondaryTokenDecimals', 18)} secondaryTokenSymbol={text('secondaryTokenSymbol', 'ABC')} /> - ) -} + ); +}; export const WhiteOnBlue = () => { return ( @@ -43,5 +43,5 @@ export const WhiteOnBlue = () => { arrowColor="white" /> - ) -} + ); +}; diff --git a/ui/app/pages/swaps/exchange-rate-display/index.js b/ui/app/pages/swaps/exchange-rate-display/index.js index e572fe698..aeef508f8 100644 --- a/ui/app/pages/swaps/exchange-rate-display/index.js +++ b/ui/app/pages/swaps/exchange-rate-display/index.js @@ -1 +1 @@ -export { default } from './exchange-rate-display' +export { default } from './exchange-rate-display'; diff --git a/ui/app/pages/swaps/fee-card/fee-card.js b/ui/app/pages/swaps/fee-card/fee-card.js index af48ff7bb..cafbd97a3 100644 --- a/ui/app/pages/swaps/fee-card/fee-card.js +++ b/ui/app/pages/swaps/fee-card/fee-card.js @@ -1,7 +1,7 @@ -import React, { useContext } from 'react' -import PropTypes from 'prop-types' -import { I18nContext } from '../../../contexts/i18n' -import InfoTooltip from '../../../components/ui/info-tooltip' +import React, { useContext } from 'react'; +import PropTypes from 'prop-types'; +import { I18nContext } from '../../../contexts/i18n'; +import InfoTooltip from '../../../components/ui/info-tooltip'; export default function FeeCard({ primaryFee, @@ -17,13 +17,13 @@ export default function FeeCard({ onQuotesClick, tokenConversionRate, }) { - const t = useContext(I18nContext) + const t = useContext(I18nContext); - let bestQuoteText = '' + let bestQuoteText = ''; if (isBestQuote && tokenConversionRate) { - bestQuoteText = t('swapUsingBestQuote') + bestQuoteText = t('swapUsingBestQuote'); } else if (tokenConversionRate) { - bestQuoteText = t('swapBetterQuoteAvailable') + bestQuoteText = t('swapBetterQuoteAvailable'); } return ( @@ -148,7 +148,7 @@ export default function FeeCard({ - ) + ); } FeeCard.propTypes = { @@ -170,4 +170,4 @@ FeeCard.propTypes = { onQuotesClick: PropTypes.func.isRequired, numberOfQuotes: PropTypes.number.isRequired, tokenConversionRate: PropTypes.number, -} +}; diff --git a/ui/app/pages/swaps/fee-card/fee-card.stories.js b/ui/app/pages/swaps/fee-card/fee-card.stories.js index aaaf43d0f..32ea9caea 100644 --- a/ui/app/pages/swaps/fee-card/fee-card.stories.js +++ b/ui/app/pages/swaps/fee-card/fee-card.stories.js @@ -1,21 +1,21 @@ -import React from 'react' -import { action } from '@storybook/addon-actions' -import { text, boolean, number, object } from '@storybook/addon-knobs' -import FeeCard from './fee-card' +import React from 'react'; +import { action } from '@storybook/addon-actions'; +import { text, boolean, number, object } from '@storybook/addon-knobs'; +import FeeCard from './fee-card'; const tokenApprovalTextComponent = ( ABC -) +); const containerStyle = { width: '300px', -} +}; export default { title: 'FeeCard', -} +}; export const WithAllProps = () => { return ( @@ -44,8 +44,8 @@ export const WithAllProps = () => { currentCurrency="usd" /> - ) -} + ); +}; export const WithoutThirdRow = () => { return ( @@ -69,8 +69,8 @@ export const WithoutThirdRow = () => { metaMaskFee="0.875" /> - ) -} + ); +}; export const WithOnlyRequiredProps = () => { return ( @@ -87,5 +87,5 @@ export const WithOnlyRequiredProps = () => { numberOfQuotes={2} /> - ) -} + ); +}; diff --git a/ui/app/pages/swaps/fee-card/index.js b/ui/app/pages/swaps/fee-card/index.js index 84bc1acbb..4cac493bf 100644 --- a/ui/app/pages/swaps/fee-card/index.js +++ b/ui/app/pages/swaps/fee-card/index.js @@ -1 +1 @@ -export { default } from './fee-card' +export { default } from './fee-card'; diff --git a/ui/app/pages/swaps/fee-card/pig-icon.js b/ui/app/pages/swaps/fee-card/pig-icon.js index ef7677ae4..fe6a4278f 100644 --- a/ui/app/pages/swaps/fee-card/pig-icon.js +++ b/ui/app/pages/swaps/fee-card/pig-icon.js @@ -1,4 +1,4 @@ -import React from 'react' +import React from 'react'; export default function PigIcon() { return ( @@ -50,5 +50,5 @@ export default function PigIcon() { stroke="#037DD6" /> - ) + ); } diff --git a/ui/app/pages/swaps/index.js b/ui/app/pages/swaps/index.js index ca720910d..517e2b0a3 100644 --- a/ui/app/pages/swaps/index.js +++ b/ui/app/pages/swaps/index.js @@ -1,19 +1,19 @@ -import React, { useState, useEffect, useRef, useContext } from 'react' -import { useDispatch, useSelector } from 'react-redux' +import React, { useState, useEffect, useRef, useContext } from 'react'; +import { useDispatch, useSelector } from 'react-redux'; import { Switch, Route, useLocation, useHistory, Redirect, -} from 'react-router-dom' -import BigNumber from 'bignumber.js' -import { I18nContext } from '../../contexts/i18n' +} from 'react-router-dom'; +import BigNumber from 'bignumber.js'; +import { I18nContext } from '../../contexts/i18n'; import { getSelectedAccount, getCurrentNetworkId, getCurrentChainId, -} from '../../selectors/selectors' +} from '../../selectors/selectors'; import { getFromToken, getQuotes, @@ -31,7 +31,7 @@ import { getSwapsFeatureLiveness, prepareToLeaveSwaps, fetchAndSetSwapsGasPriceInfo, -} from '../../ducks/swaps/swaps' +} from '../../ducks/swaps/swaps'; import { AWAITING_SWAP_ROUTE, BUILD_QUOTE_ROUTE, @@ -40,15 +40,15 @@ import { SWAPS_ERROR_ROUTE, DEFAULT_ROUTE, SWAPS_MAINTENANCE_ROUTE, -} from '../../helpers/constants/routes' +} from '../../helpers/constants/routes'; import { ERROR_FETCHING_QUOTES, QUOTES_NOT_AVAILABLE_ERROR, ETH_SWAPS_TOKEN_OBJECT, SWAP_FAILED_ERROR, OFFLINE_FOR_MAINTENANCE, -} from '../../helpers/constants/swaps' -import { MAINNET_CHAIN_ID } from '../../../../shared/constants/network' +} from '../../helpers/constants/swaps'; +import { MAINNET_CHAIN_ID } from '../../../../shared/constants/network'; import { resetBackgroundSwapsState, @@ -56,61 +56,61 @@ import { removeToken, setBackgroundSwapRouteState, setSwapsErrorKey, -} from '../../store/actions' +} from '../../store/actions'; import { currentNetworkTxListSelector, getRpcPrefsForCurrentProvider, -} from '../../selectors' -import { useNewMetricEvent } from '../../hooks/useMetricEvent' -import { getValueFromWeiHex } from '../../helpers/utils/conversions.util' +} from '../../selectors'; +import { useNewMetricEvent } from '../../hooks/useMetricEvent'; +import { getValueFromWeiHex } from '../../helpers/utils/conversions.util'; -import FeatureToggledRoute from '../../helpers/higher-order-components/feature-toggled-route' -import { TRANSACTION_STATUSES } from '../../../../shared/constants/transaction' +import FeatureToggledRoute from '../../helpers/higher-order-components/feature-toggled-route'; +import { TRANSACTION_STATUSES } from '../../../../shared/constants/transaction'; import { fetchTokens, fetchTopAssets, getSwapsTokensReceivedFromTxMeta, fetchAggregatorMetadata, -} from './swaps.util' -import AwaitingSwap from './awaiting-swap' -import LoadingQuote from './loading-swaps-quotes' -import BuildQuote from './build-quote' -import ViewQuote from './view-quote' +} from './swaps.util'; +import AwaitingSwap from './awaiting-swap'; +import LoadingQuote from './loading-swaps-quotes'; +import BuildQuote from './build-quote'; +import ViewQuote from './view-quote'; export default function Swap() { - const t = useContext(I18nContext) - const history = useHistory() - const dispatch = useDispatch() + const t = useContext(I18nContext); + const history = useHistory(); + const dispatch = useDispatch(); - const { pathname } = useLocation() - const isAwaitingSwapRoute = pathname === AWAITING_SWAP_ROUTE - const isSwapsErrorRoute = pathname === SWAPS_ERROR_ROUTE - const isLoadingQuotesRoute = pathname === LOADING_QUOTES_ROUTE + const { pathname } = useLocation(); + const isAwaitingSwapRoute = pathname === AWAITING_SWAP_ROUTE; + const isSwapsErrorRoute = pathname === SWAPS_ERROR_ROUTE; + const isLoadingQuotesRoute = pathname === LOADING_QUOTES_ROUTE; - const fetchParams = useSelector(getFetchParams) + const fetchParams = useSelector(getFetchParams); const { sourceTokenInfo = {}, destinationTokenInfo = {} } = - fetchParams?.metaData || {} + fetchParams?.metaData || {}; - const [inputValue, setInputValue] = useState(fetchParams?.value || '') - const [maxSlippage, setMaxSlippage] = useState(fetchParams?.slippage || 2) + const [inputValue, setInputValue] = useState(fetchParams?.value || ''); + const [maxSlippage, setMaxSlippage] = useState(fetchParams?.slippage || 2); - const routeState = useSelector(getBackgroundSwapRouteState) - const selectedAccount = useSelector(getSelectedAccount) - const quotes = useSelector(getQuotes) - const txList = useSelector(currentNetworkTxListSelector) - const tradeTxId = useSelector(getTradeTxId) - const approveTxId = useSelector(getApproveTxId) - const aggregatorMetadata = useSelector(getAggregatorMetadata) - const networkId = useSelector(getCurrentNetworkId) - const rpcPrefs = useSelector(getRpcPrefsForCurrentProvider) - const fetchingQuotes = useSelector(getFetchingQuotes) - let swapsErrorKey = useSelector(getSwapsErrorKey) - const swapsEnabled = useSelector(getSwapsFeatureLiveness) + const routeState = useSelector(getBackgroundSwapRouteState); + const selectedAccount = useSelector(getSelectedAccount); + const quotes = useSelector(getQuotes); + const txList = useSelector(currentNetworkTxListSelector); + const tradeTxId = useSelector(getTradeTxId); + const approveTxId = useSelector(getApproveTxId); + const aggregatorMetadata = useSelector(getAggregatorMetadata); + const networkId = useSelector(getCurrentNetworkId); + const rpcPrefs = useSelector(getRpcPrefsForCurrentProvider); + const fetchingQuotes = useSelector(getFetchingQuotes); + let swapsErrorKey = useSelector(getSwapsErrorKey); + const swapsEnabled = useSelector(getSwapsFeatureLiveness); const { balance: ethBalance, address: selectedAccountAddress, - } = selectedAccount + } = selectedAccount; const fetchParamsFromToken = sourceTokenInfo?.symbol === 'ETH' ? { @@ -122,14 +122,14 @@ export default function Swap() { }), balance: ethBalance, } - : sourceTokenInfo + : sourceTokenInfo; const selectedFromToken = - useSelector(getFromToken) || fetchParamsFromToken || {} - const { destinationTokenAddedForSwap } = fetchParams || {} + useSelector(getFromToken) || fetchParamsFromToken || {}; + const { destinationTokenAddedForSwap } = fetchParams || {}; const approveTxData = - approveTxId && txList.find(({ id }) => approveTxId === id) - const tradeTxData = tradeTxId && txList.find(({ id }) => tradeTxId === id) + approveTxId && txList.find(({ id }) => approveTxId === id); + const tradeTxData = tradeTxId && txList.find(({ id }) => tradeTxId === id); const tokensReceived = tradeTxData?.txReceipt && getSwapsTokensReceivedFromTxMeta( @@ -139,30 +139,30 @@ export default function Swap() { selectedAccountAddress, destinationTokenInfo?.decimals, approveTxData, - ) - const tradeConfirmed = tradeTxData?.status === TRANSACTION_STATUSES.CONFIRMED + ); + const tradeConfirmed = tradeTxData?.status === TRANSACTION_STATUSES.CONFIRMED; const approveError = approveTxData?.status === TRANSACTION_STATUSES.FAILED || - approveTxData?.txReceipt?.status === '0x0' + approveTxData?.txReceipt?.status === '0x0'; const tradeError = tradeTxData?.status === TRANSACTION_STATUSES.FAILED || - tradeTxData?.txReceipt?.status === '0x0' - const conversionError = approveError || tradeError + tradeTxData?.txReceipt?.status === '0x0'; + const conversionError = approveError || tradeError; if (conversionError) { - swapsErrorKey = SWAP_FAILED_ERROR + swapsErrorKey = SWAP_FAILED_ERROR; } - const clearTemporaryTokenRef = useRef() + const clearTemporaryTokenRef = useRef(); useEffect(() => { clearTemporaryTokenRef.current = () => { if ( destinationTokenAddedForSwap && (!isAwaitingSwapRoute || conversionError) ) { - dispatch(removeToken(destinationTokenInfo?.address)) + dispatch(removeToken(destinationTokenInfo?.address)); } - } + }; }, [ conversionError, dispatch, @@ -170,34 +170,34 @@ export default function Swap() { destinationTokenInfo, fetchParams, isAwaitingSwapRoute, - ]) + ]); useEffect(() => { return () => { - clearTemporaryTokenRef.current() - } - }, []) + clearTemporaryTokenRef.current(); + }; + }, []); useEffect(() => { fetchTokens() .then((tokens) => { - dispatch(setSwapsTokens(tokens)) + dispatch(setSwapsTokens(tokens)); }) - .catch((error) => console.error(error)) + .catch((error) => console.error(error)); fetchTopAssets().then((topAssets) => { - dispatch(setTopAssets(topAssets)) - }) + dispatch(setTopAssets(topAssets)); + }); fetchAggregatorMetadata().then((newAggregatorMetadata) => { - dispatch(setAggregatorMetadata(newAggregatorMetadata)) - }) + dispatch(setAggregatorMetadata(newAggregatorMetadata)); + }); - dispatch(fetchAndSetSwapsGasPriceInfo()) + dispatch(fetchAndSetSwapsGasPriceInfo()); return () => { - dispatch(prepareToLeaveSwaps()) - } - }, [dispatch]) + dispatch(prepareToLeaveSwaps()); + }; + }, [dispatch]); const exitedSwapsEvent = useNewMetricEvent({ event: 'Exited Swaps', @@ -211,45 +211,45 @@ export default function Swap() { custom_slippage: fetchParams?.slippage !== 2, current_screen: pathname.match(/\/swaps\/(.+)/u)[1], }, - }) - const exitEventRef = useRef() + }); + const exitEventRef = useRef(); useEffect(() => { exitEventRef.current = () => { - exitedSwapsEvent() - } - }) + exitedSwapsEvent(); + }; + }); useEffect(() => { return () => { - exitEventRef.current() - } - }, []) + exitEventRef.current(); + }; + }, []); useEffect(() => { if (swapsErrorKey && !isSwapsErrorRoute) { - history.push(SWAPS_ERROR_ROUTE) + history.push(SWAPS_ERROR_ROUTE); } - }, [history, swapsErrorKey, isSwapsErrorRoute]) + }, [history, swapsErrorKey, isSwapsErrorRoute]); - const beforeUnloadEventAddedRef = useRef() + const beforeUnloadEventAddedRef = useRef(); useEffect(() => { const fn = () => { - clearTemporaryTokenRef.current() + clearTemporaryTokenRef.current(); if (isLoadingQuotesRoute) { - dispatch(prepareToLeaveSwaps()) + dispatch(prepareToLeaveSwaps()); } - return null - } + return null; + }; if (isLoadingQuotesRoute && !beforeUnloadEventAddedRef.current) { - beforeUnloadEventAddedRef.current = true - window.addEventListener('beforeunload', fn) + beforeUnloadEventAddedRef.current = true; + window.addEventListener('beforeunload', fn); } - return () => window.removeEventListener('beforeunload', fn) - }, [dispatch, isLoadingQuotesRoute]) + return () => window.removeEventListener('beforeunload', fn); + }, [dispatch, isLoadingQuotesRoute]); - const chainId = useSelector(getCurrentChainId) + const chainId = useSelector(getCurrentChainId); if (chainId !== MAINNET_CHAIN_ID) { - return + return ; } return ( @@ -261,10 +261,10 @@ export default function Swap() {
    { - clearTemporaryTokenRef.current() - dispatch(clearSwapsState()) - await dispatch(resetBackgroundSwapsState()) - history.push(DEFAULT_ROUTE) + clearTemporaryTokenRef.current(); + dispatch(clearSwapsState()); + await dispatch(resetBackgroundSwapsState()); + history.push(DEFAULT_ROUTE); }} > {t('cancel')} @@ -280,21 +280,21 @@ export default function Swap() { exact render={() => { if (tradeTxData && !conversionError) { - return + return ; } else if (tradeTxData) { - return + return ; } else if (routeState === 'loading' && aggregatorMetadata) { - return + return ; } const onInputChange = (newInputValue, balance) => { - setInputValue(newInputValue) + setInputValue(newInputValue); dispatch( setBalanceError( new BigNumber(newInputValue || 0).gt(balance || 0), ), - ) - } + ); + }; return ( - ) + ); }} /> - ) + ); } else if (fetchParams) { - return + return ; } - return + return ; }} /> - ) + ); } - return + return ; }} /> { - await dispatch(setBackgroundSwapRouteState('')) + await dispatch(setBackgroundSwapRouteState('')); if ( swapsErrorKey === ERROR_FETCHING_QUOTES || swapsErrorKey === QUOTES_NOT_AVAILABLE_ERROR ) { - dispatch(setSwapsErrorKey(QUOTES_NOT_AVAILABLE_ERROR)) - history.push(SWAPS_ERROR_ROUTE) + dispatch(setSwapsErrorKey(QUOTES_NOT_AVAILABLE_ERROR)); + history.push(SWAPS_ERROR_ROUTE); } else { - history.push(VIEW_QUOTE_ROUTE) + history.push(VIEW_QUOTE_ROUTE); } }} aggregatorMetadata={aggregatorMetadata} /> ) : ( - ) + ); }} /> ) : ( - ) + ); }} /> ) : ( - ) + ); }} />
    - ) + ); } diff --git a/ui/app/pages/swaps/intro-popup/index.js b/ui/app/pages/swaps/intro-popup/index.js index 66dc3b0a5..6460538b9 100644 --- a/ui/app/pages/swaps/intro-popup/index.js +++ b/ui/app/pages/swaps/intro-popup/index.js @@ -1 +1 @@ -export { default } from './intro-popup' +export { default } from './intro-popup'; diff --git a/ui/app/pages/swaps/intro-popup/intro-popup.js b/ui/app/pages/swaps/intro-popup/intro-popup.js index 5d525b7ee..30d934841 100644 --- a/ui/app/pages/swaps/intro-popup/intro-popup.js +++ b/ui/app/pages/swaps/intro-popup/intro-popup.js @@ -1,37 +1,37 @@ -import React, { useContext } from 'react' -import { useDispatch } from 'react-redux' -import { useHistory } from 'react-router-dom' -import PropTypes from 'prop-types' -import { setSwapsFromToken } from '../../../ducks/swaps/swaps' -import { I18nContext } from '../../../contexts/i18n' -import { BUILD_QUOTE_ROUTE } from '../../../helpers/constants/routes' -import { useNewMetricEvent } from '../../../hooks/useMetricEvent' -import { useSwapsEthToken } from '../../../hooks/useSwapsEthToken' -import Button from '../../../components/ui/button' -import Popover from '../../../components/ui/popover' +import React, { useContext } from 'react'; +import { useDispatch } from 'react-redux'; +import { useHistory } from 'react-router-dom'; +import PropTypes from 'prop-types'; +import { setSwapsFromToken } from '../../../ducks/swaps/swaps'; +import { I18nContext } from '../../../contexts/i18n'; +import { BUILD_QUOTE_ROUTE } from '../../../helpers/constants/routes'; +import { useNewMetricEvent } from '../../../hooks/useMetricEvent'; +import { useSwapsEthToken } from '../../../hooks/useSwapsEthToken'; +import Button from '../../../components/ui/button'; +import Popover from '../../../components/ui/popover'; export default function IntroPopup({ onClose }) { - const dispatch = useDispatch(useDispatch) - const history = useHistory() - const t = useContext(I18nContext) + const dispatch = useDispatch(useDispatch); + const history = useHistory(); + const t = useContext(I18nContext); const enteredSwapsEvent = useNewMetricEvent({ event: 'Swaps Opened', properties: { source: 'Intro popup', active_currency: 'ETH' }, category: 'swaps', - }) + }); const blogPostVisitedEvent = useNewMetricEvent({ event: 'Blog Post Visited ', category: 'swaps', - }) + }); const contractAuditVisitedEvent = useNewMetricEvent({ event: 'Contract Audit Visited', category: 'swaps', - }) + }); const productOverviewDismissedEvent = useNewMetricEvent({ event: 'Product Overview Dismissed', category: 'swaps', - }) - const swapsEthToken = useSwapsEthToken() + }); + const swapsEthToken = useSwapsEthToken(); return (
    @@ -40,8 +40,8 @@ export default function IntroPopup({ onClose }) { title={t('swapIntroPopupTitle')} subtitle={t('swapIntroPopupSubTitle')} onClose={() => { - productOverviewDismissedEvent() - onClose() + productOverviewDismissedEvent(); + onClose(); }} footerClassName="intro-popup__footer" footer={ @@ -49,10 +49,10 @@ export default function IntroPopup({ onClose }) { type="confirm" className="intro-popup__button" onClick={() => { - onClose() - enteredSwapsEvent() - dispatch(setSwapsFromToken(swapsEthToken)) - history.push(BUILD_QUOTE_ROUTE) + onClose(); + enteredSwapsEvent(); + dispatch(setSwapsFromToken(swapsEthToken)); + history.push(BUILD_QUOTE_ROUTE); }} > {t('swapStartSwapping')} @@ -75,8 +75,8 @@ export default function IntroPopup({ onClose }) { global.platform.openTab({ url: 'https://medium.com/metamask/introducing-metamask-swaps-84318c643785', - }) - blogPostVisitedEvent() + }); + blogPostVisitedEvent(); }} > {t('swapIntroLearnMoreLink')} @@ -87,8 +87,8 @@ export default function IntroPopup({ onClose }) { global.platform.openTab({ url: 'https://diligence.consensys.net/audits/private/lsjipyllnw2/', - }) - contractAuditVisitedEvent() + }); + contractAuditVisitedEvent(); }} > {t('swapLearnMoreContractsAuditReview')} @@ -96,9 +96,9 @@ export default function IntroPopup({ onClose }) {
    - ) + ); } IntroPopup.propTypes = { onClose: PropTypes.func.isRequired, -} +}; diff --git a/ui/app/pages/swaps/loading-swaps-quotes/aggregator-logo.js b/ui/app/pages/swaps/loading-swaps-quotes/aggregator-logo.js index 6b147c1c6..2d43d83a6 100644 --- a/ui/app/pages/swaps/loading-swaps-quotes/aggregator-logo.js +++ b/ui/app/pages/swaps/loading-swaps-quotes/aggregator-logo.js @@ -1,13 +1,13 @@ -import React from 'react' -import PropTypes from 'prop-types' +import React from 'react'; +import PropTypes from 'prop-types'; // Inspired by https://stackoverflow.com/a/28056903/4727685 function hexToRGB(hex, alpha) { - const r = parseInt(hex.slice(1, 3), 16) - const g = parseInt(hex.slice(3, 5), 16) - const b = parseInt(hex.slice(5, 7), 16) + const r = parseInt(hex.slice(1, 3), 16); + const g = parseInt(hex.slice(3, 5), 16); + const b = parseInt(hex.slice(5, 7), 16); - return `rgba(${r}, ${g}, ${b}, ${alpha})` + return `rgba(${r}, ${g}, ${b}, ${alpha})`; } export default function AggregatorLogo({ icon, color }) { @@ -22,10 +22,10 @@ export default function AggregatorLogo({ icon, color }) { - ) + ); } AggregatorLogo.propTypes = { icon: PropTypes.string.isRequired, color: PropTypes.string.isRequired, -} +}; diff --git a/ui/app/pages/swaps/loading-swaps-quotes/background-animation.js b/ui/app/pages/swaps/loading-swaps-quotes/background-animation.js index d435247a0..3820bffd0 100644 --- a/ui/app/pages/swaps/loading-swaps-quotes/background-animation.js +++ b/ui/app/pages/swaps/loading-swaps-quotes/background-animation.js @@ -1,4 +1,4 @@ -import React from 'react' +import React from 'react'; export default function BackgroundAnimation() { return ( @@ -203,5 +203,5 @@ export default function BackgroundAnimation() { - ) + ); } diff --git a/ui/app/pages/swaps/loading-swaps-quotes/index.js b/ui/app/pages/swaps/loading-swaps-quotes/index.js index 205fb024b..0a79f9e56 100644 --- a/ui/app/pages/swaps/loading-swaps-quotes/index.js +++ b/ui/app/pages/swaps/loading-swaps-quotes/index.js @@ -1 +1 @@ -export { default } from './loading-swaps-quotes' +export { default } from './loading-swaps-quotes'; diff --git a/ui/app/pages/swaps/loading-swaps-quotes/loading-swaps-quotes-stories-metadata.js b/ui/app/pages/swaps/loading-swaps-quotes/loading-swaps-quotes-stories-metadata.js index 7ffb38bf1..aae2acd8a 100644 --- a/ui/app/pages/swaps/loading-swaps-quotes/loading-swaps-quotes-stories-metadata.js +++ b/ui/app/pages/swaps/loading-swaps-quotes/loading-swaps-quotes-stories-metadata.js @@ -29,4 +29,4 @@ export const storiesMetadata = { icon: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAASkAAAB5CAYAAABlYNfBAAAACXBIWXMAACxLAAAsSwGlPZapAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAACQQSURBVHgB7Z0JfFTl1f/PnSwzk3VCAoFAYEjYDRAUSHCBoOBSFwK2wlurgNrW/pVCrcv/Uzdc2tpqy6J2UStY6/ZWIYhWrCgBPwIJCmGRLZAMS1hDMknInsx9z++ZucMkTCBAAmQ4Xz/jzNx7596ZkPnlnN9znvMQCYIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgnFc0ukSwZWTaaqpMM3WNUk2k23Uip+7Ss2rXZc0jQRAuWgJWpMJGZma6XOSs+TYr25w2aU60OXjWlJRkGpXYmb4/4qSXVm92kKaPtVjIWVlJ9iCdbI0aOevXZeWRIAgXDQEpUkqgNG0xufTpusk0dHBn26w3b0ijhKNOOtizC414/WN88DyOpmxR5hB7tDlUvW5feaVximxq1J+BwJEgCBeUgBQpS9rEwoevHGx/afWWhYlRYdM+HD+Suvzrv2R+YBKlffgVpZtM9KOYKErpEkMsUkRWM1WEWWhbaBB9sKWQPtu1j8pr64l0bXZN7qJnSBCEC0YQdXAs6Zn24B4DbA37tzs9zzNu7JM464pucSw2++3PpqdYrli0ioISOtO/GxvpwdXf0+2HnZSw9wgFb9tDpVsdtKGmjlZZQ6iWNfuyeBv1jI6gfWWVVF5XlxHcbcDKhgPbHca5g7sPXBCcyNs81xMEoX0xUQenZm2Wg1zabIiV2uCiDERIPRpdCBNt4w4cI72kgig2kq74+Bu13SA4JYmO/uR6umpoH5p2tJwmbi6g67Y4aFZkOC2aPI4So8JZxrWnvS9oJDtvy9B1bYP3eoIgtCsBke4hwuHUbAGMcBap2X/u13PqDVYLjdqxhzY6K5VIaZzS6dW13tfgudY9jly7ivyeM2hwEh3+QTpN/28OG+2lDp20PNL1jC+n3mR7ac1mWpa/P7smZ/FYEgShXQkYT8o8cmJpJ1uks7SswvF0eFjGtOIyur9HHP11UyGdLRAx8z030+clTpX+IUJLNwXRWlcjTfrgS7JY9RhndpakfYLQjnT4dM9AM+nz7r1tnM0WGZ6x5Wipip6mHS0jp0k7SUTKTRrNi7TSLV2iT3nO42ym1775KV23bgfdc7yWLv94NTUsy6UrE+PV/qpqbUzz15jTbp8pqaAgtB3BFCDU1NDcDTt2z/z7Ew/SI8/Op63HayjtYAl22YxjtoYE0XPRYUTDU2hbwT4ysVjRkbIWzxlRVUNL0gbQ1ys2UPoWd0RW1DmaDi5bqx4HkT7WMjxTnUDXaKhm0jKjzEEZFbWNvXnTLBIE4ZwJqBIEc1rm3P/+5bmZZRVVdN8jv6d3i8tpUH2j2geBun9wMj3xsym05Ks1NOvOCfSj+5+kvIOlpzxn0MgBdOQHo2jL0RIqr6mnKEsIoa4KNVWreYRw9b7D3voqRFjPjr2crvvnZ06NtCy1UXft4XA1LzSMsiU1FIQzJ6BECgb66GEpKx6/bzJx2sci9AS94jjkTKlrtI3uaqN33nqJFn+1mu6//UZatf57enTumzTiSCm9WFpJUbpO+4Pd2W+PBleT82qdIpWRrlnYfK+p9RjxoRQ8OpVM7FsZwJhHKtn/5Q9beovZbL4vrMnNeosEQWgVAZPugZq1WdmrdC37caKMnl270JiMdLp7Va5tBHtUaTdcQz3i42igvQe5WJB++8YHtPaff6K3P11BP3/1X/RecQWrDBHEbGZ5NU3ndBHCBSBKDSs3nnS9htztSsC0TlFKoIIS4mjZkCTqn9STFr3yO3XM9t176cCRo/Tlmm8pd/O2jAOHizMsaRNnYyRSlU90AAoLC5EyT9V5dJNvdk3TnHzvcLlcb/Xt2zebBKEd6fDFnM0J7jFw9t6DR2xdY21038QbqKyiko7FRNEj035IURFhNGpIf5r54us09orBNGbkEH4+gL4rLaOwLbsoyqXTR11jnZ3HX2l58dBh9dxIF32BMAWnJFNV+kBaWVdP2fuPUmeTiXZelUJPr91CkckpVGLuRAcrasgWHUVDkhPphqtHUOb4a8gSGkobdhbYXA2Ns4K7D6KGom0rfc+NaLBhv7t49GKABcrOYrSGRWkKPx3At658s/MtlcVq2syZM6Pnz5//OQlCOxFQIqXqpUibVXa8im4dk0afrMqlz1Z/R3/41b0qigJ19Q20ZtN2mnXXRPUYN1tUJH3w+SqV5u2+fKDlb0/OoOs58lqq6fTGviJKr2tQgqXSQQ6uzBw1uQ4UU8jhUup/5WDqftvV9FG4mZ5igXLFxNPga2+m0up62uespk0Hy2llwTFyVteRPS6SRl+eQj36DaLV6/Kovq4mw1eo1Kigri1uKNp+UXRm8AjUCnKLUkuMEqES2pOA8qSsaZMW33lzRmavbl1oeU4epXOUNG3CeIoKD2t+KAxs76jf9sJ99OxPf6PSu7QZd9P0zOvV9pCgIFqd9z39ds4C+v3mXapa/eedIlRqCO8JwgUQWWFeYFGQiSZ9sJxCeg+i6M7xZI2MVvchZov3wlfZO9G4Pp3ps+/30x//PJ/Kiw+jfmJazdqP3mKRms0i9fTFUn+1e/dujFDOacWhenl5eadhw4bJwEALFBUVUXV1dSZHpKkmk6kXb7JxJKp+B5E687Zsfriyd+/eDhKaEDAi5YlCCte+/Sea987H9PyMqad9TRiP0lXV1tGCrC9oa+FeSh88gG4fd1WTY6x8THnFcTUS+OqmfLqfBQl+FUQK9wYQKsvDU2g/R10QKp+OChQdF09JqSMoceAQ9TzGGkI/TetFC9bsovf+/ipVVpQ5rVa9d021toF329m2z6zLWbyEzoH8/PwM/hJk8i//UN/tHBltDAoKmtuaL8OuXbs28DlS6fTofN6H2J+aS8JJsAiRw+HozT+jgtMcWsrH3tOnT58sErwETDGnwdC+vWn8qGHe5/wlo9CQYFrLKd68d5ZQeWWVdx8EKNJq4chpPL3IKWFzgQLVLGJd4zrRS0/PoAXhFop0ueiL+Bjaz1FTDjooeIC5Xvfel5QYHU4LJo52z/vzUMbR0obln9Dyt16lqnKnSgVfz9lDY/olUOr4W9QcQ0Og1HsmvTedBTC4+fZ0QUHBChanFfzZZ3rMbu8N2/jLsoGPO62KG3/pWwH+2LX2WKFlYvhn/uaGDRvkZ+lDwIgURsr4D5Zz1fotdFlyL7UNAhVhMdNLCz+iP7z6okr7YiIjmryupKxciVVzgkwnfjSVNbXKS/qWDfAhLILVKf2onM89N9KdxhmlC42bC6j+81xK6RyjJij/7IoBNDkliW7s20Ptryovo9WL36H62holVOuLnNTD3pviuvfEbnuI2ex+39Q0+jkVHmGaCWFi8Snl22yI0WleZuPj5sJzIuFiwxYREdGa6PWSIaAiKY5Alny9/nvqk9hNPY8Ot9Lb/1lBBd9/TDmPB9Guwp0UGXbCHwoNDqKlq3LUcb6iBBCiR3m21ze4R/hs3ePJzFHabWNG0Ld9EqnvpOvdEVVoiDeqql+WyxHVcup+vJqeSb+M5t2YTjcl9/CeF0KFqAoUlFSRld9Dv7Rr1POuSf09R7nsdBqMqInFphCC0wphao6tsbHxdFXxre1SCnMum4Q2gf+42knwEmjpnmPjzkLlNcVGRZCJo51F/1lMtw7V6JF/N1Ifex+a//ZH6kCkgBgFXLpynTrOFnHCXMdzfOsqeRSvE6dtOBaMvvwyTgunU6+u8fTg5FtoaD+7EqcPw0K9URVo3FxIdYu/VingvrLjaFXc5E0eKthJxUV71GNEVHHde6loqv/IaygsEvMJNfupPiSLUypSNkRNdG5p1phT7eTzt3aU0SH1UkJ7EViRlGYa2qube/Lvd9t20WPzFtCwQYOJev6Cel32E6qtrqRrRw1X+yFkX2/YouqogJmFKNziTrdQ7BnFXhXunRVVFOMRsCfum6zubx0zkh6ccgtFR0QogTKPSqUdcTaVAhqE3DhSVaPPXJbTxEQ3OLR7Z5PnI27+IYVFRTcZCfSHpyxgMZ26LKBVnM5zgvDwtU7XmbSU/a9rSRDaiYASKRYV+62citU3NpK9e1caPqgfPXTP3TSCR+3GXT2S7v/xJOrRtbMSKNw27nSQ8/gJAUEqqHmEBqN+ECeca+/hYr/X69WtMx2yd6fXnpxBD3BktSDCJ5rK3UauomKad1O615Py5VDhCZFCrZZuckdrhi/VEpyiZVAbCFRrYaGCxzWdHzqa7+PtMOgvl2FzoT0JGJFCCQLrSyoM7kZP983MselubykiXN0gQPCYDF/qX5+uYCPc7j0H0rwwj4kOcXJ5fKng4GD6R9YXJ10T18LUGtRlzfARKUyR0VnrtoYG0aT3l6NB3kmvhTcFIFCOA8XelPJ08GeYQOcZHhJfmJSU1JsFaRhHVmNx48cxvP1aESihvQmcSKqRMuAZgVr+4m/YvosaXCcmCkN8MNIXFx2hhOr5Nz6gPQePqInGzooT0ZQl9ERZQUVVjXoNtg3u15tefm/pSZfFRGYQzfdDhw/2Guil3+6gAVv3qkiqJSqcpbR73xEljkb1e31tLZ0KFt0yugBA4FmQ8pAC4saPpXBTOC8EzARjzWSa8JOb3d18N+UXUomznGrq6tVziAxG8PBFgyD9/PmXacW3W+i++39BCxe8Sa9+8Ak97vGb4E3hOERgjSxySPtgqidymrho+TeEEgdEUP6Akb71q1xKq61XI37Xf55L6Q9PUS1c0NLFHxCm+NgoKmXfKi4mSpUnsBQ5WvqcqE7WtPNfg+spSFQeVlsKFM6bn5+fGhISMoZTWURrvTCJmZoOCDgxqdlTiFpYX1+/sl+/fu22PqLns9r54QS+JuYo2lAp7u/98Pasth40wL8vRm/5c6IYFxXqQz0/E2O/g5+r6/PT7EAftAiUHueq2nz74r+pFA6dDTZ/+CqVwLDmX7gdjn0c6UQosbnh/z1F9Sw+E6b8hIpcYZT76YdUfaSIDi1/23u+Yh6Rq2toUI8RdcWzeByvqaX9R47R3b95iXL/9We/7wPXXfPYi2pSss7//bCqjoJHD6UvB9tpetbXJx0/buoDlH+wjAYmJaiUr1+vrvTxy+ieoGfX5GT57Z/uMc5R+OnX9OZf3my+28O/yKcvuWefKTk5ucXC0V27dmV6zoMvqL35a/mWzV+gZ8405ePPQA0NDRn8Wpw7k85uhNJxttf3h48Io9h1Gp2Z71foeR9vneLcrak4N3Cc4fUxrQazCAJyNe6ASPd03TQTURRStx5sZqOxHVKoysoqJVBIySY/+gINmHg/Wa1Weu7J/68ECnRL6kdlbJ5vzD/RCz046MSPBdEU0kekfSgEvXbkUFq6Klf5VYiymqNaE0dZvWnfZ+u20f6yKr/vG+eOiQ5XURTEtKz4kNrOfzk2tvRZ8YXkX/pfNf38Or6sszw+0Vh+vpDaAE/0ABGx+9mNbdPwxcMUHGoFECcc6zHcMXF5Gp19CYXduD7qxegsgYAgamERMWrOZtOZD0xAgBbu3r37z9Q22OnMwB+uuXz9gp07dwZcIWiHFyl0PrB36zzrdR5hy997gL/wFfSjcVcrkXp32UrVNyqaTXMjnXvm4Qdo1d4K9RhTVHbkuCOcr7/7XgmP7ukh5UtFtXuOHnytSeOuolfeX6rOX1VT500pAdJMiFPsgCT6KMys+qhHson/2nfb/b53LdSq6rBKyirJYgml8qNH1PZG0lbQKYCRzV/y3r7ChL+iF8gn0jgFe+pUB3iEIMYQp7MoPD3l9SEs/AVddKbTSXwinLaoOQOzPJOyLxS9+d9ifWumPHUkOn4k5aIMjNAhHevbK4HGDh+ifKW9h44qY3wIG95LV+ZyqhdOsZ060X8claqAEgK1etE7VFXh9qERSRnC09hMqFSJAG8Lt5pVy5eCokPK27KwIDmPV6mKdDzHdTJ/PIGW/eU5uosjO0RUz9vC/dZJYdIxRvRKWaBw/gg+t1Hgqbv0Paf72IioLqAwNaGZX9N8nyEE69tYnJozMTo6elFrD/a8L4xWrqe2K+mAffIUXVgg2gsCKaIKiHSvmE3y8spqGpHSX00wBoigMNqHynDUQu05dJhCbHFKoACmphgCBTbnO9Q9UriGhpMb3UEEIWJo35KWMoDPd0Q9RvRVwgIVycY8yhFQkY708sVZ96h79Fb3hzXKvVJNiUfAIsIsdGz/Xjx01K/LyrNlZNo60KozLUYgBw4c0NgQRzpmp3aGhWcsRzKzW3GcIZxfUdtPjLZdBHMieRzJ9CYFCB1fpEyUjSZ22wr2UpwtSm1C2oVYCNXnEKvbxozkFO1T6sr+E0CKd6xob5PTGGUILs+oXnMQYYGQ4CDqztHUXo7SDO8Kx0Nson2m1qAk4Tf33kEtEZuYpMoPgJUjsuqyYo9oatkQJ3RFsFioQw/zQwzq6ursrTTx24pfnirt8whUTDsJlMLJ0AUGLXZYLM97TV17EAjLrGeTpj9z//Ov0Ls8uvbInDfVCN5eVQO1RXlRECikfpgjV7x/D+3IPXmkDfsBBMffED+2GxEWuinA5/IFxZ/lVTVNts2Ycitd00K5QgWFqTQPxERHUEHeOvVYJx7WdqFti+64kI3vYHKfKywGGMWz0/klJioqqkVfCO+JBWomtVNkxyKYd5E0/9P4vcykACAg6qRYqGbvHZmZ99i8BegiaUc7lT/+6l76ZGUOpd/9a6rTgunKSXeqKSd5ng4EvsBn2n+4WI3iAXhFtT6GuAH2w68azB4YaqWaj+6hpQtqssw+1eOvP/mgeg++BaOhETGkmX2irggrbeRUT0f9DWlz4Gzw43NqeteBwSIPb7GQqDqokJCQaE4Xh51JNMbHjva33Ujz+OHZjAZCeLI4jcqrr68v87wvnGsoXy/DuAQb121VBnDSz4EfZ5B7tLVVnMor7EgETDFnXW5WFqVmZnOKlLlxZ+Gc9Lseso0YPJCuvekWaohPVsdsWfVFEx/K4J3fP0p3P/6SEh34TC1R29Cgoqmrhw1SzyFKzYGR3sUW6Y3GMGXmtScepDse+4P3mMheA7yPYcYf3rVVvS/NJ/3gwC2bLi34O6VP8teV0iMu81qborVk0Hsiu6km0xklEOjR9WxLXUeNwk/MqeTHtuTk5LZYrmwOn+eh5hs5up3H7x9TkjBA0JpU1QYDvT0LX88HgdWqJU+lRw50Xrkr8waaM/sRirS7BQGjeQUb1530EnTjRCTVNS5GdeEMs4RidM3v6VFugLTPHByspszU+zHYsf94M/HCohBGCQSwdIr3Pu4aF037tm1Sj91tWhTKPKdLDI5C/H5mCH5wcHAeIgtqJf7Ma45GNE8BaatPgwnUp2qL7Jku5EBZSBu1T4ZYb/K3g6+Dn8OKM2ihg8/cizo4Adc+GAsZJLDo3DXhRvrGUeIdzUO5gT/uuP4aMnOKNiipp6ouR6pnVJu3BETIqJ0ywMif0eoFfaia11vd5ZmyE56QRMFWd3fQUB75qyk5rNoLp4weT/09ze900gOycvhcMJvNumcayFmBfw9O0/xVzrf4Er7ePRfpBOqVrT2QI7wY6uAElEi5l7SijOvSr1C9mSBSAJGKvzQPEdS4tFQK5RQPq8qgqtxfdNQcf6N/Lo8oRXr6UDWPpjDKCCISkr3bErvGYlkrNT2m1+Dh3sJS1rssEtqUAwcO4AtrP4OXLLwY58TZ7XZEUw66hAisSMqlTcPdXZk30vL8o97Nxpe/OePThymTG9FT74R45Q9VNBuhOxPgUSFdhFAhmjLAyCHm9Vli4lWqh+tgnh5qo7rY+1It6+KBHZuNEoSFHWVl445EXV0doqnW9o7XOc27VAcuLjoCqp8UO89TM8ddo6Ko9UXuyKmlKArcdPVwleJBqNDCBca5vygJZnrulh30xZr1p30fpWyco18VFncwRguNKCpx2FWUnNiF+vSMJyuL2XEWREfRUSWSXiHVTtsJsy3R6RIhNDRUO5Pe4U6ns9UpldC+BFIkNQ3/yxw3ukkUZZjS/hjs0/AOKRoiIURBKNiEIYrH+Y599Ni8N5WnceNVw1WJwalapaD2CeKE1jDAiKKw5t7AywYocTpaUkG79x1WxZxxMZHe0T2Joi4eZKHTi4eAKUFgw3wqDPM+fZNpUfYutQldBYqbVZYbwCiPjYpUjxE9IQLqFBnujn7qSJUR/PXfn9KCJcvpnRceo26xMUq8UGLgCyKx5tEXTHVzSISK0NB9AZi7D6BtBQe8BZwgPjaaQlx1FyqKEoQOQUBEUuFXZqpRm+tGXdEkijKquP0R6VmuCgKD/lHocIDniKjQmeDdz1bSvHeX0l+fmEHdO3dSkZE/vwoeVPPIyoimXvlgKW3Md5AteQjVm0KbCBR8KZQfoPpdRVG6/oxEUYJwMgEhUjwgl4H7MVeO8npRwDNh9yRQG4X5d8CY4Gv0Nsc9qs/hI/3yxxOoX88ElfZBzHwjJq8wsauzNHvNSdfYWriPz/G/FGwJp+jkIU32ofSgZ7dYlYru27YZRZx5NblZs0loN1zuf7tWp3CB2JepoxIQIqWRNiEyPIz2u6zebZij11LZAcRnUO+eKi3DnDtEQwaod8KCofCS0gb39y7aoGqogt3ZMQTKWLQBkVddfT3lbD7RMwpLud/xyO/UVJj4EeObXD/IpLF5Hk8N1ceNNM+ha/pEEtqVsLAwnf/dTtsCxwN6ZLV6+onQvgRIZ05KxRSYwpITfhEW4PQHBApCNX7UMCU8WEQUkRJAZ8+fPfcyPTJngYq2knp0bbKyMUYAcTz8KoARPIjVNcNSeORvg/e45197j6OxYyrNMwo3DRI5gtJcDSd6WWn6dEnz2p/y8nIy5sG1kl+eaRM9oX3o8MY5/CgOhmwR8T281eWgvLjpwgeIimbeOYHvB6iIaCiP7MHYRrTz+qJltHRljhIpdDjAcQ/ffbtXvHzBa+A3qd5SbKSjXQv6RuVs3qH2z39nCX20/BtVWd48zYNRjnYu6Kvu9aFyslRrFr2RJmg6baz5NiubhDYHRZAOhyOPhQopX2vEJyYyMvIrFqprZaTvwtLhRYr1ws4ZFFWaowjNU5DmuZcxd/tRzcUJ6duh4hJ6f1m2V5iM41586F6aOHYUJcTFeD0nlB74GuPwpTDCB7GCUKE8HKkhUjyI07x3lygfqlP/4U3eJwQKRjma7bmjPG0hwihL2sQV7GtlcMCWV52zeBgJ7QL+DXft2oVVXrKplZ0E+NhhUVFR6/Pz8+9pqfrcZwEHNScwUBdDuJB0eJHi3z077ht49AxdDjCJ2IiGJl3nnjwM7wji9E3eNjaz328iTE/9/Md05w8y3A3zdHQj1slZWa26HWDdPvwSopgzKMg98odpMxAnw6sCWJgBIM2DQMGHMoWc8LlieLTQEKgTdVv6NJ+1esSXOg+wz6Q3NDTMN5lMZ+I3oZf8ioKCguzGxsaVWFLM2IH2KYWFhZmeligQKh2LOrBQSSlJGxIIdVJ2/A/iBAGYnjle+U4QKkOc4Cu9/elX7De9QoOSEumJn/4P3T7+KnWMscaeUf+E54iSUHQJcTJxmIbSA2NVZLXIqNXs9aqM3uYYETQFh1C3UTc38aGslhD2sKxNBCos0kYsSlRdXgY/zamZ9LFt7EsFxFJlbQ26CLCIQGyyfXpAtQq0f2GxavIa18mzE9Bf/GmOvFYG+lp455OOH0np/BdMc1eWP/mz/1EThZHWoZGc0RsK6RgECnP1/vn8r1XNUwmLElqyIEJS3hKLTrDnvjmdIsNbvP5v/+FeCRkChQjKV6BQamBP6MwjeZWUOHAw9R95NYWYLap1MXwpwH/cp1etaTuB8qxpR4J/2JvSOT17yLMAQ3uByCqbhDYhcCrOGSVQmIcX5RYKRDlYnfjjle507Olf3KkWCEXahs6bCbHnNniDpdpfef8Tr0CFRnZqsr+xUff2MefkgOLCTKQdPcxRlWe5dk0JlHQ8OI8gUj527NgGp9OJpnJttU5ek0tQO/VOv1QJKJGCeW1MdUF0g17nRu9yTIPpl5igHmMicainxS+ExpgAjFE6LI+F9sMPTrlFddX0hzsye1l5W/CgOg8bc5JAAaMAFLVRCV060fEDu0+0L3aXHiykNsYziuXwk4qcEeHh4Zhk29q6onansrJSLS9ObUBsbCwizjkccUZzCnfWC4u2ACZt+xsNbMsRwktqtDEQRMphPFiQ9YUyzOExbdrp8AoUgGeE9fJSknsqjwkpXnMQeUF4cHuFIzAsiYWFFIZ4lsnae+hIkxFBwyRvXgvlC6a/oLq8cP0aNQXG40FNVAtItB/n/EvcFqLgM+xP50pbia+Bx5+ajdS4jYXKGRwc3CQ6RvS2f/9+Z21trYPOcQEInGv37t34921tKUWHp+MXc+onRGrhki9UNIWGcxAYX7B95h//7l1x2GgR3Pw4XyBGiLImP/aCumElGkOg0BuquUnuizt6iqEEm5nWLX3fWKHGwQI1rD0FylMugSb+2XQO4EtstVqzyeePwIV6Lz7ncrTFuQzwGfv06TObRSqJn7ZFu2a0/n3IXzfP+vp6dPpsi/7nEFX9TFoId3Q6vEgFhZz45XqCjXOAkTise9c8XUPB5fz3lpI1NMQ7Dw+rvrS07FRLoJK8eZmBL2i/MjC5O5Xv2U4r3/+HMsp5DHGexaoEykHtDMxhHm6/51y/0N27d0fzt2vpHISqrd6L77mobQRF4elRjl7mWM0YPZ7PyiPE5+PXX4te5/72ezpqzjuTPu0t0Zbn6ggExFC1eeTEUiy+8O4Lj6qizfiYKFUicD17Ul+v39LkWJQdrP7nn8hqMaspLig3wGKiD89ZoI6FsJUdr6SeXbuo9M53KSqkd7EpVzZZSMEXpHbdOXqqLD6oIifPAqQOj/+UTecZT6FhKtrm+i5vhFofpHJY3KA1y7R7RgyxGordt3EczsNfbicLR/bpznOq9+I5R15r+4m35blaOLfNs/pLKp9rKD43uVMrI70yPmuep+96dmtLDnxWl0n1fe/8b1HqWSor+wx/Dn7Pxdv2nMvP4WIiIETKMjJzIf9JnAqRGjVkIHXt5F515Y5HX/AWWvqCOip4VzDPUV6AHwL+on7MftNtY9LUoqJfc1p3DaeCMN8xehfZayBF9RxwUvSEtA6Le3bm6Kn8cJFXnDze0zysCUiCIJw1gdGZ00QLfZ8aK7U88dPJasSuOYZ3hf5OWMYKFeaYjzd25FA6XFpOA5N60frtu1UqiNdj5A4pnq9AIWpK6GyjPj1iyVRxRPlOqxe/Q8X79zqxorI1TO8tAiUI505AiFRNDeUhctm6e5+qgTKWO1crGc+aftLxEKhtBe65fRjpg1gdKz/urixnrwrtW46VVaj9D0y+hWpKD5Or3r1aMebgpfTtQTZTDR3ekkMr3v4rrfvPRyeJ04VcIl0QAonAiKTyslRqNf/dJarUoNJnXTx4TP6McXc7lWJysv/kW6pgUOl5/QwWKYWziCOsBKo/uof++8YcFTVhKk59bU22TvosESdBaB8CZ45XaqbNHKqtSB/SP/XdFx5Tm0qc5fTrP71Orz05Q3lL5VE9OXWLUZFR2e6mCzQYPhXYylHWg7/7C21f/Df1HAb8pr1HKdhs9prhLExzrVZ6S0RJENqXwKk4RzSVnvmrnM07Vqi2KV98Q0tWrKY3nv6liqYQLcV3H6pG5tQtxt0dE3VOVUf3EaKwRV9+Q9NuG88RU6Ia1cMNntTQfnY18meY4RYLzYU41ZIgCO1NwM2WRzkCR1O2Q8Wl9PlfnlUCtXFnIaXf/Wuyj5tMuinE7+saK8uoZNOqJi2HIVDREeFK4NiKd1qtem+JnATh/BJQc/eARvoSjqamIlUzijk35TtU94GEyGCKiI0jXQv2FnOqFWIa66m6VCdb6kjanruKGmrdMVJpeaXTWXHcqeumPM3kmicCJQjnn4ATKVWOoNNUREAGmNrCBrcyu0EIe0shoe6mdfV1NbzvROKGlM6k6W/pGmXV5kgrX0G40ARkczS05J0x5ZaMP866R619h4UVSNPHsgAN5eHM3i7d1EvTdJuua05NY5+JXGW6i/IoiLJlUQRBuLgITJHCwgYubcOYKy6zuScEawtrchZNJ0EQOhwB22bWLVS0GJGSxUoTxU8SBEEQBEEQBEEQBEEQBEEQBEEQBEEQBEEQBEEQBEEQBEEQBEEQBEEQBEEQBEEQBEEQBEEQBEEQBEEQBEEQBEEQBEEQBEEQBEEQBEEQBEEQBEEQBEEQBEEQLin+Dz5IwjUsPBVBAAAAAElFTkSuQmCC', }, -} +}; diff --git a/ui/app/pages/swaps/loading-swaps-quotes/loading-swaps-quotes.js b/ui/app/pages/swaps/loading-swaps-quotes/loading-swaps-quotes.js index 684466f27..0a2359bae 100644 --- a/ui/app/pages/swaps/loading-swaps-quotes/loading-swaps-quotes.js +++ b/ui/app/pages/swaps/loading-swaps-quotes/loading-swaps-quotes.js @@ -1,21 +1,21 @@ -import EventEmitter from 'events' -import React, { useState, useEffect, useRef, useContext } from 'react' -import { useDispatch, useSelector } from 'react-redux' -import PropTypes from 'prop-types' -import { shuffle } from 'lodash' -import { useHistory } from 'react-router-dom' -import classnames from 'classnames' +import EventEmitter from 'events'; +import React, { useState, useEffect, useRef, useContext } from 'react'; +import { useDispatch, useSelector } from 'react-redux'; +import PropTypes from 'prop-types'; +import { shuffle } from 'lodash'; +import { useHistory } from 'react-router-dom'; +import classnames from 'classnames'; import { navigateBackToBuildQuote, getFetchParams, getQuotesFetchStartTime, -} from '../../../ducks/swaps/swaps' -import { I18nContext } from '../../../contexts/i18n' -import { MetaMetricsContext } from '../../../contexts/metametrics.new' -import Mascot from '../../../components/ui/mascot' -import SwapsFooter from '../swaps-footer' -import BackgroundAnimation from './background-animation' -import AggregatorLogo from './aggregator-logo' +} from '../../../ducks/swaps/swaps'; +import { I18nContext } from '../../../contexts/i18n'; +import { MetaMetricsContext } from '../../../contexts/metametrics.new'; +import Mascot from '../../../components/ui/mascot'; +import SwapsFooter from '../swaps-footer'; +import BackgroundAnimation from './background-animation'; +import AggregatorLogo from './aggregator-logo'; // These locations reference where we want the top-left corner of the logo div to appear in relation to the // centre point of the fox @@ -26,22 +26,23 @@ const AGGREGATOR_LOCATIONS = [ { x: 50, y: 0 }, { x: -135, y: 46 }, { x: 40, y: 46 }, -] +]; function getRandomLocations(numberOfLocations) { - const randomLocations = shuffle(AGGREGATOR_LOCATIONS) + const randomLocations = shuffle(AGGREGATOR_LOCATIONS); if (numberOfLocations <= AGGREGATOR_LOCATIONS.length) { - return randomLocations.slice(0, numberOfLocations) + return randomLocations.slice(0, numberOfLocations); } - const numberOfExtraLocations = numberOfLocations - AGGREGATOR_LOCATIONS.length - return [...randomLocations, ...getRandomLocations(numberOfExtraLocations)] + const numberOfExtraLocations = + numberOfLocations - AGGREGATOR_LOCATIONS.length; + return [...randomLocations, ...getRandomLocations(numberOfExtraLocations)]; } function getMascotTarget(aggregatorName, centerPoint, aggregatorLocationMap) { - const location = aggregatorLocationMap[aggregatorName] + const location = aggregatorLocationMap[aggregatorName]; if (!location || !centerPoint) { - return centerPoint ?? {} + return centerPoint ?? {}; } // The aggregator logos are 94px x 40px. For the fox to look at the center of each logo, the target needs to be @@ -50,7 +51,7 @@ function getMascotTarget(aggregatorName, centerPoint, aggregatorLocationMap) { return { x: location.x + centerPoint.x + 47, y: location.y + centerPoint.y + 20, - } + }; } export default function LoadingSwapsQuotes({ @@ -58,14 +59,14 @@ export default function LoadingSwapsQuotes({ loadingComplete, onDone, }) { - const t = useContext(I18nContext) - const metaMetricsEvent = useContext(MetaMetricsContext) - const dispatch = useDispatch() - const history = useHistory() - const animationEventEmitter = useRef(new EventEmitter()) + const t = useContext(I18nContext); + const metaMetricsEvent = useContext(MetaMetricsContext); + const dispatch = useDispatch(); + const history = useHistory(); + const animationEventEmitter = useRef(new EventEmitter()); - const fetchParams = useSelector(getFetchParams) - const quotesFetchStartTime = useSelector(getQuotesFetchStartTime) + const fetchParams = useSelector(getFetchParams); + const quotesFetchStartTime = useSelector(getQuotesFetchStartTime); const quotesRequestCancelledEventConfig = { event: 'Quotes Request Cancelled', category: 'swaps', @@ -78,34 +79,34 @@ export default function LoadingSwapsQuotes({ custom_slippage: fetchParams?.slippage !== 2, response_time: Date.now() - quotesFetchStartTime, }, - } + }; const [aggregatorNames] = useState(() => shuffle(Object.keys(aggregatorMetadata)), - ) - const numberOfQuotes = aggregatorNames.length - const mascotContainer = useRef() - const currentMascotContainer = mascotContainer.current + ); + const numberOfQuotes = aggregatorNames.length; + const mascotContainer = useRef(); + const currentMascotContainer = mascotContainer.current; - const [quoteCount, updateQuoteCount] = useState(0) + const [quoteCount, updateQuoteCount] = useState(0); // is an array of randomized items from AGGREGATOR_LOCATIONS, containing // numberOfQuotes number of items it is randomized so that the order in // which the fox looks at locations is random const [aggregatorLocations] = useState(() => getRandomLocations(numberOfQuotes), - ) + ); const _aggregatorLocationMap = aggregatorNames.reduce( (nameLocationMap, name, index) => ({ ...nameLocationMap, [name]: aggregatorLocations[index], }), {}, - ) - const [aggregatorLocationMap] = useState(_aggregatorLocationMap) - const [midPointTarget, setMidpointTarget] = useState(null) + ); + const [aggregatorLocationMap] = useState(_aggregatorLocationMap); + const [midPointTarget, setMidpointTarget] = useState(null); useEffect(() => { - let timeoutLength + let timeoutLength; // The below logic simulates a sequential loading of the aggregator quotes, even though we are fetching them all with a single call. // This is to give the user a sense of progress. The callback passed to `setTimeout` updates the quoteCount and therefore causes @@ -114,27 +115,27 @@ export default function LoadingSwapsQuotes({ // If loading is complete and all logos + aggregator names have been shown, give the user 1.2 seconds to read the // "Finalizing message" and prepare for the screen change if (quoteCount === numberOfQuotes && loadingComplete) { - timeoutLength = 1200 + timeoutLength = 1200; } else if (loadingComplete) { // If loading is complete, but the quoteCount is not, we quickly display the remaining logos/names/fox looks. 0.5s each - timeoutLength = 500 + timeoutLength = 500; } else { // If loading is not complete, we display remaining logos/names/fox looks at random intervals between 0.5s and 2s, to simulate the // sort of loading a user would experience in most async scenarios - timeoutLength = 500 + Math.floor(Math.random() * 1500) + timeoutLength = 500 + Math.floor(Math.random() * 1500); } const quoteCountTimeout = setTimeout(() => { if (quoteCount < numberOfQuotes) { - updateQuoteCount(quoteCount + 1) + updateQuoteCount(quoteCount + 1); } else if (quoteCount === numberOfQuotes && loadingComplete) { - onDone() + onDone(); } - }, timeoutLength) + }, timeoutLength); return function cleanup() { - clearTimeout(quoteCountTimeout) - } - }, [quoteCount, loadingComplete, onDone, numberOfQuotes]) + clearTimeout(quoteCountTimeout); + }; + }, [quoteCount, loadingComplete, onDone, numberOfQuotes]); useEffect(() => { if (currentMascotContainer) { @@ -143,11 +144,11 @@ export default function LoadingSwapsQuotes({ left, width, height, - } = currentMascotContainer.getBoundingClientRect() - const center = { x: left + width / 2, y: top + height / 2 } - setMidpointTarget(center) + } = currentMascotContainer.getBoundingClientRect(); + const center = { x: left + width / 2, y: top + height / 2 }; + setMidpointTarget(center); } - }, [currentMascotContainer]) + }, [currentMascotContainer]); return (
    @@ -226,13 +227,13 @@ export default function LoadingSwapsQuotes({ { - metaMetricsEvent(quotesRequestCancelledEventConfig) - await dispatch(navigateBackToBuildQuote(history)) + metaMetricsEvent(quotesRequestCancelledEventConfig); + await dispatch(navigateBackToBuildQuote(history)); }} hideCancel />
    - ) + ); } LoadingSwapsQuotes.propTypes = { @@ -244,4 +245,4 @@ LoadingSwapsQuotes.propTypes = { icon: PropTypes.string, }), ), -} +}; diff --git a/ui/app/pages/swaps/main-quote-summary/index.js b/ui/app/pages/swaps/main-quote-summary/index.js index 47c9cd3cb..235070e29 100644 --- a/ui/app/pages/swaps/main-quote-summary/index.js +++ b/ui/app/pages/swaps/main-quote-summary/index.js @@ -1 +1 @@ -export { default } from './main-quote-summary' +export { default } from './main-quote-summary'; diff --git a/ui/app/pages/swaps/main-quote-summary/main-quote-summary.js b/ui/app/pages/swaps/main-quote-summary/main-quote-summary.js index 20aadf6fc..9257c53e3 100644 --- a/ui/app/pages/swaps/main-quote-summary/main-quote-summary.js +++ b/ui/app/pages/swaps/main-quote-summary/main-quote-summary.js @@ -1,21 +1,21 @@ -import React from 'react' -import PropTypes from 'prop-types' -import BigNumber from 'bignumber.js' -import { calcTokenAmount } from '../../../helpers/utils/token-util' -import { toPrecisionWithoutTrailingZeros } from '../../../helpers/utils/util' -import Tooltip from '../../../components/ui/tooltip' -import UrlIcon from '../../../components/ui/url-icon' -import ExchangeRateDisplay from '../exchange-rate-display' -import { formatSwapsValueForDisplay } from '../swaps.util' +import React from 'react'; +import PropTypes from 'prop-types'; +import BigNumber from 'bignumber.js'; +import { calcTokenAmount } from '../../../helpers/utils/token-util'; +import { toPrecisionWithoutTrailingZeros } from '../../../helpers/utils/util'; +import Tooltip from '../../../components/ui/tooltip'; +import UrlIcon from '../../../components/ui/url-icon'; +import ExchangeRateDisplay from '../exchange-rate-display'; +import { formatSwapsValueForDisplay } from '../swaps.util'; function getFontSizesAndLineHeights(fontSizeScore) { if (fontSizeScore <= 9) { - return [60, 48] + return [60, 48]; } if (fontSizeScore <= 13) { - return [40, 32] + return [40, 32]; } - return [26, 15] + return [26, 15]; } export default function MainQuoteSummary({ @@ -31,21 +31,21 @@ export default function MainQuoteSummary({ const sourceAmount = toPrecisionWithoutTrailingZeros( calcTokenAmount(sourceValue, sourceDecimals).toString(10), 12, - ) + ); const destinationAmount = calcTokenAmount( destinationValue, destinationDecimals, - ) + ); - const amountToDisplay = formatSwapsValueForDisplay(destinationAmount) - const amountDigitLength = amountToDisplay.match(/\d+/gu).join('').length + const amountToDisplay = formatSwapsValueForDisplay(destinationAmount); + const amountDigitLength = amountToDisplay.match(/\d+/gu).join('').length; const [numberFontSize, lineHeight] = getFontSizesAndLineHeights( amountDigitLength, - ) - let ellipsedAmountToDisplay = amountToDisplay + ); + let ellipsedAmountToDisplay = amountToDisplay; if (amountDigitLength > 20) { - ellipsedAmountToDisplay = `${amountToDisplay.slice(0, 20)}...` + ellipsedAmountToDisplay = `${amountToDisplay.slice(0, 20)}...`; } return ( @@ -122,7 +122,7 @@ export default function MainQuoteSummary({ - ) + ); } MainQuoteSummary.propTypes = { @@ -143,4 +143,4 @@ MainQuoteSummary.propTypes = { destinationSymbol: PropTypes.string.isRequired, sourceIconUrl: PropTypes.string, destinationIconUrl: PropTypes.string, -} +}; diff --git a/ui/app/pages/swaps/main-quote-summary/main-quote-summary.stories.js b/ui/app/pages/swaps/main-quote-summary/main-quote-summary.stories.js index 0f5ca998d..487034ed4 100644 --- a/ui/app/pages/swaps/main-quote-summary/main-quote-summary.stories.js +++ b/ui/app/pages/swaps/main-quote-summary/main-quote-summary.stories.js @@ -1,10 +1,10 @@ -import React from 'react' -import { text, number } from '@storybook/addon-knobs' -import MainQuoteSummary from './main-quote-summary' +import React from 'react'; +import { text, number } from '@storybook/addon-knobs'; +import MainQuoteSummary from './main-quote-summary'; export default { title: 'MainQuoteSummary', -} +}; export const BestQuote = () => { return ( @@ -27,5 +27,5 @@ export const BestQuote = () => { destinationIconUrl=".storybook/images/sai.svg" /> - ) -} + ); +}; diff --git a/ui/app/pages/swaps/main-quote-summary/quote-backdrop.js b/ui/app/pages/swaps/main-quote-summary/quote-backdrop.js index bb2653a62..77bd75fd6 100644 --- a/ui/app/pages/swaps/main-quote-summary/quote-backdrop.js +++ b/ui/app/pages/swaps/main-quote-summary/quote-backdrop.js @@ -1,5 +1,5 @@ -import React from 'react' -import PropTypes from 'prop-types' +import React from 'react'; +import PropTypes from 'prop-types'; export default function QuotesBackdrop({ withTopTab }) { return ( @@ -80,9 +80,9 @@ export default function QuotesBackdrop({ withTopTab }) { - ) + ); } QuotesBackdrop.propTypes = { withTopTab: PropTypes.bool, -} +}; diff --git a/ui/app/pages/swaps/searchable-item-list/index.js b/ui/app/pages/swaps/searchable-item-list/index.js index 2a15a8de3..981085f9a 100644 --- a/ui/app/pages/swaps/searchable-item-list/index.js +++ b/ui/app/pages/swaps/searchable-item-list/index.js @@ -1 +1 @@ -export { default } from './searchable-item-list' +export { default } from './searchable-item-list'; diff --git a/ui/app/pages/swaps/searchable-item-list/item-list/index.js b/ui/app/pages/swaps/searchable-item-list/item-list/index.js index 420fdc9e5..36306eb32 100644 --- a/ui/app/pages/swaps/searchable-item-list/item-list/index.js +++ b/ui/app/pages/swaps/searchable-item-list/item-list/index.js @@ -1 +1 @@ -export { default } from './item-list.component' +export { default } from './item-list.component'; diff --git a/ui/app/pages/swaps/searchable-item-list/item-list/item-list.component.js b/ui/app/pages/swaps/searchable-item-list/item-list/item-list.component.js index 4ef6aeeb5..0601c7242 100644 --- a/ui/app/pages/swaps/searchable-item-list/item-list/item-list.component.js +++ b/ui/app/pages/swaps/searchable-item-list/item-list/item-list.component.js @@ -1,8 +1,8 @@ -import React from 'react' -import PropTypes from 'prop-types' -import classnames from 'classnames' -import Identicon from '../../../../components/ui/identicon' -import UrlIcon from '../../../../components/ui/url-icon' +import React from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; +import Identicon from '../../../../components/ui/identicon'; +import UrlIcon from '../../../../components/ui/url-icon'; export default function ItemList({ results = [], @@ -32,10 +32,10 @@ export default function ItemList({ > {results.slice(0, maxListItems).map((result, i) => { if (hideItemIf?.(result)) { - return null + return null; } - const onClick = () => onClickItem?.(result) + const onClick = () => onClickItem?.(result); const { iconUrl, identiconAddress, @@ -46,7 +46,7 @@ export default function ItemList({ rightPrimaryLabel, rightSecondaryLabel, IconComponent, - } = result + } = result; return (
    - ) + ); })} - ) + ); } ItemList.propTypes = { @@ -127,4 +127,4 @@ ItemList.propTypes = { hideRightLabels: PropTypes.bool, hideItemIf: PropTypes.func, listContainerClassName: PropTypes.string, -} +}; diff --git a/ui/app/pages/swaps/searchable-item-list/list-item-search/index.js b/ui/app/pages/swaps/searchable-item-list/list-item-search/index.js index cfa646b5a..6f816c391 100644 --- a/ui/app/pages/swaps/searchable-item-list/list-item-search/index.js +++ b/ui/app/pages/swaps/searchable-item-list/list-item-search/index.js @@ -1 +1 @@ -export { default } from './list-item-search.component' +export { default } from './list-item-search.component'; diff --git a/ui/app/pages/swaps/searchable-item-list/list-item-search/list-item-search.component.js b/ui/app/pages/swaps/searchable-item-list/list-item-search/list-item-search.component.js index d73e3a9b9..e9e322f40 100644 --- a/ui/app/pages/swaps/searchable-item-list/list-item-search/list-item-search.component.js +++ b/ui/app/pages/swaps/searchable-item-list/list-item-search/list-item-search.component.js @@ -1,15 +1,15 @@ -import React, { useState, useEffect, useRef } from 'react' -import PropTypes from 'prop-types' -import Fuse from 'fuse.js' -import InputAdornment from '@material-ui/core/InputAdornment' -import TextField from '../../../../components/ui/text-field' -import { usePrevious } from '../../../../hooks/usePrevious' +import React, { useState, useEffect, useRef } from 'react'; +import PropTypes from 'prop-types'; +import Fuse from 'fuse.js'; +import InputAdornment from '@material-ui/core/InputAdornment'; +import TextField from '../../../../components/ui/text-field'; +import { usePrevious } from '../../../../hooks/usePrevious'; const renderAdornment = () => ( -) +); export default function ListItemSearch({ onSearch, @@ -19,18 +19,18 @@ export default function ListItemSearch({ searchPlaceholderText, defaultToAll, }) { - const fuseRef = useRef() - const [searchQuery, setSearchQuery] = useState('') + const fuseRef = useRef(); + const [searchQuery, setSearchQuery] = useState(''); const handleSearch = (newSearchQuery) => { - setSearchQuery(newSearchQuery) - const fuseSearchResult = fuseRef.current.search(newSearchQuery) + setSearchQuery(newSearchQuery); + const fuseSearchResult = fuseRef.current.search(newSearchQuery); onSearch({ searchQuery: newSearchQuery, results: defaultToAll && newSearchQuery === '' ? listToSearch : fuseSearchResult, - }) - } + }); + }; useEffect(() => { if (!fuseRef.current) { @@ -42,22 +42,22 @@ export default function ListItemSearch({ maxPatternLength: 32, minMatchCharLength: 1, keys: fuseSearchKeys, - }) + }); } - }, [fuseSearchKeys, listToSearch]) + }, [fuseSearchKeys, listToSearch]); - const previousListToSearch = usePrevious(listToSearch) || [] + const previousListToSearch = usePrevious(listToSearch) || []; useEffect(() => { if ( fuseRef.current && searchQuery && previousListToSearch !== listToSearch ) { - fuseRef.current.setCollection(listToSearch) - const fuseSearchResult = fuseRef.current.search(searchQuery) - onSearch({ searchQuery, results: fuseSearchResult }) + fuseRef.current.setCollection(listToSearch); + const fuseSearchResult = fuseRef.current.search(searchQuery); + onSearch({ searchQuery, results: fuseSearchResult }); } - }, [listToSearch, searchQuery, onSearch, previousListToSearch]) + }, [listToSearch, searchQuery, onSearch, previousListToSearch]); return ( - ) + ); } ListItemSearch.propTypes = { @@ -83,4 +83,4 @@ ListItemSearch.propTypes = { fuseSearchKeys: PropTypes.arrayOf(PropTypes.object).isRequired, searchPlaceholderText: PropTypes.string, defaultToAll: PropTypes.bool, -} +}; diff --git a/ui/app/pages/swaps/searchable-item-list/searchable-item-list.js b/ui/app/pages/swaps/searchable-item-list/searchable-item-list.js index 2f92c113e..ba871339e 100644 --- a/ui/app/pages/swaps/searchable-item-list/searchable-item-list.js +++ b/ui/app/pages/swaps/searchable-item-list/searchable-item-list.js @@ -1,7 +1,7 @@ -import React, { useState, useRef } from 'react' -import PropTypes from 'prop-types' -import ItemList from './item-list' -import ListItemSearch from './list-item-search' +import React, { useState, useRef } from 'react'; +import PropTypes from 'prop-types'; +import ItemList from './item-list'; +import ListItemSearch from './list-item-search'; export default function SearchableItemList({ className, @@ -18,10 +18,10 @@ export default function SearchableItemList({ hideItemIf, listContainerClassName, }) { - const itemListRef = useRef() + const itemListRef = useRef(); - const [results, setResults] = useState(defaultToAll ? itemsToSearch : []) - const [searchQuery, setSearchQuery] = useState('') + const [results, setResults] = useState(defaultToAll ? itemsToSearch : []); + const [searchQuery, setSearchQuery] = useState(''); return (
    @@ -32,8 +32,8 @@ export default function SearchableItemList({ searchQuery: newSearchQuery = '', results: newResults = [], }) => { - setSearchQuery(newSearchQuery) - setResults(newResults) + setSearchQuery(newSearchQuery); + setResults(newResults); }} error={itemSelectorError} searchPlaceholderText={searchPlaceholderText} @@ -52,7 +52,7 @@ export default function SearchableItemList({ listContainerClassName={listContainerClassName} />
    - ) + ); } SearchableItemList.propTypes = { @@ -74,4 +74,4 @@ SearchableItemList.propTypes = { hideRightLabels: PropTypes.bool, hideItemIf: PropTypes.func, listContainerClassName: PropTypes.string, -} +}; diff --git a/ui/app/pages/swaps/select-quote-popover/index.js b/ui/app/pages/swaps/select-quote-popover/index.js index 6ffabdf2d..288e4acbd 100644 --- a/ui/app/pages/swaps/select-quote-popover/index.js +++ b/ui/app/pages/swaps/select-quote-popover/index.js @@ -1 +1 @@ -export { default } from './select-quote-popover' +export { default } from './select-quote-popover'; diff --git a/ui/app/pages/swaps/select-quote-popover/mock-quote-data.js b/ui/app/pages/swaps/select-quote-popover/mock-quote-data.js index f6c2dbd5f..93d49281a 100644 --- a/ui/app/pages/swaps/select-quote-popover/mock-quote-data.js +++ b/ui/app/pages/swaps/select-quote-popover/mock-quote-data.js @@ -89,6 +89,6 @@ const quoteDataRows = [ sourceTokenSymbol: 'ETH', sourceTokenValue: '250000000000000000', }, -] +]; -export default quoteDataRows +export default quoteDataRows; diff --git a/ui/app/pages/swaps/select-quote-popover/quote-details/index.js b/ui/app/pages/swaps/select-quote-popover/quote-details/index.js index ffe541b1e..544808b12 100644 --- a/ui/app/pages/swaps/select-quote-popover/quote-details/index.js +++ b/ui/app/pages/swaps/select-quote-popover/quote-details/index.js @@ -1 +1 @@ -export { default } from './quote-details' +export { default } from './quote-details'; diff --git a/ui/app/pages/swaps/select-quote-popover/quote-details/quote-details.js b/ui/app/pages/swaps/select-quote-popover/quote-details/quote-details.js index 96692f3a8..6d96123e0 100644 --- a/ui/app/pages/swaps/select-quote-popover/quote-details/quote-details.js +++ b/ui/app/pages/swaps/select-quote-popover/quote-details/quote-details.js @@ -1,8 +1,8 @@ -import React, { useContext } from 'react' -import PropTypes from 'prop-types' -import { I18nContext } from '../../../../contexts/i18n' -import InfoTooltip from '../../../../components/ui/info-tooltip' -import ExchangeRateDisplay from '../../exchange-rate-display' +import React, { useContext } from 'react'; +import PropTypes from 'prop-types'; +import { I18nContext } from '../../../../contexts/i18n'; +import InfoTooltip from '../../../../components/ui/info-tooltip'; +import ExchangeRateDisplay from '../../exchange-rate-display'; const QuoteDetails = ({ slippage, @@ -16,7 +16,7 @@ const QuoteDetails = ({ networkFees, metaMaskFee, }) => { - const t = useContext(I18nContext) + const t = useContext(I18nContext); return (
    @@ -91,8 +91,8 @@ const QuoteDetails = ({
    - ) -} + ); +}; QuoteDetails.propTypes = { slippage: PropTypes.number.isRequired, @@ -105,6 +105,6 @@ QuoteDetails.propTypes = { feeInEth: PropTypes.string.isRequired, networkFees: PropTypes.string.isRequired, metaMaskFee: PropTypes.number.isRequired, -} +}; -export default QuoteDetails +export default QuoteDetails; diff --git a/ui/app/pages/swaps/select-quote-popover/select-quote-popover-constants.js b/ui/app/pages/swaps/select-quote-popover/select-quote-popover-constants.js index 8d25a5b93..d2754208e 100644 --- a/ui/app/pages/swaps/select-quote-popover/select-quote-popover-constants.js +++ b/ui/app/pages/swaps/select-quote-popover/select-quote-popover-constants.js @@ -1,4 +1,4 @@ -import PropTypes from 'prop-types' +import PropTypes from 'prop-types'; export const QUOTE_DATA_ROWS_PROPTYPES_SHAPE = PropTypes.shape({ aggId: PropTypes.string.isRequired, @@ -14,4 +14,4 @@ export const QUOTE_DATA_ROWS_PROPTYPES_SHAPE = PropTypes.shape({ sourceTokenDecimals: PropTypes.number.isRequired, sourceTokenSymbol: PropTypes.string.isRequired, sourceTokenValue: PropTypes.string.isRequired, -}) +}); diff --git a/ui/app/pages/swaps/select-quote-popover/select-quote-popover.js b/ui/app/pages/swaps/select-quote-popover/select-quote-popover.js index cc5314f28..c3efcba48 100644 --- a/ui/app/pages/swaps/select-quote-popover/select-quote-popover.js +++ b/ui/app/pages/swaps/select-quote-popover/select-quote-popover.js @@ -1,11 +1,11 @@ -import React, { useState, useCallback, useContext } from 'react' -import PropTypes from 'prop-types' -import { I18nContext } from '../../../contexts/i18n' -import Popover from '../../../components/ui/popover' -import Button from '../../../components/ui/button' -import QuoteDetails from './quote-details' -import SortList from './sort-list' -import { QUOTE_DATA_ROWS_PROPTYPES_SHAPE } from './select-quote-popover-constants' +import React, { useState, useCallback, useContext } from 'react'; +import PropTypes from 'prop-types'; +import { I18nContext } from '../../../contexts/i18n'; +import Popover from '../../../components/ui/popover'; +import Button from '../../../components/ui/button'; +import QuoteDetails from './quote-details'; +import SortList from './sort-list'; +import { QUOTE_DATA_ROWS_PROPTYPES_SHAPE } from './select-quote-popover-constants'; const SelectQuotePopover = ({ quoteDataRows = [], @@ -15,45 +15,45 @@ const SelectQuotePopover = ({ initialAggId, onQuoteDetailsIsOpened, }) => { - const t = useContext(I18nContext) + const t = useContext(I18nContext); - const [sortDirection, setSortDirection] = useState(1) - const [sortColumn, setSortColumn] = useState(null) + const [sortDirection, setSortDirection] = useState(1); + const [sortColumn, setSortColumn] = useState(null); - const [selectedAggId, setSelectedAggId] = useState(initialAggId) - const [contentView, setContentView] = useState('sortList') - const [viewingAgg, setViewingAgg] = useState(null) + const [selectedAggId, setSelectedAggId] = useState(initialAggId); + const [contentView, setContentView] = useState('sortList'); + const [viewingAgg, setViewingAgg] = useState(null); const onSubmitClick = useCallback(() => { - onSubmit(selectedAggId) - onClose() - }, [selectedAggId, onClose, onSubmit]) + onSubmit(selectedAggId); + onClose(); + }, [selectedAggId, onClose, onSubmit]); const closeQuoteDetails = useCallback(() => { - setViewingAgg(null) - setContentView('sortList') - }, []) + setViewingAgg(null); + setContentView('sortList'); + }, []); const onRowClick = useCallback((aggId) => setSelectedAggId(aggId), [ setSelectedAggId, - ]) + ]); const onCaretClick = useCallback( (aggId) => { - const agg = quoteDataRows.find((quote) => quote.aggId === aggId) - setContentView('quoteDetails') - onQuoteDetailsIsOpened() - setViewingAgg(agg) + const agg = quoteDataRows.find((quote) => quote.aggId === aggId); + setContentView('quoteDetails'); + onQuoteDetailsIsOpened(); + setViewingAgg(agg); }, [quoteDataRows, onQuoteDetailsIsOpened], - ) + ); const CustomBackground = useCallback( () => (
    ), [onClose], - ) + ); const footer = ( <>
    - ) + ); } SlippageButtons.propTypes = { onSelect: PropTypes.func.isRequired, maxAllowedSlippage: PropTypes.number.isRequired, -} +}; diff --git a/ui/app/pages/swaps/slippage-buttons/slippage-buttons.stories.js b/ui/app/pages/swaps/slippage-buttons/slippage-buttons.stories.js index 035513596..63671fe95 100644 --- a/ui/app/pages/swaps/slippage-buttons/slippage-buttons.stories.js +++ b/ui/app/pages/swaps/slippage-buttons/slippage-buttons.stories.js @@ -1,13 +1,13 @@ -import React from 'react' -import { action } from '@storybook/addon-actions' -import SlippageButtons from '.' +import React from 'react'; +import { action } from '@storybook/addon-actions'; +import SlippageButtons from '.'; export default { title: 'SlippageButtons', -} +}; export const Default = () => (
    -) +); diff --git a/ui/app/pages/swaps/swaps-footer/index.js b/ui/app/pages/swaps/swaps-footer/index.js index 5672e3c1b..0c529e3a3 100644 --- a/ui/app/pages/swaps/swaps-footer/index.js +++ b/ui/app/pages/swaps/swaps-footer/index.js @@ -1 +1 @@ -export { default } from './swaps-footer' +export { default } from './swaps-footer'; diff --git a/ui/app/pages/swaps/swaps-footer/swaps-footer.js b/ui/app/pages/swaps/swaps-footer/swaps-footer.js index 62a3e2a70..faefa85db 100644 --- a/ui/app/pages/swaps/swaps-footer/swaps-footer.js +++ b/ui/app/pages/swaps/swaps-footer/swaps-footer.js @@ -1,9 +1,9 @@ -import React, { useContext } from 'react' -import PropTypes from 'prop-types' -import classnames from 'classnames' -import { I18nContext } from '../../../contexts/i18n' +import React, { useContext } from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; +import { I18nContext } from '../../../contexts/i18n'; -import PageContainerFooter from '../../../components/ui/page-container/page-container-footer' +import PageContainerFooter from '../../../components/ui/page-container/page-container-footer'; export default function SwapsFooter({ onCancel, @@ -15,7 +15,7 @@ export default function SwapsFooter({ showTopBorder, className = '', }) { - const t = useContext(I18nContext) + const t = useContext(I18nContext); return (
    @@ -55,7 +55,7 @@ export default function SwapsFooter({
    )} - ) + ); } SwapsFooter.propTypes = { @@ -67,4 +67,4 @@ SwapsFooter.propTypes = { showTermsOfService: PropTypes.bool, showTopBorder: PropTypes.bool, className: PropTypes.string, -} +}; diff --git a/ui/app/pages/swaps/swaps-gas-customization-modal/index.js b/ui/app/pages/swaps/swaps-gas-customization-modal/index.js index 645372331..a54988ab9 100644 --- a/ui/app/pages/swaps/swaps-gas-customization-modal/index.js +++ b/ui/app/pages/swaps/swaps-gas-customization-modal/index.js @@ -1 +1 @@ -export { default } from './swaps-gas-customization-modal.container' +export { default } from './swaps-gas-customization-modal.container'; diff --git a/ui/app/pages/swaps/swaps-gas-customization-modal/swaps-gas-customization-modal.component.js b/ui/app/pages/swaps/swaps-gas-customization-modal/swaps-gas-customization-modal.component.js index 1347529dc..5a0a2dfe9 100644 --- a/ui/app/pages/swaps/swaps-gas-customization-modal/swaps-gas-customization-modal.component.js +++ b/ui/app/pages/swaps/swaps-gas-customization-modal/swaps-gas-customization-modal.component.js @@ -1,18 +1,18 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import PageContainer from '../../../components/ui/page-container' -import { Tabs, Tab } from '../../../components/ui/tabs' -import { calcGasTotal } from '../../send/send.utils' -import { sumHexWEIsToUnformattedFiat } from '../../../helpers/utils/conversions.util' -import AdvancedGasInputs from '../../../components/app/gas-customization/advanced-gas-inputs' -import BasicTabContent from '../../../components/app/gas-customization/gas-modal-page-container/basic-tab-content' -import { GAS_ESTIMATE_TYPES } from '../../../helpers/constants/common' +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import PageContainer from '../../../components/ui/page-container'; +import { Tabs, Tab } from '../../../components/ui/tabs'; +import { calcGasTotal } from '../../send/send.utils'; +import { sumHexWEIsToUnformattedFiat } from '../../../helpers/utils/conversions.util'; +import AdvancedGasInputs from '../../../components/app/gas-customization/advanced-gas-inputs'; +import BasicTabContent from '../../../components/app/gas-customization/gas-modal-page-container/basic-tab-content'; +import { GAS_ESTIMATE_TYPES } from '../../../helpers/constants/common'; export default class GasModalPageContainer extends Component { static contextTypes = { t: PropTypes.func, trackEvent: PropTypes.func, - } + }; static propTypes = { insufficientBalance: PropTypes.bool, @@ -42,17 +42,17 @@ export default class GasModalPageContainer extends Component { setSwapsCustomizationModalLimit: PropTypes.func, gasEstimateLoadingHasFailed: PropTypes.bool, minimumGasLimit: PropTypes.number.isRequired, - } + }; state = { gasSpeedType: '', - } + }; setGasSpeedType(gasEstimateType) { if (gasEstimateType === GAS_ESTIMATE_TYPES.AVERAGE) { - this.setState({ gasSpeedType: 'average' }) + this.setState({ gasSpeedType: 'average' }); } else { - this.setState({ gasSpeedType: 'fast' }) + this.setState({ gasSpeedType: 'fast' }); } } @@ -62,12 +62,12 @@ export default class GasModalPageContainer extends Component { gasPriceButtonGroupProps={{ ...gasPriceButtonGroupProps, handleGasPriceSelection: ({ gasPrice, gasEstimateType }) => { - this.setGasSpeedType(gasEstimateType) - this.props.setSwapsCustomizationModalPrice(gasPrice) + this.setGasSpeedType(gasEstimateType); + this.props.setSwapsCustomizationModalPrice(gasPrice); }, }} /> - ) + ); } renderAdvancedTabContent() { @@ -81,7 +81,7 @@ export default class GasModalPageContainer extends Component { customGasPrice, customGasLimit, minimumGasLimit, - } = this.props + } = this.props; return (
    @@ -99,12 +99,12 @@ export default class GasModalPageContainer extends Component {
    { - this.setState({ gasSpeedType: 'custom' }) - setSwapsCustomizationModalPrice(updatedPrice) + this.setState({ gasSpeedType: 'custom' }); + setSwapsCustomizationModalPrice(updatedPrice); }} updateCustomGasLimit={(updatedLimit) => { - this.setState({ gasSpeedType: 'custom' }) - setSwapsCustomizationModalLimit(updatedLimit) + this.setState({ gasSpeedType: 'custom' }); + setSwapsCustomizationModalLimit(updatedLimit); }} customGasPrice={customGasPrice} customGasLimit={customGasLimit} @@ -116,7 +116,7 @@ export default class GasModalPageContainer extends Component {
    - ) + ); } renderInfoRows( @@ -170,7 +170,7 @@ export default class GasModalPageContainer extends Component { - ) + ); } renderTabs() { @@ -184,7 +184,7 @@ export default class GasModalPageContainer extends Component { extraInfoRow, }, gasEstimateLoadingHasFailed, - } = this.props + } = this.props; const basicTabInfo = { name: this.context.t('basic'), @@ -192,15 +192,15 @@ export default class GasModalPageContainer extends Component { ...gasPriceButtonGroupProps, handleGasPriceSelection: this.props.setSwapsCustomizationModalPrice, }), - } + }; const advancedTabInfo = { name: this.context.t('advanced'), content: this.renderAdvancedTabContent(), - } + }; const tabsToRender = gasEstimateLoadingHasFailed ? [advancedTabInfo] - : [basicTabInfo, advancedTabInfo] + : [basicTabInfo, advancedTabInfo]; return ( @@ -219,7 +219,7 @@ export default class GasModalPageContainer extends Component { ))} - ) + ); } render() { @@ -229,7 +229,7 @@ export default class GasModalPageContainer extends Component { disableSave, customGasPrice, customGasLimit, - } = this.props + } = this.props; return (
    @@ -241,7 +241,10 @@ export default class GasModalPageContainer extends Component { onCancel={() => cancelAndClose()} onClose={() => cancelAndClose()} onSubmit={() => { - const newSwapGasTotal = calcGasTotal(customGasLimit, customGasPrice) + const newSwapGasTotal = calcGasTotal( + customGasLimit, + customGasPrice, + ); this.context.trackEvent({ event: 'Gas Fees Changed', @@ -254,14 +257,14 @@ export default class GasModalPageContainer extends Component { this.props.usdConversionRate, )?.slice(1), }, - }) - onSubmit(customGasLimit, customGasPrice) + }); + onSubmit(customGasLimit, customGasPrice); }} submitText={this.context.t('save')} headerCloseText={this.context.t('close')} hideCancel />
    - ) + ); } } diff --git a/ui/app/pages/swaps/swaps-gas-customization-modal/swaps-gas-customization-modal.container.js b/ui/app/pages/swaps/swaps-gas-customization-modal/swaps-gas-customization-modal.container.js index deea5c4b0..2a717fc36 100644 --- a/ui/app/pages/swaps/swaps-gas-customization-modal/swaps-gas-customization-modal.container.js +++ b/ui/app/pages/swaps/swaps-gas-customization-modal/swaps-gas-customization-modal.container.js @@ -1,6 +1,6 @@ -import { connect } from 'react-redux' -import BigNumber from 'bignumber.js' -import { hideModal, customSwapsGasParamsUpdated } from '../../../store/actions' +import { connect } from 'react-redux'; +import BigNumber from 'bignumber.js'; +import { hideModal, customSwapsGasParamsUpdated } from '../../../store/actions'; import { conversionRateSelector as getConversionRate, getCurrentCurrency, @@ -8,7 +8,7 @@ import { getDefaultActiveButtonIndex, getRenderableGasButtonData, getUSDConversionRate, -} from '../../../selectors' +} from '../../../selectors'; import { getSwapsCustomizationModalPrice, @@ -20,22 +20,22 @@ import { swapCustomGasModalLimitEdited, shouldShowCustomPriceTooLowWarning, swapCustomGasModalClosed, -} from '../../../ducks/swaps/swaps' +} from '../../../ducks/swaps/swaps'; import { addHexes, getValueFromWeiHex, sumHexWEIsToRenderableFiat, -} from '../../../helpers/utils/conversions.util' -import { formatETHFee } from '../../../helpers/utils/formatters' -import { calcGasTotal, isBalanceSufficient } from '../../send/send.utils' -import SwapsGasCustomizationModalComponent from './swaps-gas-customization-modal.component' +} from '../../../helpers/utils/conversions.util'; +import { formatETHFee } from '../../../helpers/utils/formatters'; +import { calcGasTotal, isBalanceSufficient } from '../../send/send.utils'; +import SwapsGasCustomizationModalComponent from './swaps-gas-customization-modal.component'; const mapStateToProps = (state) => { - const currentCurrency = getCurrentCurrency(state) - const conversionRate = getConversionRate(state) + const currentCurrency = getCurrentCurrency(state); + const conversionRate = getConversionRate(state); - const { modalState: { props: modalProps } = {} } = state.appState.modal || {} + const { modalState: { props: modalProps } = {} } = state.appState.modal || {}; const { value, customGasLimitMessage = '', @@ -44,18 +44,18 @@ const mapStateToProps = (state) => { initialGasPrice, initialGasLimit, minimumGasLimit, - } = modalProps - const buttonDataLoading = swapGasPriceEstimateIsLoading(state) + } = modalProps; + const buttonDataLoading = swapGasPriceEstimateIsLoading(state); - const swapsCustomizationModalPrice = getSwapsCustomizationModalPrice(state) - const swapsCustomizationModalLimit = getSwapsCustomizationModalLimit(state) + const swapsCustomizationModalPrice = getSwapsCustomizationModalPrice(state); + const swapsCustomizationModalLimit = getSwapsCustomizationModalLimit(state); - const customGasPrice = swapsCustomizationModalPrice || initialGasPrice - const customGasLimit = swapsCustomizationModalLimit || initialGasLimit + const customGasPrice = swapsCustomizationModalPrice || initialGasPrice; + const customGasLimit = swapsCustomizationModalLimit || initialGasLimit; - const customGasTotal = calcGasTotal(customGasLimit, customGasPrice) + const customGasTotal = calcGasTotal(customGasLimit, customGasPrice); - const swapsGasPriceEstimates = getSwapGasPriceEstimateData(state) + const swapsGasPriceEstimates = getSwapGasPriceEstimateData(state); const { averageEstimateData, fastEstimateData } = getRenderableGasButtonData( swapsGasPriceEstimates, @@ -63,36 +63,36 @@ const mapStateToProps = (state) => { true, conversionRate, currentCurrency, - ) - const gasButtonInfo = [averageEstimateData, fastEstimateData] + ); + const gasButtonInfo = [averageEstimateData, fastEstimateData]; const newTotalFiat = sumHexWEIsToRenderableFiat( [value, customGasTotal, customTotalSupplement], currentCurrency, conversionRate, - ) + ); - const balance = getCurrentEthBalance(state) + const balance = getCurrentEthBalance(state); const newTotalEth = sumHexWEIsToRenderableEth([ value, customGasTotal, customTotalSupplement, - ]) + ]); - const sendAmount = sumHexWEIsToRenderableEth([value, '0x0']) + const sendAmount = sumHexWEIsToRenderableEth([value, '0x0']); const insufficientBalance = !isBalanceSufficient({ amount: value, gasTotal: customGasTotal, balance, conversionRate, - }) + }); const customGasLimitTooLow = new BigNumber(customGasLimit, 16).lt( minimumGasLimit, 10, - ) + ); return { customGasPrice, @@ -130,41 +130,41 @@ const mapStateToProps = (state) => { usdConversionRate: getUSDConversionRate(state), disableSave: insufficientBalance || customGasLimitTooLow, minimumGasLimit, - } -} + }; +}; const mapDispatchToProps = (dispatch) => { return { cancelAndClose: () => { - dispatch(swapCustomGasModalClosed()) - dispatch(hideModal()) + dispatch(swapCustomGasModalClosed()); + dispatch(hideModal()); }, onSubmit: async (gasLimit, gasPrice) => { - await dispatch(customSwapsGasParamsUpdated(gasLimit, gasPrice)) - dispatch(swapCustomGasModalClosed()) - dispatch(hideModal()) + await dispatch(customSwapsGasParamsUpdated(gasLimit, gasPrice)); + dispatch(swapCustomGasModalClosed()); + dispatch(hideModal()); }, setSwapsCustomizationModalPrice: (newPrice) => { - dispatch(swapCustomGasModalPriceEdited(newPrice)) + dispatch(swapCustomGasModalPriceEdited(newPrice)); }, setSwapsCustomizationModalLimit: (newLimit) => { - dispatch(swapCustomGasModalLimitEdited(newLimit)) + dispatch(swapCustomGasModalLimitEdited(newLimit)); }, - } -} + }; +}; export default connect( mapStateToProps, mapDispatchToProps, -)(SwapsGasCustomizationModalComponent) +)(SwapsGasCustomizationModalComponent); function sumHexWEIsToRenderableEth(hexWEIs) { - const hexWEIsSum = hexWEIs.filter(Boolean).reduce(addHexes) + const hexWEIsSum = hexWEIs.filter(Boolean).reduce(addHexes); return formatETHFee( getValueFromWeiHex({ value: hexWEIsSum, toCurrency: 'ETH', numberOfDecimals: 6, }), - ) + ); } diff --git a/ui/app/pages/swaps/swaps-util-test-constants.js b/ui/app/pages/swaps/swaps-util-test-constants.js index b1ec1dbc5..6bf2207c6 100644 --- a/ui/app/pages/swaps/swaps-util-test-constants.js +++ b/ui/app/pages/swaps/swaps-util-test-constants.js @@ -1,12 +1,13 @@ -import { ETH_SWAPS_TOKEN_OBJECT } from '../../helpers/constants/swaps' +import { ETH_SWAPS_TOKEN_OBJECT } from '../../helpers/constants/swaps'; export const TRADES_BASE_PROD_URL = - 'https://api.metaswap.codefi.network/trades?' -export const TOKENS_BASE_PROD_URL = 'https://api.metaswap.codefi.network/tokens' + 'https://api.metaswap.codefi.network/trades?'; +export const TOKENS_BASE_PROD_URL = + 'https://api.metaswap.codefi.network/tokens'; export const AGGREGATOR_METADATA_BASE_PROD_URL = - 'https://api.metaswap.codefi.network/aggregatorMetadata' + 'https://api.metaswap.codefi.network/aggregatorMetadata'; export const TOP_ASSET_BASE_PROD_URL = - 'https://api.metaswap.codefi.network/topAssets' + 'https://api.metaswap.codefi.network/topAssets'; export const TOKENS = [ { @@ -82,7 +83,7 @@ export const TOKENS = [ address: '0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599', }, ETH_SWAPS_TOKEN_OBJECT, -] +]; export const MOCK_TRADE_RESPONSE_1 = [ { @@ -151,12 +152,12 @@ export const MOCK_TRADE_RESPONSE_1 = [ aggregator: 'zeroEx', aggType: 'AGG', }, -] +]; export const MOCK_TRADE_RESPONSE_2 = MOCK_TRADE_RESPONSE_1.map((trade) => ({ ...trade, sourceAmount: '20000000000000000', -})) +})); export const AGGREGATOR_METADATA = { agg1: { @@ -169,7 +170,7 @@ export const AGGREGATOR_METADATA = { title: 'agg2', icon: 'data:image/png;base64,iVBORw0KGgoAAA', }, -} +}; export const TOP_ASSETS = [ { @@ -192,4 +193,4 @@ export const TOP_ASSETS = [ symbol: 'SNX', address: '0xc011a73ee8576fb46f5e1c5751ca3b9fe0af2a6f', }, -] +]; diff --git a/ui/app/pages/swaps/swaps.util.js b/ui/app/pages/swaps/swaps.util.js index 0fcc5d8a2..934caf509 100644 --- a/ui/app/pages/swaps/swaps.util.js +++ b/ui/app/pages/swaps/swaps.util.js @@ -1,56 +1,59 @@ -import log from 'loglevel' -import BigNumber from 'bignumber.js' -import abi from 'human-standard-token-abi' -import { isValidAddress } from 'ethereumjs-util' -import { ETH_SWAPS_TOKEN_OBJECT } from '../../helpers/constants/swaps' -import { calcTokenValue, calcTokenAmount } from '../../helpers/utils/token-util' +import log from 'loglevel'; +import BigNumber from 'bignumber.js'; +import abi from 'human-standard-token-abi'; +import { isValidAddress } from 'ethereumjs-util'; +import { ETH_SWAPS_TOKEN_OBJECT } from '../../helpers/constants/swaps'; +import { + calcTokenValue, + calcTokenAmount, +} from '../../helpers/utils/token-util'; import { constructTxParams, toPrecisionWithoutTrailingZeros, -} from '../../helpers/utils/util' +} from '../../helpers/utils/util'; import { decimalToHex, getValueFromWeiHex, -} from '../../helpers/utils/conversions.util' +} from '../../helpers/utils/conversions.util'; -import { subtractCurrencies } from '../../helpers/utils/conversion-util' -import { formatCurrency } from '../../helpers/utils/confirm-tx.util' -import fetchWithCache from '../../helpers/utils/fetch-with-cache' +import { subtractCurrencies } from '../../helpers/utils/conversion-util'; +import { formatCurrency } from '../../helpers/utils/confirm-tx.util'; +import fetchWithCache from '../../helpers/utils/fetch-with-cache'; -import { calcGasTotal } from '../send/send.utils' +import { calcGasTotal } from '../send/send.utils'; const TOKEN_TRANSFER_LOG_TOPIC_HASH = - '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef' + '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef'; -const CACHE_REFRESH_ONE_HOUR = 3600000 +const CACHE_REFRESH_ONE_HOUR = 3600000; -const METASWAP_API_HOST = 'https://api.metaswap.codefi.network' +const METASWAP_API_HOST = 'https://api.metaswap.codefi.network'; const getBaseApi = function (type) { switch (type) { case 'trade': - return `${METASWAP_API_HOST}/trades?` + return `${METASWAP_API_HOST}/trades?`; case 'tokens': - return `${METASWAP_API_HOST}/tokens` + return `${METASWAP_API_HOST}/tokens`; case 'topAssets': - return `${METASWAP_API_HOST}/topAssets` + return `${METASWAP_API_HOST}/topAssets`; case 'featureFlag': - return `${METASWAP_API_HOST}/featureFlag` + return `${METASWAP_API_HOST}/featureFlag`; case 'aggregatorMetadata': - return `${METASWAP_API_HOST}/aggregatorMetadata` + return `${METASWAP_API_HOST}/aggregatorMetadata`; case 'gasPrices': - return `${METASWAP_API_HOST}/gasPrices` + return `${METASWAP_API_HOST}/gasPrices`; case 'refreshTime': - return `${METASWAP_API_HOST}/quoteRefreshRate` + return `${METASWAP_API_HOST}/quoteRefreshRate`; default: - throw new Error('getBaseApi requires an api call type') + throw new Error('getBaseApi requires an api call type'); } -} +}; -const validHex = (string) => Boolean(string?.match(/^0x[a-f0-9]+$/u)) -const truthyString = (string) => Boolean(string?.length) +const validHex = (string) => Boolean(string?.match(/^0x[a-f0-9]+$/u)); +const truthyString = (string) => Boolean(string?.length); const truthyDigitString = (string) => - truthyString(string) && Boolean(string.match(/^\d+$/u)) + truthyString(string) && Boolean(string.match(/^\d+$/u)); const QUOTE_VALIDATORS = [ { @@ -121,7 +124,7 @@ const QUOTE_VALIDATORS = [ type: 'number|undefined', validator: (gasEstimate) => gasEstimate === undefined || gasEstimate > 0, }, -] +]; const TOKEN_VALIDATORS = [ { @@ -139,9 +142,9 @@ const TOKEN_VALIDATORS = [ type: 'string|number', validator: (string) => Number(string) >= 0 && Number(string) <= 36, }, -] +]; -const TOP_ASSET_VALIDATORS = TOKEN_VALIDATORS.slice(0, 2) +const TOP_ASSET_VALIDATORS = TOKEN_VALIDATORS.slice(0, 2); const AGGREGATOR_METADATA_VALIDATORS = [ { @@ -159,10 +162,10 @@ const AGGREGATOR_METADATA_VALIDATORS = [ type: 'string', validator: (string) => Boolean(string.match(/^data:image/u)), }, -] +]; const isValidDecimalNumber = (string) => - !isNaN(string) && string.match(/^[.0-9]+$/u) && !isNaN(parseFloat(string)) + !isNaN(string) && string.match(/^[.0-9]+$/u) && !isNaN(parseFloat(string)); const SWAP_GAS_PRICE_VALIDATOR = [ { @@ -180,25 +183,25 @@ const SWAP_GAS_PRICE_VALIDATOR = [ type: 'string', validator: isValidDecimalNumber, }, -] +]; function validateData(validators, object, urlUsed) { return validators.every(({ property, type, validator }) => { - const types = type.split('|') + const types = type.split('|'); const valid = types.some((_type) => typeof object[property] === _type) && - (!validator || validator(object[property])) + (!validator || validator(object[property])); if (!valid) { log.error( `response to GET ${urlUsed} invalid for property ${property}; value was:`, object[property], '| type was: ', typeof object[property], - ) + ); } - return valid - }) + return valid; + }); } export async function fetchTradesInfo({ @@ -217,19 +220,19 @@ export async function fetchTradesInfo({ slippage, timeout: 10000, walletAddress: fromAddress, - } + }; if (exchangeList) { - urlParams.exchangeList = exchangeList + urlParams.exchangeList = exchangeList; } - const queryString = new URLSearchParams(urlParams).toString() - const tradeURL = `${getBaseApi('trade')}${queryString}` + const queryString = new URLSearchParams(urlParams).toString(); + const tradeURL = `${getBaseApi('trade')}${queryString}`; const tradesResponse = await fetchWithCache( tradeURL, { method: 'GET' }, { cacheRefreshTime: 0, timeout: 15000 }, - ) + ); const newQuotes = tradesResponse.reduce((aggIdTradeMap, quote) => { if ( quote.trade && @@ -242,14 +245,14 @@ export async function fetchTradesInfo({ data: quote.trade.data, amount: decimalToHex(quote.trade.value), gas: decimalToHex(quote.maxGas), - }) + }); - let { approvalNeeded } = quote + let { approvalNeeded } = quote; if (approvalNeeded) { approvalNeeded = constructTxParams({ ...approvalNeeded, - }) + }); } return { @@ -260,39 +263,39 @@ export async function fetchTradesInfo({ trade: constructedTrade, approvalNeeded, }, - } + }; } - return aggIdTradeMap - }, {}) + return aggIdTradeMap; + }, {}); - return newQuotes + return newQuotes; } export async function fetchTokens() { - const tokenUrl = getBaseApi('tokens') + const tokenUrl = getBaseApi('tokens'); const tokens = await fetchWithCache( tokenUrl, { method: 'GET' }, { cacheRefreshTime: CACHE_REFRESH_ONE_HOUR }, - ) + ); const filteredTokens = tokens.filter((token) => { return ( validateData(TOKEN_VALIDATORS, token, tokenUrl) && token.address !== ETH_SWAPS_TOKEN_OBJECT.address - ) - }) - filteredTokens.push(ETH_SWAPS_TOKEN_OBJECT) - return filteredTokens + ); + }); + filteredTokens.push(ETH_SWAPS_TOKEN_OBJECT); + return filteredTokens; } export async function fetchAggregatorMetadata() { - const aggregatorMetadataUrl = getBaseApi('aggregatorMetadata') + const aggregatorMetadataUrl = getBaseApi('aggregatorMetadata'); const aggregators = await fetchWithCache( aggregatorMetadataUrl, { method: 'GET' }, { cacheRefreshTime: CACHE_REFRESH_ONE_HOUR }, - ) - const filteredAggregators = {} + ); + const filteredAggregators = {}; for (const aggKey in aggregators) { if ( validateData( @@ -301,26 +304,26 @@ export async function fetchAggregatorMetadata() { aggregatorMetadataUrl, ) ) { - filteredAggregators[aggKey] = aggregators[aggKey] + filteredAggregators[aggKey] = aggregators[aggKey]; } } - return filteredAggregators + return filteredAggregators; } export async function fetchTopAssets() { - const topAssetsUrl = getBaseApi('topAssets') + const topAssetsUrl = getBaseApi('topAssets'); const response = await fetchWithCache( topAssetsUrl, { method: 'GET' }, { cacheRefreshTime: CACHE_REFRESH_ONE_HOUR }, - ) + ); const topAssetsMap = response.reduce((_topAssetsMap, asset, index) => { if (validateData(TOP_ASSET_VALIDATORS, asset, topAssetsUrl)) { - return { ..._topAssetsMap, [asset.address]: { index: String(index) } } + return { ..._topAssetsMap, [asset.address]: { index: String(index) } }; } - return _topAssetsMap - }, {}) - return topAssetsMap + return _topAssetsMap; + }, {}); + return topAssetsMap; } export async function fetchSwapsFeatureLiveness() { @@ -328,8 +331,8 @@ export async function fetchSwapsFeatureLiveness() { getBaseApi('featureFlag'), { method: 'GET' }, { cacheRefreshTime: 600000 }, - ) - return status?.active + ); + return status?.active; } export async function fetchSwapsQuoteRefreshTime() { @@ -337,66 +340,66 @@ export async function fetchSwapsQuoteRefreshTime() { getBaseApi('refreshTime'), { method: 'GET' }, { cacheRefreshTime: 600000 }, - ) + ); // We presently use milliseconds in the UI if (typeof response?.seconds === 'number' && response.seconds > 0) { - return response.seconds * 1000 + return response.seconds * 1000; } throw new Error( `MetaMask - refreshTime provided invalid response: ${response}`, - ) + ); } export async function fetchTokenPrice(address) { - const query = `contract_addresses=${address}&vs_currencies=eth` + const query = `contract_addresses=${address}&vs_currencies=eth`; const prices = await fetchWithCache( `https://api.coingecko.com/api/v3/simple/token_price/ethereum?${query}`, { method: 'GET' }, { cacheRefreshTime: 60000 }, - ) - return prices && prices[address]?.eth + ); + return prices && prices[address]?.eth; } export async function fetchTokenBalance(address, userAddress) { - const tokenContract = global.eth.contract(abi).at(address) + const tokenContract = global.eth.contract(abi).at(address); const tokenBalancePromise = tokenContract ? tokenContract.balanceOf(userAddress) - : Promise.resolve() - const usersToken = await tokenBalancePromise - return usersToken + : Promise.resolve(); + const usersToken = await tokenBalancePromise; + return usersToken; } export async function fetchSwapsGasPrices() { - const gasPricesUrl = getBaseApi('gasPrices') + const gasPricesUrl = getBaseApi('gasPrices'); const response = await fetchWithCache( gasPricesUrl, { method: 'GET' }, { cacheRefreshTime: 15000 }, - ) + ); const responseIsValid = validateData( SWAP_GAS_PRICE_VALIDATOR, response, gasPricesUrl, - ) + ); if (!responseIsValid) { - throw new Error(`${gasPricesUrl} response is invalid`) + throw new Error(`${gasPricesUrl} response is invalid`); } const { SafeGasPrice: safeLow, ProposeGasPrice: average, FastGasPrice: fast, - } = response + } = response; return { safeLow, average, fast, - } + }; } export function getRenderableNetworkFeesForQuote( @@ -411,36 +414,36 @@ export function getRenderableNetworkFeesForQuote( ) { const totalGasLimitForCalculation = new BigNumber(tradeGas || '0x0', 16) .plus(approveGas || '0x0', 16) - .toString(16) - const gasTotalInWeiHex = calcGasTotal(totalGasLimitForCalculation, gasPrice) + .toString(16); + const gasTotalInWeiHex = calcGasTotal(totalGasLimitForCalculation, gasPrice); const nonGasFee = new BigNumber(tradeValue, 16) .minus(sourceSymbol === 'ETH' ? sourceAmount : 0, 10) - .toString(16) + .toString(16); const totalWeiCost = new BigNumber(gasTotalInWeiHex, 16) .plus(nonGasFee, 16) - .toString(16) + .toString(16); const ethFee = getValueFromWeiHex({ value: totalWeiCost, toDenomination: 'ETH', numberOfDecimals: 5, - }) + }); const rawNetworkFees = getValueFromWeiHex({ value: totalWeiCost, toCurrency: currentCurrency, conversionRate, numberOfDecimals: 2, - }) - const formattedNetworkFee = formatCurrency(rawNetworkFees, currentCurrency) + }); + const formattedNetworkFee = formatCurrency(rawNetworkFees, currentCurrency); return { rawNetworkFees, rawEthFee: ethFee, feeInFiat: formattedNetworkFee, feeInEth: `${ethFee} ETH`, nonGasFee, - } + }; } export function quotesToRenderableData( @@ -464,15 +467,15 @@ export function quotesToRenderableData( averageGas, fee, trade, - } = quote + } = quote; const sourceValue = calcTokenAmount( sourceAmount, sourceTokenInfo.decimals, - ).toString(10) + ).toString(10); const destinationValue = calcTokenAmount( destinationAmount, destinationTokenInfo.decimals, - ).toPrecision(8) + ).toPrecision(8); const { feeInFiat, @@ -488,15 +491,15 @@ export function quotesToRenderableData( trade.value, sourceTokenInfo.symbol, sourceAmount, - ) + ); - const slippageMultiplier = new BigNumber(100 - slippage).div(100) + const slippageMultiplier = new BigNumber(100 - slippage).div(100); const minimumAmountReceived = new BigNumber(destinationValue) .times(slippageMultiplier) - .toFixed(6) + .toFixed(6); const tokenConversionRate = - tokenConversionRates[destinationTokenInfo.address] + tokenConversionRates[destinationTokenInfo.address]; const ethValueOfTrade = destinationTokenInfo.symbol === 'ETH' ? calcTokenAmount( @@ -508,20 +511,20 @@ export function quotesToRenderableData( calcTokenAmount(destinationAmount, destinationTokenInfo.decimals), 10, ) - .minus(rawEthFee, 10) + .minus(rawEthFee, 10); - let liquiditySourceKey - let renderedSlippage = slippage + let liquiditySourceKey; + let renderedSlippage = slippage; if (aggType === 'AGG') { - liquiditySourceKey = 'swapAggregator' + liquiditySourceKey = 'swapAggregator'; } else if (aggType === 'RFQ') { - liquiditySourceKey = 'swapRequestForQuotation' - renderedSlippage = 0 + liquiditySourceKey = 'swapRequestForQuotation'; + renderedSlippage = 0; } else if (aggType === 'DEX') { - liquiditySourceKey = 'swapDecentralizedExchange' + liquiditySourceKey = 'swapDecentralizedExchange'; } else { - liquiditySourceKey = 'swapUnknown' + liquiditySourceKey = 'swapUnknown'; } return { @@ -546,8 +549,8 @@ export function quotesToRenderableData( ethValueOfTrade, minimumAmountReceived, metaMaskFee: fee, - } - }) + }; + }); } export function getSwapsTokensReceivedFromTxMeta( @@ -558,7 +561,7 @@ export function getSwapsTokensReceivedFromTxMeta( tokenDecimals, approvalTxMeta, ) { - const txReceipt = txMeta?.txReceipt + const txReceipt = txMeta?.txReceipt; if (tokenSymbol === 'ETH') { if ( !txReceipt || @@ -566,21 +569,21 @@ export function getSwapsTokensReceivedFromTxMeta( !txMeta.postTxBalance || !txMeta.preTxBalance ) { - return null + return null; } - let approvalTxGasCost = '0x0' + let approvalTxGasCost = '0x0'; if (approvalTxMeta && approvalTxMeta.txReceipt) { approvalTxGasCost = calcGasTotal( approvalTxMeta.txReceipt.gasUsed, approvalTxMeta.txParams.gasPrice, - ) + ); } - const gasCost = calcGasTotal(txReceipt.gasUsed, txMeta.txParams.gasPrice) + const gasCost = calcGasTotal(txReceipt.gasUsed, txMeta.txParams.gasPrice); const totalGasCost = new BigNumber(gasCost, 16) .plus(approvalTxGasCost, 16) - .toString(16) + .toString(16); const preTxBalanceLessGasCost = subtractCurrencies( txMeta.preTxBalance, @@ -590,7 +593,7 @@ export function getSwapsTokensReceivedFromTxMeta( bBase: 16, toNumericBase: 'hex', }, - ) + ); const ethReceived = subtractCurrencies( txMeta.postTxBalance, @@ -603,40 +606,40 @@ export function getSwapsTokensReceivedFromTxMeta( toNumericBase: 'dec', numberOfDecimals: 6, }, - ) - return ethReceived + ); + return ethReceived; } - const txReceiptLogs = txReceipt?.logs + const txReceiptLogs = txReceipt?.logs; if (txReceiptLogs && txReceipt?.status !== '0x0') { const tokenTransferLog = txReceiptLogs.find((txReceiptLog) => { const isTokenTransfer = txReceiptLog.topics && - txReceiptLog.topics[0] === TOKEN_TRANSFER_LOG_TOPIC_HASH - const isTransferFromGivenToken = txReceiptLog.address === tokenAddress + txReceiptLog.topics[0] === TOKEN_TRANSFER_LOG_TOPIC_HASH; + const isTransferFromGivenToken = txReceiptLog.address === tokenAddress; const isTransferFromGivenAddress = txReceiptLog.topics && txReceiptLog.topics[2] && - txReceiptLog.topics[2].match(accountAddress.slice(2)) + txReceiptLog.topics[2].match(accountAddress.slice(2)); return ( isTokenTransfer && isTransferFromGivenToken && isTransferFromGivenAddress - ) - }) + ); + }); return tokenTransferLog ? toPrecisionWithoutTrailingZeros( calcTokenAmount(tokenTransferLog.data, tokenDecimals).toString(10), 6, ) - : '' + : ''; } - return null + return null; } export function formatSwapsValueForDisplay(destinationAmount) { - let amountToDisplay = toPrecisionWithoutTrailingZeros(destinationAmount, 12) + let amountToDisplay = toPrecisionWithoutTrailingZeros(destinationAmount, 12); if (amountToDisplay.match(/e[+-]/u)) { - amountToDisplay = new BigNumber(amountToDisplay).toFixed() + amountToDisplay = new BigNumber(amountToDisplay).toFixed(); } - return amountToDisplay + return amountToDisplay; } diff --git a/ui/app/pages/swaps/swaps.util.test.js b/ui/app/pages/swaps/swaps.util.test.js index 77bab1905..f3ee2a497 100644 --- a/ui/app/pages/swaps/swaps.util.test.js +++ b/ui/app/pages/swaps/swaps.util.test.js @@ -1,5 +1,5 @@ -import { strict as assert } from 'assert' -import proxyquire from 'proxyquire' +import { strict as assert } from 'assert'; +import proxyquire from 'proxyquire'; import { TRADES_BASE_PROD_URL, TOKENS_BASE_PROD_URL, @@ -9,41 +9,41 @@ import { MOCK_TRADE_RESPONSE_2, AGGREGATOR_METADATA, TOP_ASSETS, -} from './swaps-util-test-constants' +} from './swaps-util-test-constants'; const swapsUtils = proxyquire('./swaps.util.js', { '../../helpers/utils/fetch-with-cache': { default: (url, fetchObject) => { - assert.strictEqual(fetchObject.method, 'GET') + assert.strictEqual(fetchObject.method, 'GET'); if (url.match(TRADES_BASE_PROD_URL)) { assert.strictEqual( url, 'https://api.metaswap.codefi.network/trades?destinationToken=0xE41d2489571d322189246DaFA5ebDe1F4699F498&sourceToken=0x617b3f8050a0BD94b6b1da02B4384eE5B4DF13F4&sourceAmount=2000000000000000000000000000000000000&slippage=3&timeout=10000&walletAddress=0xmockAddress', - ) - return Promise.resolve(MOCK_TRADE_RESPONSE_2) + ); + return Promise.resolve(MOCK_TRADE_RESPONSE_2); } if (url.match(TOKENS_BASE_PROD_URL)) { - assert.strictEqual(url, TOKENS_BASE_PROD_URL) - return Promise.resolve(TOKENS) + assert.strictEqual(url, TOKENS_BASE_PROD_URL); + return Promise.resolve(TOKENS); } if (url.match(AGGREGATOR_METADATA_BASE_PROD_URL)) { - assert.strictEqual(url, AGGREGATOR_METADATA_BASE_PROD_URL) - return Promise.resolve(AGGREGATOR_METADATA) + assert.strictEqual(url, AGGREGATOR_METADATA_BASE_PROD_URL); + return Promise.resolve(AGGREGATOR_METADATA); } if (url.match(TOP_ASSET_BASE_PROD_URL)) { - assert.strictEqual(url, TOP_ASSET_BASE_PROD_URL) - return Promise.resolve(TOP_ASSETS) + assert.strictEqual(url, TOP_ASSET_BASE_PROD_URL); + return Promise.resolve(TOP_ASSETS); } - return Promise.resolve() + return Promise.resolve(); }, }, -}) +}); const { fetchTradesInfo, fetchTokens, fetchAggregatorMetadata, fetchTopAssets, -} = swapsUtils +} = swapsUtils; describe('Swaps Util', function () { describe('fetchTradesInfo', function () { @@ -80,13 +80,13 @@ describe('Swaps Util', function () { averageGas: 1, slippage: '3', }, - } + }; const expectedResult2 = { zeroEx: { ...expectedResult1.zeroEx, sourceAmount: '20000000000000000', }, - } + }; it('should fetch trade info on prod', async function () { const result = await fetchTradesInfo({ TOKENS, @@ -99,34 +99,34 @@ describe('Swaps Util', function () { sourceDecimals: TOKENS[0].decimals, sourceTokenInfo: { ...TOKENS[0] }, destinationTokenInfo: { ...TOKENS[1] }, - }) - assert.deepStrictEqual(result, expectedResult2) - }) - }) + }); + assert.deepStrictEqual(result, expectedResult2); + }); + }); describe('fetchTokens', function () { it('should fetch tokens', async function () { - const result = await fetchTokens(true) - assert.deepStrictEqual(result, TOKENS) - }) + const result = await fetchTokens(true); + assert.deepStrictEqual(result, TOKENS); + }); it('should fetch tokens on prod', async function () { - const result = await fetchTokens(false) - assert.deepStrictEqual(result, TOKENS) - }) - }) + const result = await fetchTokens(false); + assert.deepStrictEqual(result, TOKENS); + }); + }); describe('fetchAggregatorMetadata', function () { it('should fetch aggregator metadata', async function () { - const result = await fetchAggregatorMetadata(true) - assert.deepStrictEqual(result, AGGREGATOR_METADATA) - }) + const result = await fetchAggregatorMetadata(true); + assert.deepStrictEqual(result, AGGREGATOR_METADATA); + }); it('should fetch aggregator metadata on prod', async function () { - const result = await fetchAggregatorMetadata(false) - assert.deepStrictEqual(result, AGGREGATOR_METADATA) - }) - }) + const result = await fetchAggregatorMetadata(false); + assert.deepStrictEqual(result, AGGREGATOR_METADATA); + }); + }); describe('fetchTopAssets', function () { const expectedResult = { @@ -145,15 +145,15 @@ describe('Swaps Util', function () { '0xc011a73ee8576fb46f5e1c5751ca3b9fe0af2a6f': { index: '4', }, - } + }; it('should fetch top assets', async function () { - const result = await fetchTopAssets(true) - assert.deepStrictEqual(result, expectedResult) - }) + const result = await fetchTopAssets(true); + assert.deepStrictEqual(result, expectedResult); + }); it('should fetch top assets on prod', async function () { - const result = await fetchTopAssets(false) - assert.deepStrictEqual(result, expectedResult) - }) - }) -}) + const result = await fetchTopAssets(false); + assert.deepStrictEqual(result, expectedResult); + }); + }); +}); diff --git a/ui/app/pages/swaps/view-quote/index.js b/ui/app/pages/swaps/view-quote/index.js index 7e6d2fc6c..4a412aa90 100644 --- a/ui/app/pages/swaps/view-quote/index.js +++ b/ui/app/pages/swaps/view-quote/index.js @@ -1 +1 @@ -export { default } from './view-quote' +export { default } from './view-quote'; diff --git a/ui/app/pages/swaps/view-quote/tests/view-quote-price-difference.test.js b/ui/app/pages/swaps/view-quote/tests/view-quote-price-difference.test.js index 1fc66284b..ae41cd794 100644 --- a/ui/app/pages/swaps/view-quote/tests/view-quote-price-difference.test.js +++ b/ui/app/pages/swaps/view-quote/tests/view-quote-price-difference.test.js @@ -1,13 +1,13 @@ -import assert from 'assert' -import React from 'react' -import { shallow } from 'enzyme' -import { Provider } from 'react-redux' -import configureMockStore from 'redux-mock-store' -import { NETWORK_TYPE_RPC } from '../../../../../../shared/constants/network' -import ViewQuotePriceDifference from '../view-quote-price-difference' +import assert from 'assert'; +import React from 'react'; +import { shallow } from 'enzyme'; +import { Provider } from 'react-redux'; +import configureMockStore from 'redux-mock-store'; +import { NETWORK_TYPE_RPC } from '../../../../../../shared/constants/network'; +import ViewQuotePriceDifference from '../view-quote-price-difference'; describe('View Price Quote Difference', function () { - const t = (key) => `translate ${key}` + const t = (key) => `translate ${key}`; const state = { metamask: { @@ -17,9 +17,9 @@ describe('View Price Quote Difference', function () { currentCurrency: 'usd', conversionRate: 600.0, }, - } + }; - const store = configureMockStore()(state) + const store = configureMockStore()(state); // Sample transaction is 1 $ETH to ~42.880915 $LINK const DEFAULT_PROPS = { @@ -84,9 +84,9 @@ describe('View Price Quote Difference', function () { }, sourceTokenValue: '1', destinationTokenValue: '42.947749', - } + }; - let component + let component; function renderComponent(props) { component = shallow( @@ -95,56 +95,56 @@ describe('View Price Quote Difference', function () { { context: { t }, }, - ) + ); } afterEach(function () { - component.unmount() - }) + component.unmount(); + }); it('does not render when there is no quote', function () { - const props = { ...DEFAULT_PROPS, usedQuote: null } - renderComponent(props) + const props = { ...DEFAULT_PROPS, usedQuote: null }; + renderComponent(props); const wrappingDiv = component.find( '.view-quote__price-difference-warning-wrapper', - ) - assert.strictEqual(wrappingDiv.length, 0) - }) + ); + assert.strictEqual(wrappingDiv.length, 0); + }); it('does not render when the item is in the low bucket', function () { - const props = { ...DEFAULT_PROPS } - props.usedQuote.priceSlippage.bucket = 'low' + const props = { ...DEFAULT_PROPS }; + props.usedQuote.priceSlippage.bucket = 'low'; - renderComponent(props) + renderComponent(props); const wrappingDiv = component.find( '.view-quote__price-difference-warning-wrapper', - ) - assert.strictEqual(wrappingDiv.length, 0) - }) + ); + assert.strictEqual(wrappingDiv.length, 0); + }); it('displays an error when in medium bucket', function () { - const props = { ...DEFAULT_PROPS } - props.usedQuote.priceSlippage.bucket = 'medium' + const props = { ...DEFAULT_PROPS }; + props.usedQuote.priceSlippage.bucket = 'medium'; - renderComponent(props) - assert.strictEqual(component.html().includes('medium'), true) - }) + renderComponent(props); + assert.strictEqual(component.html().includes('medium'), true); + }); it('displays an error when in high bucket', function () { - const props = { ...DEFAULT_PROPS } - props.usedQuote.priceSlippage.bucket = 'high' + const props = { ...DEFAULT_PROPS }; + props.usedQuote.priceSlippage.bucket = 'high'; - renderComponent(props) - assert.strictEqual(component.html().includes('high'), true) - }) + renderComponent(props); + assert.strictEqual(component.html().includes('high'), true); + }); it('displays a fiat error when calculationError is present', function () { - const props = { ...DEFAULT_PROPS, priceSlippageUnknownFiatValue: true } + const props = { ...DEFAULT_PROPS, priceSlippageUnknownFiatValue: true }; props.usedQuote.priceSlippage.calculationError = - 'Could not determine price.' + 'Could not determine price.'; - renderComponent(props) - assert.strictEqual(component.html().includes('fiat-error'), true) - }) -}) + renderComponent(props); + assert.strictEqual(component.html().includes('fiat-error'), true); + }); +}); diff --git a/ui/app/pages/swaps/view-quote/view-quote-price-difference.js b/ui/app/pages/swaps/view-quote/view-quote-price-difference.js index bf229b8da..b7589a567 100644 --- a/ui/app/pages/swaps/view-quote/view-quote-price-difference.js +++ b/ui/app/pages/swaps/view-quote/view-quote-price-difference.js @@ -1,11 +1,11 @@ -import React, { useContext } from 'react' +import React, { useContext } from 'react'; -import PropTypes from 'prop-types' -import classnames from 'classnames' -import { I18nContext } from '../../../contexts/i18n' +import PropTypes from 'prop-types'; +import classnames from 'classnames'; +import { I18nContext } from '../../../contexts/i18n'; -import ActionableMessage from '../actionable-message' -import Tooltip from '../../../components/ui/tooltip' +import ActionableMessage from '../actionable-message'; +import Tooltip from '../../../components/ui/tooltip'; export default function ViewQuotePriceDifference(props) { const { @@ -18,25 +18,25 @@ export default function ViewQuotePriceDifference(props) { priceSlippageFromDestination, priceDifferencePercentage, priceSlippageUnknownFiatValue, - } = props + } = props; - const t = useContext(I18nContext) + const t = useContext(I18nContext); - let priceDifferenceTitle = '' - let priceDifferenceMessage = '' - let priceDifferenceClass = '' - let priceDifferenceAcknowledgementText = '' + let priceDifferenceTitle = ''; + let priceDifferenceMessage = ''; + let priceDifferenceClass = ''; + let priceDifferenceAcknowledgementText = ''; if (priceSlippageUnknownFiatValue) { // A calculation error signals we cannot determine dollar value - priceDifferenceMessage = t('swapPriceDifferenceUnavailable') - priceDifferenceClass = 'fiat-error' + priceDifferenceMessage = t('swapPriceDifferenceUnavailable'); + priceDifferenceClass = 'fiat-error'; priceDifferenceAcknowledgementText = t( 'swapPriceDifferenceAcknowledgementNoFiat', - ) + ); } else { priceDifferenceTitle = t('swapPriceDifferenceTitle', [ priceDifferencePercentage, - ]) + ]); priceDifferenceMessage = t('swapPriceDifference', [ sourceTokenValue, // Number of source token to swap usedQuote.sourceTokenInfo.symbol, // Source token symbol @@ -44,9 +44,11 @@ export default function ViewQuotePriceDifference(props) { destinationTokenValue, // Number of destination tokens in return usedQuote.destinationTokenInfo.symbol, // Destination token symbol, priceSlippageFromDestination, // Destination tokens total value - ]) - priceDifferenceClass = usedQuote.priceSlippage.bucket - priceDifferenceAcknowledgementText = t('swapPriceDifferenceAcknowledgement') + ]); + priceDifferenceClass = usedQuote.priceSlippage.bucket; + priceDifferenceAcknowledgementText = t( + 'swapPriceDifferenceAcknowledgement', + ); } return ( @@ -70,7 +72,7 @@ export default function ViewQuotePriceDifference(props) {
    - ) + ); } ViewQuotePriceDifference.propTypes = { @@ -102,4 +104,4 @@ ViewQuotePriceDifference.propTypes = { priceSlippageFromDestination: PropTypes.string, priceDifferencePercentage: PropTypes.number, priceSlippageUnknownFiatValue: PropTypes.bool, -} +}; diff --git a/ui/app/pages/swaps/view-quote/view-quote.js b/ui/app/pages/swaps/view-quote/view-quote.js index 466fb8377..2c5c43865 100644 --- a/ui/app/pages/swaps/view-quote/view-quote.js +++ b/ui/app/pages/swaps/view-quote/view-quote.js @@ -1,17 +1,17 @@ -import React, { useState, useContext, useMemo, useEffect, useRef } from 'react' -import { useSelector, useDispatch } from 'react-redux' -import { useHistory } from 'react-router-dom' -import BigNumber from 'bignumber.js' -import { isEqual } from 'lodash' -import classnames from 'classnames' -import { I18nContext } from '../../../contexts/i18n' -import SelectQuotePopover from '../select-quote-popover' -import { useEthFiatAmount } from '../../../hooks/useEthFiatAmount' -import { useEqualityCheck } from '../../../hooks/useEqualityCheck' -import { useNewMetricEvent } from '../../../hooks/useMetricEvent' -import { useSwapsEthToken } from '../../../hooks/useSwapsEthToken' -import { MetaMetricsContext } from '../../../contexts/metametrics.new' -import FeeCard from '../fee-card' +import React, { useState, useContext, useMemo, useEffect, useRef } from 'react'; +import { useSelector, useDispatch } from 'react-redux'; +import { useHistory } from 'react-router-dom'; +import BigNumber from 'bignumber.js'; +import { isEqual } from 'lodash'; +import classnames from 'classnames'; +import { I18nContext } from '../../../contexts/i18n'; +import SelectQuotePopover from '../select-quote-popover'; +import { useEthFiatAmount } from '../../../hooks/useEthFiatAmount'; +import { useEqualityCheck } from '../../../hooks/useEqualityCheck'; +import { useNewMetricEvent } from '../../../hooks/useMetricEvent'; +import { useSwapsEthToken } from '../../../hooks/useSwapsEthToken'; +import { MetaMetricsContext } from '../../../contexts/metametrics.new'; +import FeeCard from '../fee-card'; import { FALLBACK_GAS_MULTIPLIER, getQuotes, @@ -30,146 +30,146 @@ import { getBackgroundSwapRouteState, swapsQuoteSelected, getSwapsQuoteRefreshTime, -} from '../../../ducks/swaps/swaps' +} from '../../../ducks/swaps/swaps'; import { conversionRateSelector, getSelectedAccount, getCurrentCurrency, getTokenExchangeRates, -} from '../../../selectors' -import { toPrecisionWithoutTrailingZeros } from '../../../helpers/utils/util' -import { getTokens } from '../../../ducks/metamask/metamask' +} from '../../../selectors'; +import { toPrecisionWithoutTrailingZeros } from '../../../helpers/utils/util'; +import { getTokens } from '../../../ducks/metamask/metamask'; import { safeRefetchQuotes, setCustomApproveTxData, setSwapsErrorKey, showModal, -} from '../../../store/actions' +} from '../../../store/actions'; import { ASSET_ROUTE, BUILD_QUOTE_ROUTE, DEFAULT_ROUTE, SWAPS_ERROR_ROUTE, AWAITING_SWAP_ROUTE, -} from '../../../helpers/constants/routes' -import { getTokenData } from '../../../helpers/utils/transactions.util' +} from '../../../helpers/constants/routes'; +import { getTokenData } from '../../../helpers/utils/transactions.util'; import { calcTokenAmount, calcTokenValue, getTokenValueParam, -} from '../../../helpers/utils/token-util' +} from '../../../helpers/utils/token-util'; import { decimalToHex, hexToDecimal, getValueFromWeiHex, -} from '../../../helpers/utils/conversions.util' -import MainQuoteSummary from '../main-quote-summary' -import { calcGasTotal } from '../../send/send.utils' -import { getCustomTxParamsData } from '../../confirm-approve/confirm-approve.util' -import ActionableMessage from '../actionable-message' +} from '../../../helpers/utils/conversions.util'; +import MainQuoteSummary from '../main-quote-summary'; +import { calcGasTotal } from '../../send/send.utils'; +import { getCustomTxParamsData } from '../../confirm-approve/confirm-approve.util'; +import ActionableMessage from '../actionable-message'; import { quotesToRenderableData, getRenderableNetworkFeesForQuote, -} from '../swaps.util' -import { useTokenTracker } from '../../../hooks/useTokenTracker' -import { QUOTES_EXPIRED_ERROR } from '../../../helpers/constants/swaps' -import CountdownTimer from '../countdown-timer' -import SwapsFooter from '../swaps-footer' -import ViewQuotePriceDifference from './view-quote-price-difference' +} from '../swaps.util'; +import { useTokenTracker } from '../../../hooks/useTokenTracker'; +import { QUOTES_EXPIRED_ERROR } from '../../../helpers/constants/swaps'; +import CountdownTimer from '../countdown-timer'; +import SwapsFooter from '../swaps-footer'; +import ViewQuotePriceDifference from './view-quote-price-difference'; export default function ViewQuote() { - const history = useHistory() - const dispatch = useDispatch() - const t = useContext(I18nContext) - const metaMetricsEvent = useContext(MetaMetricsContext) + const history = useHistory(); + const dispatch = useDispatch(); + const t = useContext(I18nContext); + const metaMetricsEvent = useContext(MetaMetricsContext); - const [dispatchedSafeRefetch, setDispatchedSafeRefetch] = useState(false) - const [submitClicked, setSubmitClicked] = useState(false) - const [selectQuotePopoverShown, setSelectQuotePopoverShown] = useState(false) - const [warningHidden, setWarningHidden] = useState(false) - const [originalApproveAmount, setOriginalApproveAmount] = useState(null) + const [dispatchedSafeRefetch, setDispatchedSafeRefetch] = useState(false); + const [submitClicked, setSubmitClicked] = useState(false); + const [selectQuotePopoverShown, setSelectQuotePopoverShown] = useState(false); + const [warningHidden, setWarningHidden] = useState(false); + const [originalApproveAmount, setOriginalApproveAmount] = useState(null); const [ acknowledgedPriceDifference, setAcknowledgedPriceDifference, - ] = useState(false) + ] = useState(false); - const routeState = useSelector(getBackgroundSwapRouteState) - const quotes = useSelector(getQuotes, isEqual) + const routeState = useSelector(getBackgroundSwapRouteState); + const quotes = useSelector(getQuotes, isEqual); useEffect(() => { if (!Object.values(quotes).length) { - history.push(BUILD_QUOTE_ROUTE) + history.push(BUILD_QUOTE_ROUTE); } else if (routeState === 'awaiting') { - history.push(AWAITING_SWAP_ROUTE) + history.push(AWAITING_SWAP_ROUTE); } - }, [history, quotes, routeState]) + }, [history, quotes, routeState]); - const quotesLastFetched = useSelector(getQuotesLastFetched) + const quotesLastFetched = useSelector(getQuotesLastFetched); // Select necessary data - const gasPrice = useSelector(getUsedSwapsGasPrice) - const customMaxGas = useSelector(getCustomSwapsGas) - const tokenConversionRates = useSelector(getTokenExchangeRates) - const memoizedTokenConversionRates = useEqualityCheck(tokenConversionRates) - const { balance: ethBalance } = useSelector(getSelectedAccount) - const conversionRate = useSelector(conversionRateSelector) - const currentCurrency = useSelector(getCurrentCurrency) - const swapsTokens = useSelector(getTokens) - const balanceError = useSelector(getBalanceError) - const fetchParams = useSelector(getFetchParams) - const approveTxParams = useSelector(getApproveTxParams) - const selectedQuote = useSelector(getSelectedQuote) - const topQuote = useSelector(getTopQuote) - const usedQuote = selectedQuote || topQuote - const tradeValue = usedQuote?.trade?.value ?? '0x0' - const swapsQuoteRefreshTime = useSelector(getSwapsQuoteRefreshTime) + const gasPrice = useSelector(getUsedSwapsGasPrice); + const customMaxGas = useSelector(getCustomSwapsGas); + const tokenConversionRates = useSelector(getTokenExchangeRates); + const memoizedTokenConversionRates = useEqualityCheck(tokenConversionRates); + const { balance: ethBalance } = useSelector(getSelectedAccount); + const conversionRate = useSelector(conversionRateSelector); + const currentCurrency = useSelector(getCurrentCurrency); + const swapsTokens = useSelector(getTokens); + const balanceError = useSelector(getBalanceError); + const fetchParams = useSelector(getFetchParams); + const approveTxParams = useSelector(getApproveTxParams); + const selectedQuote = useSelector(getSelectedQuote); + const topQuote = useSelector(getTopQuote); + const usedQuote = selectedQuote || topQuote; + const tradeValue = usedQuote?.trade?.value ?? '0x0'; + const swapsQuoteRefreshTime = useSelector(getSwapsQuoteRefreshTime); - const { isBestQuote } = usedQuote + const { isBestQuote } = usedQuote; - const fetchParamsSourceToken = fetchParams?.sourceToken + const fetchParamsSourceToken = fetchParams?.sourceToken; const usedGasLimit = usedQuote?.gasEstimateWithRefund || - `0x${decimalToHex(usedQuote?.averageGas || 0)}` + `0x${decimalToHex(usedQuote?.averageGas || 0)}`; - const gasLimitForMax = usedQuote?.gasEstimate || `0x0` + const gasLimitForMax = usedQuote?.gasEstimate || `0x0`; const usedGasLimitWithMultiplier = new BigNumber(gasLimitForMax, 16) .times(usedQuote?.gasMultiplier || FALLBACK_GAS_MULTIPLIER, 10) .round(0) - .toString(16) + .toString(16); const nonCustomMaxGasLimit = usedQuote?.gasEstimate ? usedGasLimitWithMultiplier - : `0x${decimalToHex(usedQuote?.maxGas || 0)}` - const maxGasLimit = customMaxGas || nonCustomMaxGasLimit + : `0x${decimalToHex(usedQuote?.maxGas || 0)}`; + const maxGasLimit = customMaxGas || nonCustomMaxGasLimit; - const gasTotalInWeiHex = calcGasTotal(maxGasLimit, gasPrice) + const gasTotalInWeiHex = calcGasTotal(maxGasLimit, gasPrice); - const { tokensWithBalances } = useTokenTracker(swapsTokens) - const swapsEthToken = useSwapsEthToken() + const { tokensWithBalances } = useTokenTracker(swapsTokens); + const swapsEthToken = useSwapsEthToken(); const balanceToken = fetchParamsSourceToken === swapsEthToken.address ? swapsEthToken : tokensWithBalances.find( ({ address }) => address === fetchParamsSourceToken, - ) + ); - const selectedFromToken = balanceToken || usedQuote.sourceTokenInfo + const selectedFromToken = balanceToken || usedQuote.sourceTokenInfo; const tokenBalance = tokensWithBalances?.length && calcTokenAmount( selectedFromToken.balance || '0x0', selectedFromToken.decimals, - ).toFixed(9) + ).toFixed(9); - const approveData = getTokenData(approveTxParams?.data) - const approveValue = approveData && getTokenValueParam(approveData) + const approveData = getTokenData(approveTxParams?.data); + const approveValue = approveData && getTokenValueParam(approveData); const approveAmount = approveValue && selectedFromToken?.decimals !== undefined && - calcTokenAmount(approveValue, selectedFromToken.decimals).toFixed(9) - const approveGas = approveTxParams?.gas + calcTokenAmount(approveValue, selectedFromToken.decimals).toFixed(9); + const approveGas = approveTxParams?.gas; const renderablePopoverData = useMemo(() => { return quotesToRenderableData( @@ -179,7 +179,7 @@ export default function ViewQuote() { currentCurrency, approveGas, memoizedTokenConversionRates, - ) + ); }, [ quotes, gasPrice, @@ -187,12 +187,12 @@ export default function ViewQuote() { currentCurrency, approveGas, memoizedTokenConversionRates, - ]) + ]); const renderableDataForUsedQuote = renderablePopoverData.find( (renderablePopoverDatum) => renderablePopoverDatum.aggId === usedQuote.aggregator, - ) + ); const { destinationTokenDecimals, @@ -203,7 +203,7 @@ export default function ViewQuote() { sourceTokenSymbol, sourceTokenValue, sourceTokenIconUrl, - } = renderableDataForUsedQuote + } = renderableDataForUsedQuote; const { feeInFiat, feeInEth } = getRenderableNetworkFeesForQuote( usedGasLimit, @@ -214,7 +214,7 @@ export default function ViewQuote() { tradeValue, sourceTokenSymbol, usedQuote.sourceAmount, - ) + ); const { feeInFiat: maxFeeInFiat, @@ -229,18 +229,18 @@ export default function ViewQuote() { tradeValue, sourceTokenSymbol, usedQuote.sourceAmount, - ) + ); - const tokenCost = new BigNumber(usedQuote.sourceAmount) + const tokenCost = new BigNumber(usedQuote.sourceAmount); const ethCost = new BigNumber(usedQuote.trade.value || 0, 10).plus( new BigNumber(gasTotalInWeiHex, 16), - ) + ); const insufficientTokens = (tokensWithBalances?.length || balanceError) && - tokenCost.gt(new BigNumber(selectedFromToken.balance || '0x0')) + tokenCost.gt(new BigNumber(selectedFromToken.balance || '0x0')); - const insufficientEth = ethCost.gt(new BigNumber(ethBalance || '0x0')) + const insufficientEth = ethCost.gt(new BigNumber(ethBalance || '0x0')); const tokenBalanceNeeded = insufficientTokens ? toPrecisionWithoutTrailingZeros( @@ -249,7 +249,7 @@ export default function ViewQuote() { .toString(10), 6, ) - : null + : null; const ethBalanceNeeded = insufficientEth ? toPrecisionWithoutTrailingZeros( @@ -259,30 +259,30 @@ export default function ViewQuote() { .toString(10), 6, ) - : null + : null; - const destinationToken = useSelector(getDestinationTokenInfo) + const destinationToken = useSelector(getDestinationTokenInfo); useEffect(() => { if (insufficientTokens || insufficientEth) { - dispatch(setBalanceError(true)) + dispatch(setBalanceError(true)); } else if (balanceError && !insufficientTokens && !insufficientEth) { - dispatch(setBalanceError(false)) + dispatch(setBalanceError(false)); } - }, [insufficientTokens, insufficientEth, balanceError, dispatch]) + }, [insufficientTokens, insufficientEth, balanceError, dispatch]); useEffect(() => { - const currentTime = Date.now() - const timeSinceLastFetched = currentTime - quotesLastFetched + const currentTime = Date.now(); + const timeSinceLastFetched = currentTime - quotesLastFetched; if ( timeSinceLastFetched > swapsQuoteRefreshTime && !dispatchedSafeRefetch ) { - setDispatchedSafeRefetch(true) - dispatch(safeRefetchQuotes()) + setDispatchedSafeRefetch(true); + dispatch(safeRefetchQuotes()); } else if (timeSinceLastFetched > swapsQuoteRefreshTime) { - dispatch(setSwapsErrorKey(QUOTES_EXPIRED_ERROR)) - history.push(SWAPS_ERROR_ROUTE) + dispatch(setSwapsErrorKey(QUOTES_EXPIRED_ERROR)); + history.push(SWAPS_ERROR_ROUTE); } }, [ quotesLastFetched, @@ -290,19 +290,19 @@ export default function ViewQuote() { dispatch, history, swapsQuoteRefreshTime, - ]) + ]); useEffect(() => { if (!originalApproveAmount && approveAmount) { - setOriginalApproveAmount(approveAmount) + setOriginalApproveAmount(approveAmount); } - }, [originalApproveAmount, approveAmount]) + }, [originalApproveAmount, approveAmount]); const showInsufficientWarning = - (balanceError || tokenBalanceNeeded || ethBalanceNeeded) && !warningHidden + (balanceError || tokenBalanceNeeded || ethBalanceNeeded) && !warningHidden; - const numberOfQuotes = Object.values(quotes).length - const bestQuoteReviewedEventSent = useRef() + const numberOfQuotes = Object.values(quotes).length; + const bestQuoteReviewedEventSent = useRef(); const eventObjectBase = { token_from: sourceTokenSymbol, token_from_amount: sourceTokenValue, @@ -314,7 +314,7 @@ export default function ViewQuote() { response_time: fetchParams?.responseTime, best_quote_source: topQuote?.aggregator, available_quotes: numberOfQuotes, - } + }; const allAvailableQuotesOpened = useNewMetricEvent({ event: 'All Available Quotes Opened', @@ -327,7 +327,7 @@ export default function ViewQuote() { ? null : usedQuote?.aggregator, }, - }) + }); const quoteDetailsOpened = useNewMetricEvent({ event: 'Quote Details Opened', category: 'swaps', @@ -339,7 +339,7 @@ export default function ViewQuote() { ? null : usedQuote?.aggregator, }, - }) + }); const editSpendLimitOpened = useNewMetricEvent({ event: 'Edit Spend Limit Opened', category: 'swaps', @@ -349,13 +349,13 @@ export default function ViewQuote() { custom_spend_limit_amount: originalApproveAmount === approveAmount ? null : approveAmount, }, - }) + }); const bestQuoteReviewedEvent = useNewMetricEvent({ event: 'Best Quote Reviewed', category: 'swaps', sensitiveProperties: { ...eventObjectBase, network_fees: feeInFiat }, - }) + }); useEffect(() => { if ( !bestQuoteReviewedEventSent.current && @@ -370,8 +370,8 @@ export default function ViewQuote() { feeInFiat, ].every((dep) => dep !== null && dep !== undefined) ) { - bestQuoteReviewedEventSent.current = true - bestQuoteReviewedEvent() + bestQuoteReviewedEventSent.current = true; + bestQuoteReviewedEvent(); } }, [ sourceTokenSymbol, @@ -383,12 +383,12 @@ export default function ViewQuote() { numberOfQuotes, feeInFiat, bestQuoteReviewedEvent, - ]) + ]); - const metaMaskFee = usedQuote.fee + const metaMaskFee = usedQuote.fee; const onFeeCardTokenApprovalClick = () => { - editSpendLimitOpened() + editSpendLimitOpened(); dispatch( showModal({ name: 'EDIT_APPROVAL_PERMISSION', @@ -398,17 +398,17 @@ export default function ViewQuote() { const customPermissionAmount = newCustomPermissionAmount === '' ? originalApproveAmount - : newCustomPermissionAmount + : newCustomPermissionAmount; const newData = getCustomTxParamsData(approveTxParams.data, { customPermissionAmount, decimals: selectedFromToken.decimals, - }) + }); if ( customPermissionAmount?.length && approveTxParams.data !== newData ) { - dispatch(setCustomApproveTxData(newData)) + dispatch(setCustomApproveTxData(newData)); } }, tokenAmount: originalApproveAmount, @@ -421,27 +421,27 @@ export default function ViewQuote() { selectedFromToken.decimals, ), }), - ) - } + ); + }; - const nonGasFeeIsPositive = new BigNumber(nonGasFee, 16).gt(0) - const approveGasTotal = calcGasTotal(approveGas || '0x0', gasPrice) + const nonGasFeeIsPositive = new BigNumber(nonGasFee, 16).gt(0); + const approveGasTotal = calcGasTotal(approveGas || '0x0', gasPrice); const extraNetworkFeeTotalInHexWEI = new BigNumber(nonGasFee, 16) .plus(approveGasTotal, 16) - .toString(16) + .toString(16); const extraNetworkFeeTotalInEth = getValueFromWeiHex({ value: extraNetworkFeeTotalInHexWEI, toDenomination: 'ETH', numberOfDecimals: 4, - }) + }); - let extraInfoRowLabel = '' + let extraInfoRowLabel = ''; if (approveGas && nonGasFeeIsPositive) { - extraInfoRowLabel = t('approvalAndAggregatorTxFeeCost') + extraInfoRowLabel = t('approvalAndAggregatorTxFeeCost'); } else if (approveGas) { - extraInfoRowLabel = t('approvalTxGasCost') + extraInfoRowLabel = t('approvalTxGasCost'); } else if (nonGasFeeIsPositive) { - extraInfoRowLabel = t('aggregatorFeeCost') + extraInfoRowLabel = t('aggregatorFeeCost'); } const onFeeCardMaxRowClick = () => @@ -463,13 +463,13 @@ export default function ViewQuote() { initialGasLimit: maxGasLimit, minimumGasLimit: new BigNumber(nonCustomMaxGasLimit, 16).toNumber(), }), - ) + ); const tokenApprovalTextComponent = ( {sourceTokenSymbol} - ) + ); const actionableInsufficientMessage = t('swapApproveNeedMoreTokens', [ @@ -478,25 +478,25 @@ export default function ViewQuote() { tokenBalanceNeeded && !(sourceTokenSymbol === 'ETH') ? sourceTokenSymbol : 'ETH', - ]) + ]); // Price difference warning - let viewQuotePriceDifferenceComponent = null + let viewQuotePriceDifferenceComponent = null; const priceSlippageFromSource = useEthFiatAmount( usedQuote?.priceSlippage?.sourceAmountInETH || 0, - ) + ); const priceSlippageFromDestination = useEthFiatAmount( usedQuote?.priceSlippage?.destinationAmountInEth || 0, - ) + ); // We cannot present fiat value if there is a calculation error or no slippage // from source or destination const priceSlippageUnknownFiatValue = !priceSlippageFromSource || !priceSlippageFromDestination || - usedQuote?.priceSlippage?.calculationError + usedQuote?.priceSlippage?.calculationError; - let priceDifferencePercentage = 0 + let priceDifferencePercentage = 0; if (usedQuote?.priceSlippage?.ratio) { priceDifferencePercentage = parseFloat( new BigNumber(usedQuote.priceSlippage.ratio, 10) @@ -504,14 +504,14 @@ export default function ViewQuote() { .times(100, 10) .toFixed(2), 10, - ) + ); } const shouldShowPriceDifferenceWarning = !showInsufficientWarning && usedQuote && (['high', 'medium'].includes(usedQuote.priceSlippage.bucket) || - priceSlippageUnknownFiatValue) + priceSlippageUnknownFiatValue); if (shouldShowPriceDifferenceWarning) { viewQuotePriceDifferenceComponent = ( @@ -524,18 +524,18 @@ export default function ViewQuote() { priceDifferencePercentage={priceDifferencePercentage} priceSlippageUnknownFiatValue={priceSlippageUnknownFiatValue} onAcknowledgementClick={() => { - setAcknowledgedPriceDifference(true) + setAcknowledgedPriceDifference(true); }} acknowledged={acknowledgedPriceDifference} /> - ) + ); } const disableSubmissionDueToPriceWarning = - shouldShowPriceDifferenceWarning && !acknowledgedPriceDifference + shouldShowPriceDifferenceWarning && !acknowledgedPriceDifference; const isShowingWarning = - showInsufficientWarning || shouldShowPriceDifferenceWarning + showInsufficientWarning || shouldShowPriceDifferenceWarning; return (
    @@ -614,8 +614,8 @@ export default function ViewQuote() { isBestQuote={isBestQuote} numberOfQuotes={Object.values(quotes).length} onQuotesClick={() => { - allAvailableQuotesOpened() - setSelectQuotePopoverShown(true) + allAvailableQuotesOpened(); + setSelectQuotePopoverShown(true); }} tokenConversionRate={ destinationTokenSymbol === 'ETH' @@ -627,13 +627,13 @@ export default function ViewQuote() {
    { - setSubmitClicked(true) + setSubmitClicked(true); if (!balanceError) { - dispatch(signAndSendTransactions(history, metaMetricsEvent)) + dispatch(signAndSendTransactions(history, metaMetricsEvent)); } else if (destinationToken.symbol === 'ETH') { - history.push(DEFAULT_ROUTE) + history.push(DEFAULT_ROUTE); } else { - history.push(`${ASSET_ROUTE}/${destinationToken.address}`) + history.push(`${ASSET_ROUTE}/${destinationToken.address}`); } }} submitText={t('swap')} @@ -649,5 +649,5 @@ export default function ViewQuote() { showTopBorder /> - ) + ); } diff --git a/ui/app/pages/unlock-page/index.js b/ui/app/pages/unlock-page/index.js index 1f4c6ead9..2eac68721 100644 --- a/ui/app/pages/unlock-page/index.js +++ b/ui/app/pages/unlock-page/index.js @@ -1,3 +1,3 @@ -import UnlockPage from './unlock-page.container' +import UnlockPage from './unlock-page.container'; -export default UnlockPage +export default UnlockPage; diff --git a/ui/app/pages/unlock-page/tests/unlock-page.test.js b/ui/app/pages/unlock-page/tests/unlock-page.test.js index 34b258469..37bff5c34 100644 --- a/ui/app/pages/unlock-page/tests/unlock-page.test.js +++ b/ui/app/pages/unlock-page/tests/unlock-page.test.js @@ -1,11 +1,11 @@ -import assert from 'assert' -import React from 'react' -import sinon from 'sinon' -import { mount } from 'enzyme' -import UnlockPage from '..' +import assert from 'assert'; +import React from 'react'; +import sinon from 'sinon'; +import { mount } from 'enzyme'; +import UnlockPage from '..'; describe('Unlock Page', function () { - let wrapper + let wrapper; const props = { history: { @@ -17,47 +17,47 @@ describe('Unlock Page', function () { onSubmit: sinon.spy(), forceUpdateMetamaskState: sinon.spy(), showOptInModal: sinon.spy(), - } + }; beforeEach(function () { wrapper = mount(, { context: { t: (str) => str, }, - }) - }) + }); + }); after(function () { - sinon.restore() - }) + sinon.restore(); + }); it('renders', function () { - assert.strictEqual(wrapper.length, 1) - }) + assert.strictEqual(wrapper.length, 1); + }); it('changes password and submits', function () { - const passwordField = wrapper.find({ type: 'password', id: 'password' }) - const loginButton = wrapper.find({ type: 'submit' }).last() + const passwordField = wrapper.find({ type: 'password', id: 'password' }); + const loginButton = wrapper.find({ type: 'submit' }).last(); - const event = { target: { value: 'password' } } - assert.strictEqual(wrapper.instance().state.password, '') - passwordField.last().simulate('change', event) - assert.strictEqual(wrapper.instance().state.password, 'password') + const event = { target: { value: 'password' } }; + assert.strictEqual(wrapper.instance().state.password, ''); + passwordField.last().simulate('change', event); + assert.strictEqual(wrapper.instance().state.password, 'password'); - loginButton.simulate('click') - assert(props.onSubmit.calledOnce) - }) + loginButton.simulate('click'); + assert(props.onSubmit.calledOnce); + }); it('clicks imports seed button', function () { - const importSeedButton = wrapper.find('.unlock-page__link--import') + const importSeedButton = wrapper.find('.unlock-page__link--import'); - importSeedButton.simulate('click') - assert(props.onImport.calledOnce) - }) + importSeedButton.simulate('click'); + assert(props.onImport.calledOnce); + }); it('clicks restore', function () { - const restoreFromSeedButton = wrapper.find('.unlock-page__link').at(0) - restoreFromSeedButton.simulate('click') - assert(props.onRestore.calledOnce) - }) -}) + const restoreFromSeedButton = wrapper.find('.unlock-page__link').at(0); + restoreFromSeedButton.simulate('click'); + assert(props.onRestore.calledOnce); + }); +}); diff --git a/ui/app/pages/unlock-page/unlock-page.component.js b/ui/app/pages/unlock-page/unlock-page.component.js index 17776f7bd..bbf18716c 100644 --- a/ui/app/pages/unlock-page/unlock-page.component.js +++ b/ui/app/pages/unlock-page/unlock-page.component.js @@ -1,17 +1,17 @@ -import { EventEmitter } from 'events' -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import Button from '@material-ui/core/Button' -import getCaretCoordinates from 'textarea-caret' -import TextField from '../../components/ui/text-field' -import Mascot from '../../components/ui/mascot' -import { DEFAULT_ROUTE } from '../../helpers/constants/routes' +import { EventEmitter } from 'events'; +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import Button from '@material-ui/core/Button'; +import getCaretCoordinates from 'textarea-caret'; +import TextField from '../../components/ui/text-field'; +import Mascot from '../../components/ui/mascot'; +import { DEFAULT_ROUTE } from '../../helpers/constants/routes'; export default class UnlockPage extends Component { static contextTypes = { metricsEvent: PropTypes.func, t: PropTypes.func, - } + }; static propTypes = { history: PropTypes.object.isRequired, @@ -21,42 +21,42 @@ export default class UnlockPage extends Component { onSubmit: PropTypes.func, forceUpdateMetamaskState: PropTypes.func, showOptInModal: PropTypes.func, - } + }; state = { password: '', error: null, - } + }; - submitting = false + submitting = false; - animationEventEmitter = new EventEmitter() + animationEventEmitter = new EventEmitter(); UNSAFE_componentWillMount() { - const { isUnlocked, history } = this.props + const { isUnlocked, history } = this.props; if (isUnlocked) { - history.push(DEFAULT_ROUTE) + history.push(DEFAULT_ROUTE); } } handleSubmit = async (event) => { - event.preventDefault() - event.stopPropagation() + event.preventDefault(); + event.stopPropagation(); - const { password } = this.state - const { onSubmit, forceUpdateMetamaskState, showOptInModal } = this.props + const { password } = this.state; + const { onSubmit, forceUpdateMetamaskState, showOptInModal } = this.props; if (password === '' || this.submitting) { - return + return; } - this.setState({ error: null }) - this.submitting = true + this.setState({ error: null }); + this.submitting = true; try { - await onSubmit(password) - const newState = await forceUpdateMetamaskState() + await onSubmit(password); + const newState = await forceUpdateMetamaskState(); this.context.metricsEvent({ eventOpts: { category: 'Navigation', @@ -64,17 +64,17 @@ export default class UnlockPage extends Component { name: 'Success', }, isNewVisit: true, - }) + }); if ( newState.participateInMetaMetrics === null || newState.participateInMetaMetrics === undefined ) { - showOptInModal() + showOptInModal(); } } catch ({ message }) { if (message === 'Incorrect password') { - const newState = await forceUpdateMetamaskState() + const newState = await forceUpdateMetamaskState(); this.context.metricsEvent({ eventOpts: { category: 'Navigation', @@ -85,26 +85,26 @@ export default class UnlockPage extends Component { numberOfTokens: newState.tokens.length, numberOfAccounts: Object.keys(newState.accounts).length, }, - }) + }); } - this.setState({ error: message }) - this.submitting = false + this.setState({ error: message }); + this.submitting = false; } - } + }; handleInputChange({ target }) { - this.setState({ password: target.value, error: null }) + this.setState({ password: target.value, error: null }); // tell mascot to look at page action if (target.getBoundingClientRect) { - const element = target - const boundingRect = element.getBoundingClientRect() - const coordinates = getCaretCoordinates(element, element.selectionEnd) + const element = target; + const boundingRect = element.getBoundingClientRect(); + const coordinates = getCaretCoordinates(element, element.selectionEnd); this.animationEventEmitter.emit('point', { x: boundingRect.left + coordinates.left - element.scrollLeft, y: boundingRect.top + coordinates.top - element.scrollTop, - }) + }); } } @@ -117,7 +117,7 @@ export default class UnlockPage extends Component { fontWeight: '400', boxShadow: 'none', borderRadius: '4px', - } + }; return ( - ) + ); } render() { - const { password, error } = this.state - const { t } = this.context - const { onImport, onRestore } = this.props + const { password, error } = this.state; + const { t } = this.context; + const { onImport, onRestore } = this.props; return (
    @@ -180,6 +180,6 @@ export default class UnlockPage extends Component {
    - ) + ); } } diff --git a/ui/app/pages/unlock-page/unlock-page.container.js b/ui/app/pages/unlock-page/unlock-page.container.js index 9284ebeba..dbc20eaea 100644 --- a/ui/app/pages/unlock-page/unlock-page.container.js +++ b/ui/app/pages/unlock-page/unlock-page.container.js @@ -1,29 +1,29 @@ -import { connect } from 'react-redux' -import { withRouter } from 'react-router-dom' -import { compose } from 'redux' -import { getEnvironmentType } from '../../../../app/scripts/lib/util' -import { ENVIRONMENT_TYPE_POPUP } from '../../../../shared/constants/app' +import { connect } from 'react-redux'; +import { withRouter } from 'react-router-dom'; +import { compose } from 'redux'; +import { getEnvironmentType } from '../../../../app/scripts/lib/util'; +import { ENVIRONMENT_TYPE_POPUP } from '../../../../shared/constants/app'; import { DEFAULT_ROUTE, RESTORE_VAULT_ROUTE, -} from '../../helpers/constants/routes' +} from '../../helpers/constants/routes'; import { tryUnlockMetamask, forgotPassword, markPasswordForgotten, forceUpdateMetamaskState, showModal, -} from '../../store/actions' -import UnlockPage from './unlock-page.component' +} from '../../store/actions'; +import UnlockPage from './unlock-page.component'; const mapStateToProps = (state) => { const { metamask: { isUnlocked }, - } = state + } = state; return { isUnlocked, - } -} + }; +}; const mapDispatchToProps = (dispatch) => { return { @@ -33,8 +33,8 @@ const mapDispatchToProps = (dispatch) => { forceUpdateMetamaskState: () => forceUpdateMetamaskState(dispatch), showOptInModal: () => dispatch(showModal({ name: 'METAMETRICS_OPT_IN_MODAL' })), - } -} + }; +}; const mergeProps = (stateProps, dispatchProps, ownProps) => { const { @@ -43,22 +43,22 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => { // eslint-disable-next-line no-shadow tryUnlockMetamask, ...restDispatchProps - } = dispatchProps - const { history, onSubmit: ownPropsSubmit, ...restOwnProps } = ownProps + } = dispatchProps; + const { history, onSubmit: ownPropsSubmit, ...restOwnProps } = ownProps; const onImport = async () => { - await markPasswordForgotten() - history.push(RESTORE_VAULT_ROUTE) + await markPasswordForgotten(); + history.push(RESTORE_VAULT_ROUTE); if (getEnvironmentType() === ENVIRONMENT_TYPE_POPUP) { - global.platform.openExtensionInBrowser(RESTORE_VAULT_ROUTE) + global.platform.openExtensionInBrowser(RESTORE_VAULT_ROUTE); } - } + }; const onSubmit = async (password) => { - await tryUnlockMetamask(password) - history.push(DEFAULT_ROUTE) - } + await tryUnlockMetamask(password); + history.push(DEFAULT_ROUTE); + }; return { ...stateProps, @@ -68,10 +68,10 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => { onRestore: onImport, onSubmit: ownPropsSubmit || onSubmit, history, - } -} + }; +}; export default compose( withRouter, connect(mapStateToProps, mapDispatchToProps, mergeProps), -)(UnlockPage) +)(UnlockPage); diff --git a/ui/app/selectors/confirm-transaction.js b/ui/app/selectors/confirm-transaction.js index 3dc77d7d1..030da5f8e 100644 --- a/ui/app/selectors/confirm-transaction.js +++ b/ui/app/selectors/confirm-transaction.js @@ -1,6 +1,6 @@ -import { createSelector } from 'reselect' -import txHelper from '../../lib/tx-helper' -import { calcTokenAmount } from '../helpers/utils/token-util' +import { createSelector } from 'reselect'; +import txHelper from '../../lib/tx-helper'; +import { calcTokenAmount } from '../helpers/utils/token-util'; import { roundExponential, getValueFromWeiHex, @@ -8,21 +8,21 @@ import { getTransactionFee, addFiat, addEth, -} from '../helpers/utils/confirm-tx.util' -import { sumHexes } from '../helpers/utils/transactions.util' -import { getNativeCurrency } from '.' +} from '../helpers/utils/confirm-tx.util'; +import { sumHexes } from '../helpers/utils/transactions.util'; +import { getNativeCurrency } from '.'; -const unapprovedTxsSelector = (state) => state.metamask.unapprovedTxs -const unapprovedMsgsSelector = (state) => state.metamask.unapprovedMsgs +const unapprovedTxsSelector = (state) => state.metamask.unapprovedTxs; +const unapprovedMsgsSelector = (state) => state.metamask.unapprovedMsgs; const unapprovedPersonalMsgsSelector = (state) => - state.metamask.unapprovedPersonalMsgs + state.metamask.unapprovedPersonalMsgs; const unapprovedDecryptMsgsSelector = (state) => - state.metamask.unapprovedDecryptMsgs + state.metamask.unapprovedDecryptMsgs; const unapprovedEncryptionPublicKeyMsgsSelector = (state) => - state.metamask.unapprovedEncryptionPublicKeyMsgs + state.metamask.unapprovedEncryptionPublicKeyMsgs; const unapprovedTypedMessagesSelector = (state) => - state.metamask.unapprovedTypedMessages -const networkSelector = (state) => state.metamask.network + state.metamask.unapprovedTypedMessages; +const networkSelector = (state) => state.metamask.network; export const unconfirmedTransactionsListSelector = createSelector( unapprovedTxsSelector, @@ -50,7 +50,7 @@ export const unconfirmedTransactionsListSelector = createSelector( unapprovedTypedMessages, network, ) || [], -) +); export const unconfirmedTransactionsHashSelector = createSelector( unapprovedTxsSelector, @@ -71,17 +71,17 @@ export const unconfirmedTransactionsHashSelector = createSelector( ) => { const filteredUnapprovedTxs = Object.keys(unapprovedTxs).reduce( (acc, address) => { - const { metamaskNetworkId } = unapprovedTxs[address] - const transactions = { ...acc } + const { metamaskNetworkId } = unapprovedTxs[address]; + const transactions = { ...acc }; if (metamaskNetworkId === network) { - transactions[address] = unapprovedTxs[address] + transactions[address] = unapprovedTxs[address]; } - return transactions + return transactions; }, {}, - ) + ); return { ...filteredUnapprovedTxs, @@ -90,19 +90,19 @@ export const unconfirmedTransactionsHashSelector = createSelector( ...unapprovedDecryptMsgs, ...unapprovedEncryptionPublicKeyMsgs, ...unapprovedTypedMessages, - } + }; }, -) +); -const unapprovedMsgCountSelector = (state) => state.metamask.unapprovedMsgCount +const unapprovedMsgCountSelector = (state) => state.metamask.unapprovedMsgCount; const unapprovedPersonalMsgCountSelector = (state) => - state.metamask.unapprovedPersonalMsgCount + state.metamask.unapprovedPersonalMsgCount; const unapprovedDecryptMsgCountSelector = (state) => - state.metamask.unapprovedDecryptMsgCount + state.metamask.unapprovedDecryptMsgCount; const unapprovedEncryptionPublicKeyMsgCountSelector = (state) => - state.metamask.unapprovedEncryptionPublicKeyMsgCount + state.metamask.unapprovedEncryptionPublicKeyMsgCount; const unapprovedTypedMessagesCountSelector = (state) => - state.metamask.unapprovedTypedMessagesCount + state.metamask.unapprovedTypedMessagesCount; export const unconfirmedTransactionsCountSelector = createSelector( unapprovedTxsSelector, @@ -123,10 +123,10 @@ export const unconfirmedTransactionsCountSelector = createSelector( ) => { const filteredUnapprovedTxIds = Object.keys(unapprovedTxs).filter( (txId) => { - const { metamaskNetworkId } = unapprovedTxs[txId] - return metamaskNetworkId === network + const { metamaskNetworkId } = unapprovedTxs[txId]; + return metamaskNetworkId === network; }, - ) + ); return ( filteredUnapprovedTxIds.length + @@ -135,85 +135,86 @@ export const unconfirmedTransactionsCountSelector = createSelector( unapprovedPersonalMsgCount + unapprovedDecryptMsgCount + unapprovedEncryptionPublicKeyMsgCount - ) + ); }, -) +); -export const currentCurrencySelector = (state) => state.metamask.currentCurrency -export const conversionRateSelector = (state) => state.metamask.conversionRate +export const currentCurrencySelector = (state) => + state.metamask.currentCurrency; +export const conversionRateSelector = (state) => state.metamask.conversionRate; -export const txDataSelector = (state) => state.confirmTransaction.txData -const tokenDataSelector = (state) => state.confirmTransaction.tokenData -const tokenPropsSelector = (state) => state.confirmTransaction.tokenProps +export const txDataSelector = (state) => state.confirmTransaction.txData; +const tokenDataSelector = (state) => state.confirmTransaction.tokenData; +const tokenPropsSelector = (state) => state.confirmTransaction.tokenProps; const contractExchangeRatesSelector = (state) => - state.metamask.contractExchangeRates + state.metamask.contractExchangeRates; const tokenDecimalsSelector = createSelector( tokenPropsSelector, (tokenProps) => tokenProps && tokenProps.tokenDecimals, -) +); const tokenDataArgsSelector = createSelector( tokenDataSelector, (tokenData) => (tokenData && tokenData.args) || [], -) +); const txParamsSelector = createSelector( txDataSelector, (txData) => (txData && txData.txParams) || {}, -) +); export const tokenAddressSelector = createSelector( txParamsSelector, (txParams) => txParams && txParams.to, -) +); -const TOKEN_PARAM_TO = '_to' -const TOKEN_PARAM_VALUE = '_value' +const TOKEN_PARAM_TO = '_to'; +const TOKEN_PARAM_VALUE = '_value'; export const sendTokenTokenAmountAndToAddressSelector = createSelector( tokenDataArgsSelector, tokenDecimalsSelector, (args, tokenDecimals) => { - let toAddress = '' - let tokenAmount = '0' + let toAddress = ''; + let tokenAmount = '0'; // Token params here are ethers BigNumbers, which have a different // interface than bignumber.js if (args && args.length) { - toAddress = args[TOKEN_PARAM_TO] - let value = args[TOKEN_PARAM_VALUE].toString() + toAddress = args[TOKEN_PARAM_TO]; + let value = args[TOKEN_PARAM_VALUE].toString(); if (tokenDecimals) { // bignumber.js return value - value = calcTokenAmount(value, tokenDecimals).toFixed() + value = calcTokenAmount(value, tokenDecimals).toFixed(); } - tokenAmount = roundExponential(value) + tokenAmount = roundExponential(value); } return { toAddress, tokenAmount, - } + }; }, -) +); export const contractExchangeRateSelector = createSelector( contractExchangeRatesSelector, tokenAddressSelector, (contractExchangeRates, tokenAddress) => contractExchangeRates[tokenAddress], -) +); export const transactionFeeSelector = function (state, txData) { - const currentCurrency = currentCurrencySelector(state) - const conversionRate = conversionRateSelector(state) - const nativeCurrency = getNativeCurrency(state) + const currentCurrency = currentCurrencySelector(state); + const conversionRate = conversionRateSelector(state); + const nativeCurrency = getNativeCurrency(state); const { txParams: { value = '0x0', gas: gasLimit = '0x0', gasPrice = '0x0' } = {}, - } = txData + } = txData; const fiatTransactionAmount = getValueFromWeiHex({ value, @@ -221,16 +222,16 @@ export const transactionFeeSelector = function (state, txData) { toCurrency: currentCurrency, conversionRate, numberOfDecimals: 2, - }) + }); const ethTransactionAmount = getValueFromWeiHex({ value, fromCurrency: nativeCurrency, toCurrency: nativeCurrency, conversionRate, numberOfDecimals: 6, - }) + }); - const hexTransactionFee = getHexGasTotal({ gasLimit, gasPrice }) + const hexTransactionFee = getHexGasTotal({ gasLimit, gasPrice }); const fiatTransactionFee = getTransactionFee({ value: hexTransactionFee, @@ -238,21 +239,21 @@ export const transactionFeeSelector = function (state, txData) { toCurrency: currentCurrency, numberOfDecimals: 2, conversionRate, - }) + }); const ethTransactionFee = getTransactionFee({ value: hexTransactionFee, fromCurrency: nativeCurrency, toCurrency: nativeCurrency, numberOfDecimals: 6, conversionRate, - }) + }); const fiatTransactionTotal = addFiat( fiatTransactionFee, fiatTransactionAmount, - ) - const ethTransactionTotal = addEth(ethTransactionFee, ethTransactionAmount) - const hexTransactionTotal = sumHexes(value, hexTransactionFee) + ); + const ethTransactionTotal = addEth(ethTransactionFee, ethTransactionAmount); + const hexTransactionTotal = sumHexes(value, hexTransactionFee); return { hexTransactionAmount: value, @@ -264,5 +265,5 @@ export const transactionFeeSelector = function (state, txData) { fiatTransactionTotal, ethTransactionTotal, hexTransactionTotal, - } -} + }; +}; diff --git a/ui/app/selectors/custom-gas.js b/ui/app/selectors/custom-gas.js index 8b1df8b89..b6662c03b 100644 --- a/ui/app/selectors/custom-gas.js +++ b/ui/app/selectors/custom-gas.js @@ -1,38 +1,38 @@ -import { addHexPrefix } from '../../../app/scripts/lib/util' +import { addHexPrefix } from '../../../app/scripts/lib/util'; import { conversionUtil, conversionGreaterThan, -} from '../helpers/utils/conversion-util' -import { formatCurrency } from '../helpers/utils/confirm-tx.util' -import { decEthToConvertedCurrency as ethTotalToConvertedCurrency } from '../helpers/utils/conversions.util' -import { formatETHFee } from '../helpers/utils/formatters' -import { calcGasTotal } from '../pages/send/send.utils' +} from '../helpers/utils/conversion-util'; +import { formatCurrency } from '../helpers/utils/confirm-tx.util'; +import { decEthToConvertedCurrency as ethTotalToConvertedCurrency } from '../helpers/utils/conversions.util'; +import { formatETHFee } from '../helpers/utils/formatters'; +import { calcGasTotal } from '../pages/send/send.utils'; -import { GAS_ESTIMATE_TYPES } from '../helpers/constants/common' -import { getCurrentCurrency, getIsMainnet, getPreferences } from '.' +import { GAS_ESTIMATE_TYPES } from '../helpers/constants/common'; +import { getCurrentCurrency, getIsMainnet, getPreferences } from '.'; -const NUMBER_OF_DECIMALS_SM_BTNS = 5 +const NUMBER_OF_DECIMALS_SM_BTNS = 5; export function getCustomGasLimit(state) { - return state.gas.customData.limit + return state.gas.customData.limit; } export function getCustomGasPrice(state) { - return state.gas.customData.price + return state.gas.customData.price; } export function getBasicGasEstimateLoadingStatus(state) { - return state.gas.basicEstimateIsLoading + return state.gas.basicEstimateIsLoading; } export function getAveragePriceEstimateInHexWEI(state) { - const averagePriceEstimate = state.gas.basicEstimates.average - return getGasPriceInHexWei(averagePriceEstimate || '0x0') + const averagePriceEstimate = state.gas.basicEstimates.average; + return getGasPriceInHexWei(averagePriceEstimate || '0x0'); } export function getFastPriceEstimateInHexWEI(state) { - const fastPriceEstimate = state.gas.basicEstimates.fast - return getGasPriceInHexWei(fastPriceEstimate || '0x0') + const fastPriceEstimate = state.gas.basicEstimates.fast; + return getGasPriceInHexWei(fastPriceEstimate || '0x0'); } export function getDefaultActiveButtonIndex( @@ -42,7 +42,7 @@ export function getDefaultActiveButtonIndex( ) { return gasButtonInfo .map(({ priceInHexWei }) => priceInHexWei) - .lastIndexOf(addHexPrefix(customGasPriceInHex || gasPrice)) + .lastIndexOf(addHexPrefix(customGasPriceInHex || gasPrice)); } export function getSafeLowEstimate(state) { @@ -50,22 +50,22 @@ export function getSafeLowEstimate(state) { gas: { basicEstimates: { safeLow }, }, - } = state + } = state; - return safeLow + return safeLow; } export function isCustomPriceSafe(state) { - const safeLow = getSafeLowEstimate(state) + const safeLow = getSafeLowEstimate(state); - const customGasPrice = getCustomGasPrice(state) + const customGasPrice = getCustomGasPrice(state); if (!customGasPrice) { - return true + return true; } if (safeLow === null) { - return false + return false; } const customPriceSafe = conversionGreaterThan( @@ -76,9 +76,9 @@ export function isCustomPriceSafe(state) { toDenomination: 'GWEI', }, { value: safeLow, fromNumericBase: 'dec' }, - ) + ); - return customPriceSafe + return customPriceSafe; } export function basicPriceEstimateToETHTotal( @@ -91,16 +91,16 @@ export function basicPriceEstimateToETHTotal( toNumericBase: 'dec', fromDenomination: 'GWEI', numberOfDecimals, - }) + }); } export function getRenderableEthFee(estimate, gasLimit, numberOfDecimals = 9) { const value = conversionUtil(estimate, { fromNumericBase: 'dec', toNumericBase: 'hex', - }) - const fee = basicPriceEstimateToETHTotal(value, gasLimit, numberOfDecimals) - return formatETHFee(fee) + }); + const fee = basicPriceEstimateToETHTotal(value, gasLimit, numberOfDecimals); + return formatETHFee(fee); } export function getRenderableConvertedCurrencyFee( @@ -112,14 +112,14 @@ export function getRenderableConvertedCurrencyFee( const value = conversionUtil(estimate, { fromNumericBase: 'dec', toNumericBase: 'hex', - }) - const fee = basicPriceEstimateToETHTotal(value, gasLimit) + }); + const fee = basicPriceEstimateToETHTotal(value, gasLimit); const feeInCurrency = ethTotalToConvertedCurrency( fee, convertedCurrency, conversionRate, - ) - return formatCurrency(feeInCurrency, convertedCurrency) + ); + return formatCurrency(feeInCurrency, convertedCurrency); } export function priceEstimateToWei(priceEstimate) { @@ -129,15 +129,15 @@ export function priceEstimateToWei(priceEstimate) { fromDenomination: 'GWEI', toDenomination: 'WEI', numberOfDecimals: 9, - }) + }); } export function getGasPriceInHexWei(price) { const value = conversionUtil(price, { fromNumericBase: 'dec', toNumericBase: 'hex', - }) - return addHexPrefix(priceEstimateToWei(value)) + }); + return addHexPrefix(priceEstimateToWei(value)); } export function getRenderableGasButtonData( @@ -147,7 +147,7 @@ export function getRenderableGasButtonData( conversionRate, currentCurrency, ) { - const { safeLow, average, fast } = estimates + const { safeLow, average, fast } = estimates; const slowEstimateData = { gasEstimateType: GAS_ESTIMATE_TYPES.SLOW, @@ -161,7 +161,7 @@ export function getRenderableGasButtonData( ) : '', priceInHexWei: getGasPriceInHexWei(safeLow), - } + }; const averageEstimateData = { gasEstimateType: GAS_ESTIMATE_TYPES.AVERAGE, feeInPrimaryCurrency: getRenderableEthFee(average, gasLimit), @@ -174,7 +174,7 @@ export function getRenderableGasButtonData( ) : '', priceInHexWei: getGasPriceInHexWei(average), - } + }; const fastEstimateData = { gasEstimateType: GAS_ESTIMATE_TYPES.FAST, feeInPrimaryCurrency: getRenderableEthFee(fast, gasLimit), @@ -187,25 +187,25 @@ export function getRenderableGasButtonData( ) : '', priceInHexWei: getGasPriceInHexWei(fast), - } + }; return { slowEstimateData, averageEstimateData, fastEstimateData, - } + }; } export function getRenderableBasicEstimateData(state, gasLimit) { if (getBasicGasEstimateLoadingStatus(state)) { - return [] + return []; } - const { showFiatInTestnets } = getPreferences(state) - const isMainnet = getIsMainnet(state) - const showFiat = isMainnet || Boolean(showFiatInTestnets) - const { conversionRate } = state.metamask - const currentCurrency = getCurrentCurrency(state) + const { showFiatInTestnets } = getPreferences(state); + const isMainnet = getIsMainnet(state); + const showFiat = isMainnet || Boolean(showFiatInTestnets); + const { conversionRate } = state.metamask; + const currentCurrency = getCurrentCurrency(state); const { slowEstimateData, @@ -217,28 +217,28 @@ export function getRenderableBasicEstimateData(state, gasLimit) { showFiat, conversionRate, currentCurrency, - ) + ); - return [slowEstimateData, averageEstimateData, fastEstimateData] + return [slowEstimateData, averageEstimateData, fastEstimateData]; } export function getRenderableEstimateDataForSmallButtonsFromGWEI(state) { if (getBasicGasEstimateLoadingStatus(state)) { - return [] + return []; } - const { showFiatInTestnets } = getPreferences(state) - const isMainnet = getIsMainnet(state) - const showFiat = isMainnet || Boolean(showFiatInTestnets) + const { showFiatInTestnets } = getPreferences(state); + const isMainnet = getIsMainnet(state); + const showFiat = isMainnet || Boolean(showFiatInTestnets); const gasLimit = - state.metamask.send.gasLimit || getCustomGasLimit(state) || '0x5208' - const { conversionRate } = state.metamask - const currentCurrency = getCurrentCurrency(state) + state.metamask.send.gasLimit || getCustomGasLimit(state) || '0x5208'; + const { conversionRate } = state.metamask; + const currentCurrency = getCurrentCurrency(state); const { gas: { basicEstimates: { safeLow, average, fast }, }, - } = state + } = state; return [ { @@ -295,5 +295,5 @@ export function getRenderableEstimateDataForSmallButtonsFromGWEI(state) { ), priceInHexWei: getGasPriceInHexWei(fast, true), }, - ] + ]; } diff --git a/ui/app/selectors/first-time-flow.js b/ui/app/selectors/first-time-flow.js index 284a4bca1..b56bdc861 100644 --- a/ui/app/selectors/first-time-flow.js +++ b/ui/app/selectors/first-time-flow.js @@ -2,34 +2,34 @@ import { INITIALIZE_CREATE_PASSWORD_ROUTE, INITIALIZE_IMPORT_WITH_SEED_PHRASE_ROUTE, DEFAULT_ROUTE, -} from '../helpers/constants/routes' +} from '../helpers/constants/routes'; export function getFirstTimeFlowTypeRoute(state) { - const { firstTimeFlowType } = state.metamask + const { firstTimeFlowType } = state.metamask; - let nextRoute + let nextRoute; if (firstTimeFlowType === 'create') { - nextRoute = INITIALIZE_CREATE_PASSWORD_ROUTE + nextRoute = INITIALIZE_CREATE_PASSWORD_ROUTE; } else if (firstTimeFlowType === 'import') { - nextRoute = INITIALIZE_IMPORT_WITH_SEED_PHRASE_ROUTE + nextRoute = INITIALIZE_IMPORT_WITH_SEED_PHRASE_ROUTE; } else { - nextRoute = DEFAULT_ROUTE + nextRoute = DEFAULT_ROUTE; } - return nextRoute + return nextRoute; } export const getOnboardingInitiator = (state) => { - const { onboardingTabs } = state.metamask + const { onboardingTabs } = state.metamask; if (!onboardingTabs || Object.keys(onboardingTabs).length !== 1) { - return null + return null; } - const location = Object.keys(onboardingTabs)[0] - const tabId = onboardingTabs[location] + const location = Object.keys(onboardingTabs)[0]; + const tabId = onboardingTabs[location]; return { location, tabId, - } -} + }; +}; diff --git a/ui/app/selectors/index.js b/ui/app/selectors/index.js index c9e5f2f6a..b82c59c05 100644 --- a/ui/app/selectors/index.js +++ b/ui/app/selectors/index.js @@ -1,7 +1,7 @@ -export * from './confirm-transaction' -export * from './custom-gas' -export * from './first-time-flow' -export * from './permissions' -export * from './selectors' -export * from './send' -export * from './transactions' +export * from './confirm-transaction'; +export * from './custom-gas'; +export * from './first-time-flow'; +export * from './permissions'; +export * from './selectors'; +export * from './send'; +export * from './transactions'; diff --git a/ui/app/selectors/permissions.js b/ui/app/selectors/permissions.js index e6dfa4db5..6b104f2e1 100644 --- a/ui/app/selectors/permissions.js +++ b/ui/app/selectors/permissions.js @@ -1,10 +1,10 @@ -import { forOwn } from 'lodash' -import { CAVEAT_NAMES } from '../../../shared/constants/permissions' +import { forOwn } from 'lodash'; +import { CAVEAT_NAMES } from '../../../shared/constants/permissions'; import { getMetaMaskAccountsOrdered, getOriginOfCurrentTab, getSelectedAddress, -} from '.' +} from '.'; // selectors @@ -15,7 +15,7 @@ import { * @returns {Object} The permissions domains object. */ export function getPermissionDomains(state) { - return state.metamask.domains || {} + return state.metamask.domains || {}; } /** @@ -25,7 +25,7 @@ export function getPermissionDomains(state) { * @returns {Object} The permission domains metadata object. */ export function getPermissionDomainsMetadata(state) { - return state.metamask.domainMetadata || {} + return state.metamask.domainMetadata || {}; } /** @@ -39,7 +39,7 @@ export function getPermissionDomainsMetadata(state) { export function getPermittedAccounts(state, origin) { return getAccountsFromPermission( getAccountsPermissionFromDomain(domainSelector(state, origin)), - ) + ); } /** @@ -50,7 +50,7 @@ export function getPermittedAccounts(state, origin) { * @returns {Array} An empty array or an array of accounts. */ export function getPermittedAccountsForCurrentTab(state) { - return getPermittedAccounts(state, getOriginOfCurrentTab(state)) + return getPermittedAccounts(state, getOriginOfCurrentTab(state)); } /** @@ -60,16 +60,16 @@ export function getPermittedAccountsForCurrentTab(state) { * @returns {Object} Permitted accounts by origin. */ export function getPermittedAccountsByOrigin(state) { - const domains = getPermissionDomains(state) + const domains = getPermissionDomains(state); return Object.keys(domains).reduce((acc, domainKey) => { const accounts = getAccountsFromPermission( getAccountsPermissionFromDomain(domains[domainKey]), - ) + ); if (accounts.length > 0) { - acc[domainKey] = accounts + acc[domainKey] = accounts; } - return acc - }, {}) + return acc; + }, {}); } /** @@ -83,19 +83,19 @@ export function getPermittedAccountsByOrigin(state) { * @returns {Array} An array of connected domain objects. */ export function getConnectedDomainsForSelectedAddress(state) { - const { selectedAddress } = state.metamask - const domains = getPermissionDomains(state) - const domainMetadata = getPermissionDomainsMetadata(state) + const { selectedAddress } = state.metamask; + const domains = getPermissionDomains(state); + const domainMetadata = getPermissionDomainsMetadata(state); - const connectedDomains = [] + const connectedDomains = []; forOwn(domains, (domainValue, domainKey) => { - const exposedAccounts = getAccountsFromDomain(domainValue) + const exposedAccounts = getAccountsFromDomain(domainValue); if (!exposedAccounts.includes(selectedAddress)) { - return + return; } - const { extensionId, name, icon, host } = domainMetadata[domainKey] || {} + const { extensionId, name, icon, host } = domainMetadata[domainKey] || {}; connectedDomains.push({ extensionId, @@ -103,10 +103,10 @@ export function getConnectedDomainsForSelectedAddress(state) { name, icon, host, - }) - }) + }); + }); - return connectedDomains + return connectedDomains; } /** @@ -120,32 +120,32 @@ export function getConnectedDomainsForSelectedAddress(state) { * connected domain info. */ export function getAddressConnectedDomainMap(state) { - const domainMetadata = getPermissionDomainsMetadata(state) - const accountsMap = getPermittedAccountsByOrigin(state) - const addressConnectedIconMap = {} + const domainMetadata = getPermissionDomainsMetadata(state); + const accountsMap = getPermittedAccountsByOrigin(state); + const addressConnectedIconMap = {}; Object.keys(accountsMap).forEach((domainKey) => { - const { icon, name } = domainMetadata[domainKey] || {} + const { icon, name } = domainMetadata[domainKey] || {}; accountsMap[domainKey].forEach((address) => { - const nameToRender = name || domainKey + const nameToRender = name || domainKey; addressConnectedIconMap[address] = addressConnectedIconMap[address] ? { ...addressConnectedIconMap[address], [domainKey]: { icon, name: nameToRender }, } - : { [domainKey]: { icon, name: nameToRender } } - }) - }) + : { [domainKey]: { icon, name: nameToRender } }; + }); + }); - return addressConnectedIconMap + return addressConnectedIconMap; } // selector helpers function getAccountsFromDomain(domain) { - return getAccountsFromPermission(getAccountsPermissionFromDomain(domain)) + return getAccountsFromPermission(getAccountsPermissionFromDomain(domain)); } function getAccountsPermissionFromDomain(domain = {}) { @@ -153,14 +153,14 @@ function getAccountsPermissionFromDomain(domain = {}) { ? domain.permissions.find( (perm) => perm.parentCapability === 'eth_accounts', ) - : {} + : {}; } function getAccountsFromPermission(accountsPermission) { - const accountsCaveat = getAccountsCaveatFromPermission(accountsPermission) + const accountsCaveat = getAccountsCaveatFromPermission(accountsPermission); return accountsCaveat && Array.isArray(accountsCaveat.value) ? accountsCaveat.value - : [] + : []; } function getAccountsCaveatFromPermission(accountsPermission = {}) { @@ -169,21 +169,21 @@ function getAccountsCaveatFromPermission(accountsPermission = {}) { accountsPermission.caveats.find( (c) => c.name === CAVEAT_NAMES.exposedAccounts, ) - ) + ); } function domainSelector(state, origin) { - return origin && state.metamask.domains?.[origin] + return origin && state.metamask.domains?.[origin]; } export function getAccountToConnectToActiveTab(state) { - const selectedAddress = getSelectedAddress(state) - const connectedAccounts = getPermittedAccountsForCurrentTab(state) + const selectedAddress = getSelectedAddress(state); + const connectedAccounts = getPermittedAccountsForCurrentTab(state); const { metamask: { identities }, - } = state - const numberOfAccounts = Object.keys(identities).length + } = state; + const numberOfAccounts = Object.keys(identities).length; if ( connectedAccounts.length && @@ -193,24 +193,24 @@ export function getAccountToConnectToActiveTab(state) { connectedAccounts.findIndex((address) => address === selectedAddress) === -1 ) { - return identities[selectedAddress] + return identities[selectedAddress]; } } - return undefined + return undefined; } export function getOrderedConnectedAccountsForActiveTab(state) { const { activeTab, metamask: { permissionsHistory }, - } = state + } = state; const permissionsHistoryByAccount = // eslint-disable-next-line camelcase - permissionsHistory[activeTab.origin]?.eth_accounts?.accounts - const orderedAccounts = getMetaMaskAccountsOrdered(state) - const connectedAccounts = getPermittedAccountsForCurrentTab(state) + permissionsHistory[activeTab.origin]?.eth_accounts?.accounts; + const orderedAccounts = getMetaMaskAccountsOrdered(state); + const connectedAccounts = getPermittedAccountsForCurrentTab(state); return orderedAccounts .filter((account) => connectedAccounts.includes(account.address)) @@ -221,73 +221,73 @@ export function getOrderedConnectedAccountsForActiveTab(state) { .sort( ({ lastSelected: lastSelectedA }, { lastSelected: lastSelectedB }) => { if (lastSelectedA === lastSelectedB) { - return 0 + return 0; } else if (lastSelectedA === undefined) { - return 1 + return 1; } else if (lastSelectedB === undefined) { - return -1 + return -1; } - return lastSelectedB - lastSelectedA + return lastSelectedB - lastSelectedA; }, - ) + ); } export function getPermissionsForActiveTab(state) { - const { activeTab, metamask } = state - const { domains = {} } = metamask + const { activeTab, metamask } = state; + const { domains = {} } = metamask; return domains[activeTab.origin]?.permissions?.map(({ parentCapability }) => { return { key: parentCapability, - } - }) + }; + }); } export function activeTabHasPermissions(state) { - const { activeTab, metamask } = state - const { domains = {} } = metamask + const { activeTab, metamask } = state; + const { domains = {} } = metamask; - return Boolean(domains[activeTab.origin]?.permissions?.length > 0) + return Boolean(domains[activeTab.origin]?.permissions?.length > 0); } export function getLastConnectedInfo(state) { - const { permissionsHistory = {} } = state.metamask + const { permissionsHistory = {} } = state.metamask; return Object.keys(permissionsHistory).reduce((acc, origin) => { const ethAccountsHistory = JSON.parse( JSON.stringify(permissionsHistory[origin].eth_accounts), - ) + ); return { ...acc, [origin]: ethAccountsHistory, - } - }, {}) + }; + }, {}); } export function getPermissionsMetadataHostCounts(state) { - const metadata = getPermissionDomainsMetadata(state) + const metadata = getPermissionDomainsMetadata(state); return Object.values(metadata).reduce((counts, { host }) => { if (host) { if (counts[host]) { - counts[host] += 1 + counts[host] += 1; } else { - counts[host] = 1 + counts[host] = 1; } } - return counts - }, {}) + return counts; + }, {}); } export function getPermissionsRequests(state) { - return state.metamask.permissionsRequests || [] + return state.metamask.permissionsRequests || []; } export function getPermissionsRequestCount(state) { - const permissionsRequests = getPermissionsRequests(state) - return permissionsRequests.length + const permissionsRequests = getPermissionsRequests(state); + return permissionsRequests.length; } export function getFirstPermissionRequest(state) { - const requests = getPermissionsRequests(state) - return requests && requests[0] ? requests[0] : null + const requests = getPermissionsRequests(state); + return requests && requests[0] ? requests[0] : null; } diff --git a/ui/app/selectors/selectors.js b/ui/app/selectors/selectors.js index 9db335a85..9e8711e2f 100644 --- a/ui/app/selectors/selectors.js +++ b/ui/app/selectors/selectors.js @@ -1,70 +1,70 @@ -import { stripHexPrefix } from 'ethereumjs-util' -import { createSelector } from 'reselect' -import { addHexPrefix } from '../../../app/scripts/lib/util' -import { MAINNET, NETWORK_TYPE_RPC } from '../../../shared/constants/network' +import { stripHexPrefix } from 'ethereumjs-util'; +import { createSelector } from 'reselect'; +import { addHexPrefix } from '../../../app/scripts/lib/util'; +import { MAINNET, NETWORK_TYPE_RPC } from '../../../shared/constants/network'; import { shortenAddress, checksumAddress, getAccountByAddress, -} from '../helpers/utils/util' -import { getPermissionsRequestCount } from './permissions' +} from '../helpers/utils/util'; +import { getPermissionsRequestCount } from './permissions'; export function getNetworkIdentifier(state) { const { metamask: { provider: { type, nickname, rpcUrl }, }, - } = state + } = state; - return nickname || rpcUrl || type + return nickname || rpcUrl || type; } export function getMetricsNetworkIdentifier(state) { - const { provider } = state.metamask - return provider.type === NETWORK_TYPE_RPC ? provider.rpcUrl : provider.type + const { provider } = state.metamask; + return provider.type === NETWORK_TYPE_RPC ? provider.rpcUrl : provider.type; } export function getCurrentChainId(state) { - const { chainId } = state.metamask.provider - return chainId + const { chainId } = state.metamask.provider; + return chainId; } export function getCurrentKeyring(state) { - const identity = getSelectedIdentity(state) + const identity = getSelectedIdentity(state); if (!identity) { - return null + return null; } - const simpleAddress = stripHexPrefix(identity.address).toLowerCase() + const simpleAddress = stripHexPrefix(identity.address).toLowerCase(); const keyring = state.metamask.keyrings.find((kr) => { return ( kr.accounts.includes(simpleAddress) || kr.accounts.includes(identity.address) - ) - }) + ); + }); - return keyring + return keyring; } export function getAccountType(state) { - const currentKeyring = getCurrentKeyring(state) - const type = currentKeyring && currentKeyring.type + const currentKeyring = getCurrentKeyring(state); + const type = currentKeyring && currentKeyring.type; switch (type) { case 'Trezor Hardware': case 'Ledger Hardware': - return 'hardware' + return 'hardware'; case 'Simple Key Pair': - return 'imported' + return 'imported'; default: - return 'default' + return 'default'; } } export function getCurrentNetworkId(state) { - return state.metamask.network + return state.metamask.network; } export const getMetaMaskAccounts = createSelector( @@ -80,53 +80,53 @@ export const getMetaMaskAccounts = createSelector( ...account, balance: cachedBalances && cachedBalances[accountID], }, - } + }; } return { ...selectedAccounts, [accountID]: account, - } + }; }, {}, ), -) +); export function getSelectedAddress(state) { - return state.metamask.selectedAddress + return state.metamask.selectedAddress; } export function getSelectedIdentity(state) { - const selectedAddress = getSelectedAddress(state) - const { identities } = state.metamask + const selectedAddress = getSelectedAddress(state); + const { identities } = state.metamask; - return identities[selectedAddress] + return identities[selectedAddress]; } export function getNumberOfAccounts(state) { - return Object.keys(state.metamask.accounts).length + return Object.keys(state.metamask.accounts).length; } export function getNumberOfTokens(state) { - const { tokens } = state.metamask - return tokens ? tokens.length : 0 + const { tokens } = state.metamask; + return tokens ? tokens.length : 0; } export function getMetaMaskKeyrings(state) { - return state.metamask.keyrings + return state.metamask.keyrings; } export function getMetaMaskIdentities(state) { - return state.metamask.identities + return state.metamask.identities; } export function getMetaMaskAccountsRaw(state) { - return state.metamask.accounts + return state.metamask.accounts; } export function getMetaMaskCachedBalances(state) { - const network = getCurrentNetworkId(state) + const network = getCurrentNetworkId(state); - return state.metamask.cachedBalances[network] + return state.metamask.cachedBalances[network]; } /** @@ -141,76 +141,76 @@ export const getMetaMaskAccountsOrdered = createSelector( .reduce((list, keyring) => list.concat(keyring.accounts), []) .filter((address) => Boolean(identities[address])) .map((address) => ({ ...identities[address], ...accounts[address] })), -) +); export function isBalanceCached(state) { const selectedAccountBalance = - state.metamask.accounts[getSelectedAddress(state)].balance - const cachedBalance = getSelectedAccountCachedBalance(state) + state.metamask.accounts[getSelectedAddress(state)].balance; + const cachedBalance = getSelectedAccountCachedBalance(state); - return Boolean(!selectedAccountBalance && cachedBalance) + return Boolean(!selectedAccountBalance && cachedBalance); } export function getSelectedAccountCachedBalance(state) { - const cachedBalances = state.metamask.cachedBalances[state.metamask.network] - const selectedAddress = getSelectedAddress(state) + const cachedBalances = state.metamask.cachedBalances[state.metamask.network]; + const selectedAddress = getSelectedAddress(state); - return cachedBalances && cachedBalances[selectedAddress] + return cachedBalances && cachedBalances[selectedAddress]; } export function getSelectedAccount(state) { - const accounts = getMetaMaskAccounts(state) - const selectedAddress = getSelectedAddress(state) + const accounts = getMetaMaskAccounts(state); + const selectedAddress = getSelectedAddress(state); - return accounts[selectedAddress] + return accounts[selectedAddress]; } export function getTargetAccount(state, targetAddress) { - const accounts = getMetaMaskAccounts(state) - return accounts[targetAddress] + const accounts = getMetaMaskAccounts(state); + return accounts[targetAddress]; } export const getTokenExchangeRates = (state) => - state.metamask.contractExchangeRates + state.metamask.contractExchangeRates; export function getAssetImages(state) { - const assetImages = state.metamask.assetImages || {} - return assetImages + const assetImages = state.metamask.assetImages || {}; + return assetImages; } export function getAddressBook(state) { - const chainId = getCurrentChainId(state) + const chainId = getCurrentChainId(state); if (!state.metamask.addressBook[chainId]) { - return [] + return []; } - return Object.values(state.metamask.addressBook[chainId]) + return Object.values(state.metamask.addressBook[chainId]); } export function getAddressBookEntry(state, address) { - const addressBook = getAddressBook(state) + const addressBook = getAddressBook(state); const entry = addressBook.find( (contact) => contact.address === checksumAddress(address), - ) - return entry + ); + return entry; } export function getAddressBookEntryName(state, address) { const entry = - getAddressBookEntry(state, address) || state.metamask.identities[address] - return entry && entry.name !== '' ? entry.name : shortenAddress(address) + getAddressBookEntry(state, address) || state.metamask.identities[address]; + return entry && entry.name !== '' ? entry.name : shortenAddress(address); } export function accountsWithSendEtherInfoSelector(state) { - const accounts = getMetaMaskAccounts(state) - const identities = getMetaMaskIdentities(state) + const accounts = getMetaMaskAccounts(state); + const identities = getMetaMaskIdentities(state); const accountsWithSendEtherInfo = Object.entries(identities).map( ([key, identity]) => { - return { ...identity, ...accounts[key] } + return { ...identity, ...accounts[key] }; }, - ) + ); - return accountsWithSendEtherInfo + return accountsWithSendEtherInfo; } export function getAccountsWithLabels(state) { @@ -221,31 +221,31 @@ export function getAccountsWithLabels(state) { label: name, balance, }), - ) + ); } export function getCurrentAccountWithSendEtherInfo(state) { - const currentAddress = getSelectedAddress(state) - const accounts = accountsWithSendEtherInfoSelector(state) + const currentAddress = getSelectedAddress(state); + const accounts = accountsWithSendEtherInfoSelector(state); - return getAccountByAddress(accounts, currentAddress) + return getAccountByAddress(accounts, currentAddress); } export function getTargetAccountWithSendEtherInfo(state, targetAddress) { - const accounts = accountsWithSendEtherInfoSelector(state) - return getAccountByAddress(accounts, targetAddress) + const accounts = accountsWithSendEtherInfoSelector(state); + return getAccountByAddress(accounts, targetAddress); } export function getCurrentEthBalance(state) { - return getCurrentAccountWithSendEtherInfo(state).balance + return getCurrentAccountWithSendEtherInfo(state).balance; } export function getGasIsLoading(state) { - return state.appState.gasIsLoading + return state.appState.gasIsLoading; } export function getCurrentCurrency(state) { - return state.metamask.currentCurrency + return state.metamask.currentCurrency; } export function getTotalUnapprovedCount(state) { @@ -255,7 +255,7 @@ export function getTotalUnapprovedCount(state) { unapprovedDecryptMsgCount = 0, unapprovedEncryptionPublicKeyMsgCount = 0, unapprovedTypedMessagesCount = 0, - } = state.metamask + } = state.metamask; return ( unapprovedMsgCount + @@ -266,48 +266,48 @@ export function getTotalUnapprovedCount(state) { getUnapprovedTxCount(state) + getPermissionsRequestCount(state) + getSuggestedTokenCount(state) - ) + ); } function getUnapprovedTxCount(state) { - const { unapprovedTxs = {} } = state.metamask - return Object.keys(unapprovedTxs).length + const { unapprovedTxs = {} } = state.metamask; + return Object.keys(unapprovedTxs).length; } function getSuggestedTokenCount(state) { - const { suggestedTokens = {} } = state.metamask - return Object.keys(suggestedTokens).length + const { suggestedTokens = {} } = state.metamask; + return Object.keys(suggestedTokens).length; } export function getIsMainnet(state) { - const networkType = getNetworkIdentifier(state) - return networkType === MAINNET + const networkType = getNetworkIdentifier(state); + return networkType === MAINNET; } export function getPreferences({ metamask }) { - return metamask.preferences + return metamask.preferences; } export function getShouldShowFiat(state) { - const isMainNet = getIsMainnet(state) - const { showFiatInTestnets } = getPreferences(state) - return Boolean(isMainNet || showFiatInTestnets) + const isMainNet = getIsMainnet(state); + const { showFiatInTestnets } = getPreferences(state); + return Boolean(isMainNet || showFiatInTestnets); } export function getAdvancedInlineGasShown(state) { - return Boolean(state.metamask.featureFlags.advancedInlineGas) + return Boolean(state.metamask.featureFlags.advancedInlineGas); } export function getUseNonceField(state) { - return Boolean(state.metamask.useNonceField) + return Boolean(state.metamask.useNonceField); } export function getCustomNonceValue(state) { - return String(state.metamask.customNonceValue) + return String(state.metamask.customNonceValue); } export function getDomainMetadata(state) { - return state.metamask.domainMetadata + return state.metamask.domainMetadata; } export const getBackgroundMetaMetricState = (state) => { @@ -318,45 +318,45 @@ export const getBackgroundMetaMetricState = (state) => { numberOfTokens: getNumberOfTokens(state), numberOfAccounts: getNumberOfAccounts(state), participateInMetaMetrics: state.metamask.participateInMetaMetrics, - } -} + }; +}; export function getRpcPrefsForCurrentProvider(state) { - const { frequentRpcListDetail, provider } = state.metamask + const { frequentRpcListDetail, provider } = state.metamask; const selectRpcInfo = frequentRpcListDetail.find( (rpcInfo) => rpcInfo.rpcUrl === provider.rpcUrl, - ) - const { rpcPrefs = {} } = selectRpcInfo || {} - return rpcPrefs + ); + const { rpcPrefs = {} } = selectRpcInfo || {}; + return rpcPrefs; } export function getKnownMethodData(state, data) { if (!data) { - return null + return null; } - const prefixedData = addHexPrefix(data) - const fourBytePrefix = prefixedData.slice(0, 10) - const { knownMethodData } = state.metamask + const prefixedData = addHexPrefix(data); + const fourBytePrefix = prefixedData.slice(0, 10); + const { knownMethodData } = state.metamask; - return knownMethodData && knownMethodData[fourBytePrefix] + return knownMethodData && knownMethodData[fourBytePrefix]; } export function getFeatureFlags(state) { - return state.metamask.featureFlags + return state.metamask.featureFlags; } export function getOriginOfCurrentTab(state) { - return state.activeTab.origin + return state.activeTab.origin; } export function getIpfsGateway(state) { - return state.metamask.ipfsGateway + return state.metamask.ipfsGateway; } export function getUSDConversionRate(state) { - return state.metamask.usdConversionRate + return state.metamask.usdConversionRate; } export function getWeb3ShimUsageStateForOrigin(state, origin) { - return state.metamask.web3ShimUsageOrigins[origin] + return state.metamask.web3ShimUsageOrigins[origin]; } diff --git a/ui/app/selectors/send.js b/ui/app/selectors/send.js index 799215cc9..c7a2c870f 100644 --- a/ui/app/selectors/send.js +++ b/ui/app/selectors/send.js @@ -1,164 +1,166 @@ -import abi from 'human-standard-token-abi' -import { calcGasTotal } from '../pages/send/send.utils' +import abi from 'human-standard-token-abi'; +import { calcGasTotal } from '../pages/send/send.utils'; import { accountsWithSendEtherInfoSelector, getAddressBook, getSelectedAccount, getTargetAccount, getAveragePriceEstimateInHexWEI, -} from '.' +} from '.'; export function getBlockGasLimit(state) { - return state.metamask.currentBlockGasLimit + return state.metamask.currentBlockGasLimit; } export function getConversionRate(state) { - return state.metamask.conversionRate + return state.metamask.conversionRate; } export function getNativeCurrency(state) { - return state.metamask.nativeCurrency + return state.metamask.nativeCurrency; } export function getCurrentNetwork(state) { - return state.metamask.network + return state.metamask.network; } export function getGasLimit(state) { - return state.metamask.send.gasLimit || '0' + return state.metamask.send.gasLimit || '0'; } export function getGasPrice(state) { - return state.metamask.send.gasPrice || getAveragePriceEstimateInHexWEI(state) + return state.metamask.send.gasPrice || getAveragePriceEstimateInHexWEI(state); } export function getGasTotal(state) { - return calcGasTotal(getGasLimit(state), getGasPrice(state)) + return calcGasTotal(getGasLimit(state), getGasPrice(state)); } export function getPrimaryCurrency(state) { - const sendToken = getSendToken(state) - return sendToken?.symbol + const sendToken = getSendToken(state); + return sendToken?.symbol; } export function getSendToken(state) { - return state.metamask.send.token + return state.metamask.send.token; } export function getSendTokenAddress(state) { - return getSendToken(state)?.address + return getSendToken(state)?.address; } export function getSendTokenContract(state) { - const sendTokenAddress = getSendTokenAddress(state) - return sendTokenAddress ? global.eth.contract(abi).at(sendTokenAddress) : null + const sendTokenAddress = getSendTokenAddress(state); + return sendTokenAddress + ? global.eth.contract(abi).at(sendTokenAddress) + : null; } export function getSendAmount(state) { - return state.metamask.send.amount + return state.metamask.send.amount; } export function getSendHexData(state) { - return state.metamask.send.data + return state.metamask.send.data; } export function getSendHexDataFeatureFlagState(state) { - return state.metamask.featureFlags.sendHexData + return state.metamask.featureFlags.sendHexData; } export function getSendEditingTransactionId(state) { - return state.metamask.send.editingTransactionId + return state.metamask.send.editingTransactionId; } export function getSendErrors(state) { - return state.send.errors + return state.send.errors; } export function sendAmountIsInError(state) { - return Boolean(state.send.errors.amount) + return Boolean(state.send.errors.amount); } export function getSendFrom(state) { - return state.metamask.send.from + return state.metamask.send.from; } export function getSendFromBalance(state) { - const fromAccount = getSendFromObject(state) - return fromAccount.balance + const fromAccount = getSendFromObject(state); + return fromAccount.balance; } export function getSendFromObject(state) { - const fromAddress = getSendFrom(state) + const fromAddress = getSendFrom(state); return fromAddress ? getTargetAccount(state, fromAddress) - : getSelectedAccount(state) + : getSelectedAccount(state); } export function getSendMaxModeState(state) { - return state.metamask.send.maxModeOn + return state.metamask.send.maxModeOn; } export function getSendTo(state) { - return state.metamask.send.to + return state.metamask.send.to; } export function getSendToNickname(state) { - return state.metamask.send.toNickname + return state.metamask.send.toNickname; } export function getSendToAccounts(state) { - const fromAccounts = accountsWithSendEtherInfoSelector(state) - const addressBookAccounts = getAddressBook(state) - return [...fromAccounts, ...addressBookAccounts] + const fromAccounts = accountsWithSendEtherInfoSelector(state); + const addressBookAccounts = getAddressBook(state); + return [...fromAccounts, ...addressBookAccounts]; } export function getTokenBalance(state) { - return state.metamask.send.tokenBalance + return state.metamask.send.tokenBalance; } export function getSendEnsResolution(state) { - return state.metamask.send.ensResolution + return state.metamask.send.ensResolution; } export function getSendEnsResolutionError(state) { - return state.metamask.send.ensResolutionError + return state.metamask.send.ensResolutionError; } export function getUnapprovedTxs(state) { - return state.metamask.unapprovedTxs + return state.metamask.unapprovedTxs; } export function getQrCodeData(state) { - return state.appState.qrCodeData + return state.appState.qrCodeData; } export function getGasLoadingError(state) { - return state.send.errors.gasLoading + return state.send.errors.gasLoading; } export function gasFeeIsInError(state) { - return Boolean(state.send.errors.gasFee) + return Boolean(state.send.errors.gasFee); } export function getGasButtonGroupShown(state) { - return state.send.gasButtonGroupShown + return state.send.gasButtonGroupShown; } export function getTitleKey(state) { - const isEditing = Boolean(getSendEditingTransactionId(state)) - const isToken = Boolean(getSendToken(state)) + const isEditing = Boolean(getSendEditingTransactionId(state)); + const isToken = Boolean(getSendToken(state)); if (!getSendTo(state)) { - return 'addRecipient' + return 'addRecipient'; } if (isEditing) { - return 'edit' + return 'edit'; } else if (isToken) { - return 'sendTokens' + return 'sendTokens'; } - return 'sendETH' + return 'sendETH'; } export function isSendFormInError(state) { - return Object.values(getSendErrors(state)).some((n) => n) + return Object.values(getSendErrors(state)).some((n) => n); } diff --git a/ui/app/selectors/tests/confirm-transaction.test.js b/ui/app/selectors/tests/confirm-transaction.test.js index df8b3ae86..738000037 100644 --- a/ui/app/selectors/tests/confirm-transaction.test.js +++ b/ui/app/selectors/tests/confirm-transaction.test.js @@ -1,20 +1,20 @@ -import assert from 'assert' -import { TRANSACTION_CATEGORIES } from '../../../../shared/constants/transaction' +import assert from 'assert'; +import { TRANSACTION_CATEGORIES } from '../../../../shared/constants/transaction'; import { unconfirmedTransactionsCountSelector, sendTokenTokenAmountAndToAddressSelector, contractExchangeRateSelector, conversionRateSelector, -} from '../confirm-transaction' +} from '../confirm-transaction'; const getEthersArrayLikeFromObj = (obj) => { - const arr = [] + const arr = []; Object.keys(obj).forEach((key) => { - arr.push([obj[key]]) - arr[key] = obj[key] - }) - return arr -} + arr.push([obj[key]]); + arr[key] = obj[key]; + }); + return arr; +}; describe('Confirm Transaction Selector', function () { describe('unconfirmedTransactionsCountSelector', function () { @@ -33,12 +33,12 @@ describe('Confirm Transaction Selector', function () { unapprovedTypedMessagesCount: 1, network: 'test', }, - } + }; it('returns number of txs in unapprovedTxs state with the same network plus unapproved signing method counts', function () { - assert.strictEqual(unconfirmedTransactionsCountSelector(state), 4) - }) - }) + assert.strictEqual(unconfirmedTransactionsCountSelector(state), 4); + }); + }); describe('sendTokenTokenAmountAndToAddressSelector', function () { const state = { @@ -55,15 +55,15 @@ describe('Confirm Transaction Selector', function () { tokenSymbol: 'META', }, }, - } + }; it('returns token address and calculated token amount', function () { assert.deepStrictEqual(sendTokenTokenAmountAndToAddressSelector(state), { toAddress: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc', tokenAmount: '0.01', - }) - }) - }) + }); + }); + }); describe('contractExchangeRateSelector', function () { const state = { @@ -79,19 +79,19 @@ describe('Confirm Transaction Selector', function () { }, }, }, - } + }; it('returns contract exchange rate in metamask state based on confirm transaction txParams token recipient', function () { - assert.strictEqual(contractExchangeRateSelector(state), '10') - }) - }) + assert.strictEqual(contractExchangeRateSelector(state), '10'); + }); + }); describe('conversionRateSelector', function () { it('returns conversionRate from state', function () { const state = { metamask: { conversionRate: 556.12 }, - } - assert.strictEqual(conversionRateSelector(state), 556.12) - }) - }) -}) + }; + assert.strictEqual(conversionRateSelector(state), 556.12); + }); + }); +}); diff --git a/ui/app/selectors/tests/custom-gas.test.js b/ui/app/selectors/tests/custom-gas.test.js index cd5d9686e..e0a94eaf5 100644 --- a/ui/app/selectors/tests/custom-gas.test.js +++ b/ui/app/selectors/tests/custom-gas.test.js @@ -1,27 +1,27 @@ -import assert from 'assert' -import proxyquire from 'proxyquire' +import assert from 'assert'; +import proxyquire from 'proxyquire'; const { getCustomGasLimit, getCustomGasPrice, getRenderableBasicEstimateData, getRenderableEstimateDataForSmallButtonsFromGWEI, -} = proxyquire('../custom-gas', {}) +} = proxyquire('../custom-gas', {}); describe('custom-gas selectors', function () { describe('getCustomGasPrice()', function () { it('should return gas.customData.price', function () { - const mockState = { gas: { customData: { price: 'mockPrice' } } } - assert.strictEqual(getCustomGasPrice(mockState), 'mockPrice') - }) - }) + const mockState = { gas: { customData: { price: 'mockPrice' } } }; + assert.strictEqual(getCustomGasPrice(mockState), 'mockPrice'); + }); + }); describe('getCustomGasLimit()', function () { it('should return gas.customData.limit', function () { - const mockState = { gas: { customData: { limit: 'mockLimit' } } } - assert.strictEqual(getCustomGasLimit(mockState), 'mockLimit') - }) - }) + const mockState = { gas: { customData: { limit: 'mockLimit' } } }; + assert.strictEqual(getCustomGasLimit(mockState), 'mockLimit'); + }); + }); describe('getRenderableBasicEstimateData()', function () { const tests = [ @@ -260,7 +260,7 @@ describe('custom-gas selectors', function () { }, }, }, - ] + ]; it('should return renderable data about basic estimates', function () { tests.forEach((test) => { assert.deepStrictEqual( @@ -270,10 +270,10 @@ describe('custom-gas selectors', function () { test.useFastestButtons, ), test.expectedResult, - ) - }) - }) - }) + ); + }); + }); + }); describe('getRenderableEstimateDataForSmallButtonsFromGWEI()', function () { const tests = [ @@ -509,14 +509,14 @@ describe('custom-gas selectors', function () { }, }, }, - ] + ]; it('should return renderable data about basic estimates appropriate for buttons with less info', function () { tests.forEach((test) => { assert.deepStrictEqual( getRenderableEstimateDataForSmallButtonsFromGWEI(test.mockState), test.expectedResult, - ) - }) - }) - }) -}) + ); + }); + }); + }); +}); diff --git a/ui/app/selectors/tests/permissions.test.js b/ui/app/selectors/tests/permissions.test.js index 4750afa60..c9d303603 100644 --- a/ui/app/selectors/tests/permissions.test.js +++ b/ui/app/selectors/tests/permissions.test.js @@ -1,9 +1,9 @@ -import assert from 'assert' +import assert from 'assert'; import { getConnectedDomainsForSelectedAddress, getOrderedConnectedAccountsForActiveTab, getPermissionsForActiveTab, -} from '../permissions' +} from '../permissions'; describe('selectors', function () { describe('getConnectedDomainsForSelectedAddress', function () { @@ -62,8 +62,8 @@ describe('selectors', function () { }, }, }, - } - const extensionId = undefined + }; + const extensionId = undefined; assert.deepStrictEqual(getConnectedDomainsForSelectedAddress(mockState), [ { extensionId, @@ -79,8 +79,8 @@ describe('selectors', function () { origin: 'https://remix.ethereum.org', host: 'remix.ethereum.org', }, - ]) - }) + ]); + }); it('should return the list of connected domains when there are 2 connected accounts', function () { const mockState = { @@ -140,8 +140,8 @@ describe('selectors', function () { }, }, }, - } - const extensionId = undefined + }; + const extensionId = undefined; assert.deepStrictEqual(getConnectedDomainsForSelectedAddress(mockState), [ { extensionId, @@ -150,9 +150,9 @@ describe('selectors', function () { origin: 'https://remix.ethereum.org', host: 'remix.ethereum.com', }, - ]) - }) - }) + ]); + }); + }); describe('getConnectedAccountsForActiveTab', function () { const mockState = { @@ -276,7 +276,7 @@ describe('selectors', function () { }, }, }, - } + }; it('should return connected accounts sorted by last selected, then by keyring controller order', function () { assert.deepStrictEqual( @@ -311,9 +311,9 @@ describe('selectors', function () { lastActive: 1586359844192, }, ], - ) - }) - }) + ); + }); + }); describe('getPermissionsForActiveTab', function () { const mockState = { @@ -415,14 +415,14 @@ describe('selectors', function () { }, }, }, - } + }; it('should return a list of permissions strings', function () { assert.deepStrictEqual(getPermissionsForActiveTab(mockState), [ { key: 'eth_accounts', }, - ]) - }) - }) -}) + ]); + }); + }); +}); diff --git a/ui/app/selectors/tests/selectors.test.js b/ui/app/selectors/tests/selectors.test.js index be03752a9..46058fe12 100644 --- a/ui/app/selectors/tests/selectors.test.js +++ b/ui/app/selectors/tests/selectors.test.js @@ -1,6 +1,6 @@ -import assert from 'assert' -import * as selectors from '../selectors' -import mockState from '../../../../test/data/mock-state.json' +import assert from 'assert'; +import * as selectors from '../selectors'; +import mockState from '../../../../test/data/mock-state.json'; describe('Selectors', function () { describe('#getSelectedAddress', function () { @@ -8,43 +8,43 @@ describe('Selectors', function () { assert.strictEqual( selectors.getSelectedAddress({ metamask: {} }), undefined, - ) - }) + ); + }); it('returns selectedAddress', function () { - const selectedAddress = '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc' + const selectedAddress = '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc'; assert.strictEqual( selectors.getSelectedAddress({ metamask: { selectedAddress } }), selectedAddress, - ) - }) - }) + ); + }); + }); it('returns selected identity', function () { assert.deepStrictEqual(selectors.getSelectedIdentity(mockState), { address: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc', name: 'Test Account', - }) - }) + }); + }); it('returns selected account', function () { - const account = selectors.getSelectedAccount(mockState) - assert.strictEqual(account.balance, '0x0') + const account = selectors.getSelectedAccount(mockState); + assert.strictEqual(account.balance, '0x0'); assert.strictEqual( account.address, '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc', - ) - }) + ); + }); describe('#getTokenExchangeRates', function () { it('returns token exchange rates', function () { - const tokenExchangeRates = selectors.getTokenExchangeRates(mockState) + const tokenExchangeRates = selectors.getTokenExchangeRates(mockState); assert.deepStrictEqual(tokenExchangeRates, { '0x108cf70c7d384c552f42c07c41c0e1e46d77ea0d': 0.00039345803819379796, '0xd8f6a2ffb0fc5952d16c9768b71cfd35b6399aa5': 0.00008189274407698049, - }) - }) - }) + }); + }); + }); describe('#getAddressBook', function () { it('should return the address book', function () { @@ -56,47 +56,47 @@ describe('Selectors', function () { memo: '', name: 'Address Book Account 1', }, - ]) - }) - }) + ]); + }); + }); it('returns accounts with balance, address, and name from identity and accounts in state', function () { const accountsWithSendEther = selectors.accountsWithSendEtherInfoSelector( mockState, - ) - assert.strictEqual(accountsWithSendEther.length, 2) - assert.strictEqual(accountsWithSendEther[0].balance, '0x0') + ); + assert.strictEqual(accountsWithSendEther.length, 2); + assert.strictEqual(accountsWithSendEther[0].balance, '0x0'); assert.strictEqual( accountsWithSendEther[0].address, '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc', - ) - assert.strictEqual(accountsWithSendEther[0].name, 'Test Account') - }) + ); + assert.strictEqual(accountsWithSendEther[0].name, 'Test Account'); + }); it('returns selected account with balance, address, and name from accountsWithSendEtherInfoSelector', function () { const currentAccountwithSendEther = selectors.getCurrentAccountWithSendEtherInfo( mockState, - ) - assert.strictEqual(currentAccountwithSendEther.balance, '0x0') + ); + assert.strictEqual(currentAccountwithSendEther.balance, '0x0'); assert.strictEqual( currentAccountwithSendEther.address, '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc', - ) - assert.strictEqual(currentAccountwithSendEther.name, 'Test Account') - }) + ); + assert.strictEqual(currentAccountwithSendEther.name, 'Test Account'); + }); it('#getGasIsLoading', function () { - const gasIsLoading = selectors.getGasIsLoading(mockState) - assert.strictEqual(gasIsLoading, false) - }) + const gasIsLoading = selectors.getGasIsLoading(mockState); + assert.strictEqual(gasIsLoading, false); + }); it('#getCurrentCurrency', function () { - const currentCurrency = selectors.getCurrentCurrency(mockState) - assert.strictEqual(currentCurrency, 'usd') - }) + const currentCurrency = selectors.getCurrentCurrency(mockState); + assert.strictEqual(currentCurrency, 'usd'); + }); it('#getTotalUnapprovedCount', function () { - const totalUnapprovedCount = selectors.getTotalUnapprovedCount(mockState) - assert.strictEqual(totalUnapprovedCount, 1) - }) -}) + const totalUnapprovedCount = selectors.getTotalUnapprovedCount(mockState); + assert.strictEqual(totalUnapprovedCount, 1); + }); +}); diff --git a/ui/app/selectors/tests/send-selectors-test-data.js b/ui/app/selectors/tests/send-selectors-test-data.js index bfa015e58..19a91e9d3 100644 --- a/ui/app/selectors/tests/send-selectors-test-data.js +++ b/ui/app/selectors/tests/send-selectors-test-data.js @@ -1,4 +1,4 @@ -import { TRANSACTION_STATUSES } from '../../../../shared/constants/transaction' +import { TRANSACTION_STATUSES } from '../../../../shared/constants/transaction'; const state = { metamask: { @@ -214,6 +214,6 @@ const state = { toDropdownOpen: false, errors: { someError: null }, }, -} +}; -export default state +export default state; diff --git a/ui/app/selectors/tests/send.test.js b/ui/app/selectors/tests/send.test.js index eeb080e3b..2dc9598ac 100644 --- a/ui/app/selectors/tests/send.test.js +++ b/ui/app/selectors/tests/send.test.js @@ -1,10 +1,10 @@ -import assert from 'assert' -import sinon from 'sinon' +import assert from 'assert'; +import sinon from 'sinon'; import { accountsWithSendEtherInfoSelector, getCurrentAccountWithSendEtherInfo, -} from '..' -import { TRANSACTION_STATUSES } from '../../../../shared/constants/transaction' +} from '..'; +import { TRANSACTION_STATUSES } from '../../../../shared/constants/transaction'; import { getBlockGasLimit, getConversionRate, @@ -34,22 +34,22 @@ import { getGasButtonGroupShown, getTitleKey, isSendFormInError, -} from '../send' -import mockState from './send-selectors-test-data' +} from '../send'; +import mockState from './send-selectors-test-data'; describe('send selectors', function () { - const tempGlobalEth = { ...global.eth } + const tempGlobalEth = { ...global.eth }; beforeEach(function () { global.eth = { contract: sinon.stub().returns({ at: (address) => `mockAt:${address}`, }), - } - }) + }; + }); afterEach(function () { - global.eth = tempGlobalEth - }) + global.eth = tempGlobalEth; + }); describe('accountsWithSendEtherInfoSelector()', function () { it('should return an array of account objects with name info from identities', function () { @@ -82,21 +82,21 @@ describe('send selectors', function () { address: '0xd85a4b6a394794842887b8284293d69163007bbb', name: 'Send Account 4', }, - ]) - }) - }) + ]); + }); + }); describe('getBlockGasLimit', function () { it('should return the current block gas limit', function () { - assert.deepStrictEqual(getBlockGasLimit(mockState), '0x4c1878') - }) - }) + assert.deepStrictEqual(getBlockGasLimit(mockState), '0x4c1878'); + }); + }); describe('getConversionRate()', function () { it('should return the eth conversion rate', function () { - assert.deepStrictEqual(getConversionRate(mockState), 1200.88200327) - }) - }) + assert.deepStrictEqual(getConversionRate(mockState), 1200.88200327); + }); + }); describe('getCurrentAccountWithSendEtherInfo()', function () { it('should return the currently selected account with identity info', function () { @@ -106,39 +106,39 @@ describe('send selectors', function () { nonce: '0x0', address: '0xd85a4b6a394794842887b8284293d69163007bbb', name: 'Send Account 4', - }) - }) - }) + }); + }); + }); describe('getNativeCurrency()', function () { it('should return the ticker symbol of the selected network', function () { - assert.strictEqual(getNativeCurrency(mockState), 'ETH') - }) - }) + assert.strictEqual(getNativeCurrency(mockState), 'ETH'); + }); + }); describe('getCurrentNetwork()', function () { it('should return the id of the currently selected network', function () { - assert.strictEqual(getCurrentNetwork(mockState), '3') - }) - }) + assert.strictEqual(getCurrentNetwork(mockState), '3'); + }); + }); describe('getGasLimit()', function () { it('should return the send.gasLimit', function () { - assert.strictEqual(getGasLimit(mockState), '0xFFFF') - }) - }) + assert.strictEqual(getGasLimit(mockState), '0xFFFF'); + }); + }); describe('getGasPrice()', function () { it('should return the send.gasPrice', function () { - assert.strictEqual(getGasPrice(mockState), '0xaa') - }) - }) + assert.strictEqual(getGasPrice(mockState), '0xaa'); + }); + }); describe('getGasTotal()', function () { it('should return the send.gasTotal', function () { - assert.strictEqual(getGasTotal(mockState), 'a9ff56') - }) - }) + assert.strictEqual(getGasTotal(mockState), 'a9ff56'); + }); + }); describe('getPrimaryCurrency()', function () { it('should return the symbol of the send token', function () { @@ -147,9 +147,9 @@ describe('send selectors', function () { metamask: { send: { token: { symbol: 'DEF' } } }, }), 'DEF', - ) - }) - }) + ); + }); + }); describe('getSendToken()', function () { it('should return the current send token if set', function () { @@ -170,9 +170,9 @@ describe('send selectors', function () { decimals: 4, symbol: 'DEF', }, - ) - }) - }) + ); + }); + }); describe('getSendTokenContract()', function () { it('should return the contract at the send token address', function () { @@ -189,55 +189,55 @@ describe('send selectors', function () { }, }), 'mockAt:0x8d6b81208414189a58339873ab429b6c47ab92d3', - ) - }) + ); + }); it('should return null if send token is not set', function () { - const modifiedMetamaskState = { ...mockState.metamask, send: {} } + const modifiedMetamaskState = { ...mockState.metamask, send: {} }; assert.strictEqual( getSendTokenContract({ ...mockState, metamask: modifiedMetamaskState }), null, - ) - }) - }) + ); + }); + }); describe('getSendAmount()', function () { it('should return the send.amount', function () { - assert.strictEqual(getSendAmount(mockState), '0x080') - }) - }) + assert.strictEqual(getSendAmount(mockState), '0x080'); + }); + }); describe('getSendEditingTransactionId()', function () { it('should return the send.editingTransactionId', function () { - assert.strictEqual(getSendEditingTransactionId(mockState), 97531) - }) - }) + assert.strictEqual(getSendEditingTransactionId(mockState), 97531); + }); + }); describe('getSendErrors()', function () { it('should return the send.errors', function () { - assert.deepStrictEqual(getSendErrors(mockState), { someError: null }) - }) - }) + assert.deepStrictEqual(getSendErrors(mockState), { someError: null }); + }); + }); describe('getSendHexDataFeatureFlagState()', function () { it('should return the sendHexData feature flag state', function () { - assert.deepStrictEqual(getSendHexDataFeatureFlagState(mockState), true) - }) - }) + assert.deepStrictEqual(getSendHexDataFeatureFlagState(mockState), true); + }); + }); describe('getSendFrom()', function () { it('should return the send.from', function () { assert.deepStrictEqual( getSendFrom(mockState), '0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb', - ) - }) - }) + ); + }); + }); describe('getSendFromBalance()', function () { it('should get the send.from balance if it exists', function () { - assert.strictEqual(getSendFromBalance(mockState), '0x37452b1315889f80') - }) + assert.strictEqual(getSendFromBalance(mockState), '0x37452b1315889f80'); + }); it('should get the selected account balance if the send.from does not exist', function () { const editedMockState = { @@ -247,10 +247,10 @@ describe('send selectors', function () { from: null, }, }, - } - assert.strictEqual(getSendFromBalance(editedMockState), '0x0') - }) - }) + }; + assert.strictEqual(getSendFromBalance(editedMockState), '0x0'); + }); + }); describe('getSendFromObject()', function () { it('should return send.from if it exists', function () { @@ -259,8 +259,8 @@ describe('send selectors', function () { balance: '0x37452b1315889f80', code: '0x', nonce: '0xa', - }) - }) + }); + }); it('should return the current account if send.from does not exist', function () { const editedMockState = { @@ -270,27 +270,27 @@ describe('send selectors', function () { from: null, }, }, - } + }; assert.deepStrictEqual(getSendFromObject(editedMockState), { code: '0x', balance: '0x0', nonce: '0x0', address: '0xd85a4b6a394794842887b8284293d69163007bbb', - }) - }) - }) + }); + }); + }); describe('getSendMaxModeState()', function () { it('should return send.maxModeOn', function () { - assert.strictEqual(getSendMaxModeState(mockState), false) - }) - }) + assert.strictEqual(getSendMaxModeState(mockState), false); + }); + }); describe('getSendTo()', function () { it('should return send.to', function () { - assert.strictEqual(getSendTo(mockState), '0x987fedabc') - }) - }) + assert.strictEqual(getSendTo(mockState), '0x987fedabc'); + }); + }); describe('getSendToAccounts()', function () { it('should return an array including all the users accounts and the address book', function () { @@ -328,15 +328,15 @@ describe('send selectors', function () { name: 'Address Book Account 1', chainId: '0x3', }, - ]) - }) - }) + ]); + }); + }); describe('getTokenBalance()', function () { it('should', function () { - assert.strictEqual(getTokenBalance(mockState), 3434) - }) - }) + assert.strictEqual(getTokenBalance(mockState), 3434); + }); + }); describe('getUnapprovedTxs()', function () { it('should return the unapproved txs', function () { @@ -360,9 +360,9 @@ describe('send selectors', function () { maxCost: 'de234b52e4a0800', gasPrice: '4a817c800', }, - }) - }) - }) + }); + }); + }); describe('send-amount-row selectors', function () { describe('sendAmountIsInError()', function () { @@ -373,10 +373,10 @@ describe('send selectors', function () { amount: 'abc', }, }, - } + }; - assert.strictEqual(sendAmountIsInError(state), true) - }) + assert.strictEqual(sendAmountIsInError(state), true); + }); it('should return false if send.errors.amount is falsy', function () { const state = { @@ -385,12 +385,12 @@ describe('send selectors', function () { amount: null, }, }, - } + }; - assert.strictEqual(sendAmountIsInError(state), false) - }) - }) - }) + assert.strictEqual(sendAmountIsInError(state), false); + }); + }); + }); describe('send-gas-row selectors', function () { describe('getGasLoadingError()', function () { @@ -401,11 +401,11 @@ describe('send selectors', function () { gasLoading: 'abc', }, }, - } + }; - assert.strictEqual(getGasLoadingError(state), 'abc') - }) - }) + assert.strictEqual(getGasLoadingError(state), 'abc'); + }); + }); describe('gasFeeIsInError()', function () { it('should return true if send.errors.gasFee is truthy', function () { @@ -415,10 +415,10 @@ describe('send selectors', function () { gasFee: 'def', }, }, - } + }; - assert.strictEqual(gasFeeIsInError(state), true) - }) + assert.strictEqual(gasFeeIsInError(state), true); + }); it('should return false send.errors.gasFee is falsely', function () { const state = { @@ -427,11 +427,11 @@ describe('send selectors', function () { gasFee: null, }, }, - } + }; - assert.strictEqual(gasFeeIsInError(state), false) - }) - }) + assert.strictEqual(gasFeeIsInError(state), false); + }); + }); describe('getGasButtonGroupShown()', function () { it('should return send.gasButtonGroupShown', function () { @@ -439,12 +439,12 @@ describe('send selectors', function () { send: { gasButtonGroupShown: 'foobar', }, - } + }; - assert.strictEqual(getGasButtonGroupShown(state), 'foobar') - }) - }) - }) + assert.strictEqual(getGasButtonGroupShown(state), 'foobar'); + }); + }); + }); describe('send-header selectors', function () { const getMetamaskSendMockState = (send) => { @@ -452,16 +452,16 @@ describe('send selectors', function () { metamask: { send: { ...send }, }, - } - } + }; + }; describe('getTitleKey()', function () { it('should return the correct key when "to" is empty', function () { assert.strictEqual( getTitleKey(getMetamaskSendMockState({})), 'addRecipient', - ) - }) + ); + }); it('should return the correct key when getSendEditingTransactionId is truthy', function () { assert.strictEqual( @@ -473,8 +473,8 @@ describe('send selectors', function () { }), ), 'edit', - ) - }) + ); + }); it('should return the correct key when getSendEditingTransactionId is falsy and getSendToken is truthy', function () { assert.strictEqual( @@ -486,8 +486,8 @@ describe('send selectors', function () { }), ), 'sendTokens', - ) - }) + ); + }); it('should return the correct key when getSendEditingTransactionId is falsy and getSendToken is falsy', function () { assert.strictEqual( @@ -499,17 +499,17 @@ describe('send selectors', function () { }), ), 'sendETH', - ) - }) - }) - }) + ); + }); + }); + }); describe('send-footer selectors', function () { const getSendMockState = (send) => { return { send: { ...send }, - } - } + }; + }; describe('isSendFormInError()', function () { it('should return true if any of the values of the object returned by getSendErrors are truthy', function () { @@ -520,8 +520,8 @@ describe('send selectors', function () { }), ), true, - ) - }) + ); + }); it('should return false if all of the values of the object returned by getSendErrors are falsy', function () { assert.strictEqual( @@ -531,7 +531,7 @@ describe('send selectors', function () { }), ), false, - ) + ); assert.strictEqual( isSendFormInError( getSendMockState({ @@ -539,8 +539,8 @@ describe('send selectors', function () { }), ), false, - ) - }) - }) - }) -}) + ); + }); + }); + }); +}); diff --git a/ui/app/selectors/tests/transactions.test.js b/ui/app/selectors/tests/transactions.test.js index 593055392..c38dd4d30 100644 --- a/ui/app/selectors/tests/transactions.test.js +++ b/ui/app/selectors/tests/transactions.test.js @@ -1,5 +1,5 @@ -import { strict as assert } from 'assert' -import { TRANSACTION_STATUSES } from '../../../../shared/constants/transaction' +import { strict as assert } from 'assert'; +import { TRANSACTION_STATUSES } from '../../../../shared/constants/transaction'; import { unapprovedMessagesSelector, transactionsSelector, @@ -7,7 +7,7 @@ import { nonceSortedPendingTransactionsSelector, nonceSortedCompletedTransactionsSelector, submittedPendingTransactionsSelector, -} from '../transactions' +} from '../transactions'; describe('Transaction Selectors', function () { describe('unapprovedMessagesSelector', function () { @@ -22,7 +22,7 @@ describe('Transaction Selectors', function () { time: 1, status: TRANSACTION_STATUSES.UNAPPROVED, type: 'eth_sign', - } + }; const state = { metamask: { @@ -30,13 +30,13 @@ describe('Transaction Selectors', function () { 1: msg, }, }, - } + }; - const msgSelector = unapprovedMessagesSelector(state) + const msgSelector = unapprovedMessagesSelector(state); - assert(Array.isArray(msgSelector)) - assert.deepStrictEqual(msgSelector, [msg]) - }) + assert(Array.isArray(msgSelector)); + assert.deepStrictEqual(msgSelector, [msg]); + }); it('returns personal sign from unapprovedPersonalMsgsSelector', function () { const msg = { @@ -49,7 +49,7 @@ describe('Transaction Selectors', function () { time: 1, status: TRANSACTION_STATUSES.UNAPPROVED, type: 'personal_sign', - } + }; const state = { metamask: { @@ -57,13 +57,13 @@ describe('Transaction Selectors', function () { 1: msg, }, }, - } + }; - const msgSelector = unapprovedMessagesSelector(state) + const msgSelector = unapprovedMessagesSelector(state); - assert(Array.isArray(msgSelector)) - assert.deepStrictEqual(msgSelector, [msg]) - }) + assert(Array.isArray(msgSelector)); + assert.deepStrictEqual(msgSelector, [msg]); + }); it('returns typed message from unapprovedTypedMessagesSelector', function () { const msg = { @@ -77,7 +77,7 @@ describe('Transaction Selectors', function () { time: 1, status: TRANSACTION_STATUSES.UNAPPROVED, type: 'eth_signTypedData', - } + }; const state = { metamask: { @@ -85,14 +85,14 @@ describe('Transaction Selectors', function () { 1: msg, }, }, - } + }; - const msgSelector = unapprovedMessagesSelector(state) + const msgSelector = unapprovedMessagesSelector(state); - assert(Array.isArray(msgSelector)) - assert.deepStrictEqual(msgSelector, [msg]) - }) - }) + assert(Array.isArray(msgSelector)); + assert.deepStrictEqual(msgSelector, [msg]); + }); + }); describe('transactionsSelector', function () { it('selects the currentNetworkTxList', function () { @@ -124,18 +124,18 @@ describe('Transaction Selectors', function () { }, ], }, - } + }; const orderedTxList = state.metamask.currentNetworkTxList.sort( (a, b) => b.time - a.time, - ) + ); - const selectedTx = transactionsSelector(state) + const selectedTx = transactionsSelector(state); - assert(Array.isArray(selectedTx)) - assert.deepStrictEqual(selectedTx, orderedTxList) - }) - }) + assert(Array.isArray(selectedTx)); + assert.deepStrictEqual(selectedTx, orderedTxList); + }); + }); describe('nonceSortedTransactionsSelector', function () { it('returns transaction group nonce sorted tx from from selectedTxList wit', function () { @@ -147,7 +147,7 @@ describe('Transaction Selectors', function () { to: '0xRecipient', nonce: '0x0', }, - } + }; const tx2 = { id: 1, @@ -157,7 +157,7 @@ describe('Transaction Selectors', function () { to: '0xRecipient', nonce: '0x1', }, - } + }; const state = { metamask: { @@ -170,7 +170,7 @@ describe('Transaction Selectors', function () { }, currentNetworkTxList: [tx1, tx2], }, - } + }; const expectedResult = [ { @@ -189,14 +189,14 @@ describe('Transaction Selectors', function () { hasRetried: false, hasCancelled: false, }, - ] + ]; assert.deepStrictEqual( nonceSortedTransactionsSelector(state), expectedResult, - ) - }) - }) + ); + }); + }); describe('Sorting Transactions Selectors', function () { const submittedTx = { @@ -208,7 +208,7 @@ describe('Transaction Selectors', function () { nonce: '0x0', }, status: TRANSACTION_STATUSES.SUBMITTED, - } + }; const unapprovedTx = { id: 1, @@ -219,7 +219,7 @@ describe('Transaction Selectors', function () { nonce: '0x1', }, status: TRANSACTION_STATUSES.UNAPPROVED, - } + }; const approvedTx = { id: 2, @@ -230,7 +230,7 @@ describe('Transaction Selectors', function () { nonce: '0x2', }, status: TRANSACTION_STATUSES.APPROVED, - } + }; const confirmedTx = { id: 3, @@ -241,7 +241,7 @@ describe('Transaction Selectors', function () { nonce: '0x3', }, status: TRANSACTION_STATUSES.CONFIRMED, - } + }; const state = { metamask: { @@ -259,7 +259,7 @@ describe('Transaction Selectors', function () { confirmedTx, ], }, - } + }; it('nonceSortedPendingTransactionsSelector', function () { const expectedResult = [ @@ -287,13 +287,13 @@ describe('Transaction Selectors', function () { hasRetried: false, hasCancelled: false, }, - ] + ]; assert.deepStrictEqual( nonceSortedPendingTransactionsSelector(state), expectedResult, - ) - }) + ); + }); it('nonceSortedCompletedTransactionsSelector', function () { const expectedResult = [ @@ -305,20 +305,20 @@ describe('Transaction Selectors', function () { hasRetried: false, hasCancelled: false, }, - ] + ]; assert.deepStrictEqual( nonceSortedCompletedTransactionsSelector(state), expectedResult, - ) - }) + ); + }); it('submittedPendingTransactionsSelector', function () { - const expectedResult = [submittedTx] + const expectedResult = [submittedTx]; assert.deepStrictEqual( submittedPendingTransactionsSelector(state), expectedResult, - ) - }) - }) -}) + ); + }); + }); +}); diff --git a/ui/app/selectors/transactions.js b/ui/app/selectors/transactions.js index 9436d56c1..f9a8539d6 100644 --- a/ui/app/selectors/transactions.js +++ b/ui/app/selectors/transactions.js @@ -1,42 +1,42 @@ -import { createSelector } from 'reselect' +import { createSelector } from 'reselect'; import { PRIORITY_STATUS_HASH, PENDING_STATUS_HASH, -} from '../helpers/constants/transactions' -import { hexToDecimal } from '../helpers/utils/conversions.util' -import txHelper from '../../lib/tx-helper' +} from '../helpers/constants/transactions'; +import { hexToDecimal } from '../helpers/utils/conversions.util'; +import txHelper from '../../lib/tx-helper'; import { TRANSACTION_CATEGORIES, TRANSACTION_STATUSES, TRANSACTION_TYPES, -} from '../../../shared/constants/transaction' -import { getSelectedAddress } from '.' +} from '../../../shared/constants/transaction'; +import { getSelectedAddress } from '.'; export const incomingTxListSelector = (state) => { - const { showIncomingTransactions } = state.metamask.featureFlags + const { showIncomingTransactions } = state.metamask.featureFlags; if (!showIncomingTransactions) { - return [] + return []; } - const { network } = state.metamask - const selectedAddress = getSelectedAddress(state) + const { network } = state.metamask; + const selectedAddress = getSelectedAddress(state); return Object.values(state.metamask.incomingTransactions).filter( ({ metamaskNetworkId, txParams }) => txParams.to === selectedAddress && metamaskNetworkId === network, - ) -} -export const unapprovedMsgsSelector = (state) => state.metamask.unapprovedMsgs + ); +}; +export const unapprovedMsgsSelector = (state) => state.metamask.unapprovedMsgs; export const currentNetworkTxListSelector = (state) => - state.metamask.currentNetworkTxList + state.metamask.currentNetworkTxList; export const unapprovedPersonalMsgsSelector = (state) => - state.metamask.unapprovedPersonalMsgs + state.metamask.unapprovedPersonalMsgs; export const unapprovedDecryptMsgsSelector = (state) => - state.metamask.unapprovedDecryptMsgs + state.metamask.unapprovedDecryptMsgs; export const unapprovedEncryptionPublicKeyMsgsSelector = (state) => - state.metamask.unapprovedEncryptionPublicKeyMsgs + state.metamask.unapprovedEncryptionPublicKeyMsgs; export const unapprovedTypedMessagesSelector = (state) => - state.metamask.unapprovedTypedMessages -export const networkSelector = (state) => state.metamask.network + state.metamask.unapprovedTypedMessages; +export const networkSelector = (state) => state.metamask.network; export const selectedAddressTxListSelector = createSelector( getSelectedAddress, @@ -44,9 +44,9 @@ export const selectedAddressTxListSelector = createSelector( (selectedAddress, transactions = []) => { return transactions.filter( ({ txParams }) => txParams.from === selectedAddress, - ) + ); }, -) +); export const unapprovedMessagesSelector = createSelector( unapprovedMsgsSelector, @@ -72,25 +72,25 @@ export const unapprovedMessagesSelector = createSelector( unapprovedTypedMessages, network, ) || [], -) +); export const transactionSubSelector = createSelector( unapprovedMessagesSelector, incomingTxListSelector, (unapprovedMessages = [], incomingTxList = []) => { - return unapprovedMessages.concat(incomingTxList) + return unapprovedMessages.concat(incomingTxList); }, -) +); export const transactionsSelector = createSelector( transactionSubSelector, selectedAddressTxListSelector, (subSelectorTxList = [], selectedAddressTxList = []) => { - const txsToRender = selectedAddressTxList.concat(subSelectorTxList) + const txsToRender = selectedAddressTxList.concat(subSelectorTxList); - return txsToRender.sort((a, b) => b.time - a.time) + return txsToRender.sort((a, b) => b.time - a.time); }, -) +); /** * @name insertOrderedNonce @@ -102,19 +102,19 @@ export const transactionsSelector = createSelector( * @returns {string[]} */ const insertOrderedNonce = (nonces, nonceToInsert) => { - let insertIndex = nonces.length + let insertIndex = nonces.length; for (let i = 0; i < nonces.length; i++) { - const nonce = nonces[i] + const nonce = nonces[i]; if (Number(hexToDecimal(nonce)) > Number(hexToDecimal(nonceToInsert))) { - insertIndex = i - break + insertIndex = i; + break; } } - nonces.splice(insertIndex, 0, nonceToInsert) -} + nonces.splice(insertIndex, 0, nonceToInsert); +}; /** * @name insertTransactionByTime @@ -126,21 +126,21 @@ const insertOrderedNonce = (nonces, nonceToInsert) => { * @returns {Object[]} */ const insertTransactionByTime = (transactions, transaction) => { - const { time } = transaction + const { time } = transaction; - let insertIndex = transactions.length + let insertIndex = transactions.length; for (let i = 0; i < transactions.length; i++) { - const tx = transactions[i] + const tx = transactions[i]; if (tx.time > time) { - insertIndex = i - break + insertIndex = i; + break; } } - transactions.splice(insertIndex, 0, transaction) -} + transactions.splice(insertIndex, 0, transaction); +}; /** * Contains transactions and properties associated with those transactions of the same nonce. @@ -166,22 +166,22 @@ const insertTransactionByTime = (transactions, transaction) => { const insertTransactionGroupByTime = (transactionGroups, transactionGroup) => { const { primaryTransaction: { time: groupToInsertTime } = {}, - } = transactionGroup + } = transactionGroup; - let insertIndex = transactionGroups.length + let insertIndex = transactionGroups.length; for (let i = 0; i < transactionGroups.length; i++) { - const txGroup = transactionGroups[i] - const { primaryTransaction: { time } = {} } = txGroup + const txGroup = transactionGroups[i]; + const { primaryTransaction: { time } = {} } = txGroup; if (time > groupToInsertTime) { - insertIndex = i - break + insertIndex = i; + break; } } - transactionGroups.splice(insertIndex, 0, transactionGroup) -} + transactionGroups.splice(insertIndex, 0, transactionGroup); +}; /** * @name mergeNonNonceTransactionGroups @@ -198,9 +198,9 @@ const mergeNonNonceTransactionGroups = ( nonNonceTransactionGroups, ) => { nonNonceTransactionGroups.forEach((transactionGroup) => { - insertTransactionGroupByTime(orderedTransactionGroups, transactionGroup) - }) -} + insertTransactionGroupByTime(orderedTransactionGroups, transactionGroup); + }); +}; /** * @name nonceSortedTransactionsSelector @@ -210,10 +210,10 @@ const mergeNonNonceTransactionGroups = ( export const nonceSortedTransactionsSelector = createSelector( transactionsSelector, (transactions = []) => { - const unapprovedTransactionGroups = [] - const incomingTransactionGroups = [] - const orderedNonces = [] - const nonceToTransactionsMap = {} + const unapprovedTransactionGroups = []; + const incomingTransactionGroups = []; + const orderedNonces = []; + const nonceToTransactionsMap = {}; transactions.forEach((transaction) => { const { @@ -222,7 +222,7 @@ export const nonceSortedTransactionsSelector = createSelector( type, time: txTime, transactionCategory, - } = transaction + } = transaction; if ( typeof nonce === 'undefined' || @@ -234,30 +234,30 @@ export const nonceSortedTransactionsSelector = createSelector( primaryTransaction: transaction, hasRetried: false, hasCancelled: false, - } + }; if (transactionCategory === TRANSACTION_CATEGORIES.INCOMING) { - incomingTransactionGroups.push(transactionGroup) + incomingTransactionGroups.push(transactionGroup); } else { insertTransactionGroupByTime( unapprovedTransactionGroups, transactionGroup, - ) + ); } } else if (nonce in nonceToTransactionsMap) { - const nonceProps = nonceToTransactionsMap[nonce] - insertTransactionByTime(nonceProps.transactions, transaction) + const nonceProps = nonceToTransactionsMap[nonce]; + insertTransactionByTime(nonceProps.transactions, transaction); const { primaryTransaction: { time: primaryTxTime = 0 } = {}, - } = nonceProps + } = nonceProps; const previousPrimaryIsNetworkFailure = nonceProps.primaryTransaction.status === TRANSACTION_STATUSES.FAILED && - nonceProps.primaryTransaction?.txReceipt?.status !== '0x0' + nonceProps.primaryTransaction?.txReceipt?.status !== '0x0'; const currentTransactionIsOnChainFailure = - transaction?.txReceipt?.status === '0x0' + transaction?.txReceipt?.status === '0x0'; if ( status === TRANSACTION_STATUSES.CONFIRMED || @@ -265,25 +265,25 @@ export const nonceSortedTransactionsSelector = createSelector( previousPrimaryIsNetworkFailure || (txTime > primaryTxTime && status in PRIORITY_STATUS_HASH) ) { - nonceProps.primaryTransaction = transaction + nonceProps.primaryTransaction = transaction; } const { initialTransaction: { time: initialTxTime = 0 } = {}, - } = nonceProps + } = nonceProps; // Used to display the transaction action, since we don't want to overwrite the action if // it was replaced with a cancel attempt transaction. if (txTime < initialTxTime) { - nonceProps.initialTransaction = transaction + nonceProps.initialTransaction = transaction; } if (type === TRANSACTION_TYPES.RETRY) { - nonceProps.hasRetried = true + nonceProps.hasRetried = true; } if (type === TRANSACTION_TYPES.CANCEL) { - nonceProps.hasCancelled = true + nonceProps.hasCancelled = true; } } else { nonceToTransactionsMap[nonce] = { @@ -293,22 +293,22 @@ export const nonceSortedTransactionsSelector = createSelector( primaryTransaction: transaction, hasRetried: transaction.type === TRANSACTION_TYPES.RETRY, hasCancelled: transaction.type === TRANSACTION_TYPES.CANCEL, - } + }; - insertOrderedNonce(orderedNonces, nonce) + insertOrderedNonce(orderedNonces, nonce); } - }) + }); const orderedTransactionGroups = orderedNonces.map( (nonce) => nonceToTransactionsMap[nonce], - ) + ); mergeNonNonceTransactionGroups( orderedTransactionGroups, incomingTransactionGroups, - ) - return unapprovedTransactionGroups.concat(orderedTransactionGroups) + ); + return unapprovedTransactionGroups.concat(orderedTransactionGroups); }, -) +); /** * @name nonceSortedPendingTransactionsSelector @@ -323,7 +323,7 @@ export const nonceSortedPendingTransactionsSelector = createSelector( ({ primaryTransaction }) => primaryTransaction.status in PENDING_STATUS_HASH, ), -) +); /** * @name nonceSortedCompletedTransactionsSelector @@ -340,7 +340,7 @@ export const nonceSortedCompletedTransactionsSelector = createSelector( !(primaryTransaction.status in PENDING_STATUS_HASH), ) .reverse(), -) +); export const submittedPendingTransactionsSelector = createSelector( transactionsSelector, @@ -348,4 +348,4 @@ export const submittedPendingTransactionsSelector = createSelector( transactions.filter( (transaction) => transaction.status === TRANSACTION_STATUSES.SUBMITTED, ), -) +); diff --git a/ui/app/store/actionConstants.js b/ui/app/store/actionConstants.js index e6fdb7f02..5cdaf608c 100644 --- a/ui/app/store/actionConstants.js +++ b/ui/app/store/actionConstants.js @@ -1,116 +1,116 @@ -export const GO_HOME = 'GO_HOME' +export const GO_HOME = 'GO_HOME'; // modal state -export const MODAL_OPEN = 'UI_MODAL_OPEN' -export const MODAL_CLOSE = 'UI_MODAL_CLOSE' +export const MODAL_OPEN = 'UI_MODAL_OPEN'; +export const MODAL_CLOSE = 'UI_MODAL_CLOSE'; // notification state -export const CLOSE_NOTIFICATION_WINDOW = 'CLOSE_NOTIFICATION_WINDOW' +export const CLOSE_NOTIFICATION_WINDOW = 'CLOSE_NOTIFICATION_WINDOW'; // sidebar state -export const SIDEBAR_OPEN = 'UI_SIDEBAR_OPEN' -export const SIDEBAR_CLOSE = 'UI_SIDEBAR_CLOSE' +export const SIDEBAR_OPEN = 'UI_SIDEBAR_OPEN'; +export const SIDEBAR_CLOSE = 'UI_SIDEBAR_CLOSE'; // alert state -export const ALERT_OPEN = 'UI_ALERT_OPEN' -export const ALERT_CLOSE = 'UI_ALERT_CLOSE' -export const QR_CODE_DETECTED = 'UI_QR_CODE_DETECTED' +export const ALERT_OPEN = 'UI_ALERT_OPEN'; +export const ALERT_CLOSE = 'UI_ALERT_CLOSE'; +export const QR_CODE_DETECTED = 'UI_QR_CODE_DETECTED'; // network dropdown open -export const NETWORK_DROPDOWN_OPEN = 'UI_NETWORK_DROPDOWN_OPEN' -export const NETWORK_DROPDOWN_CLOSE = 'UI_NETWORK_DROPDOWN_CLOSE' +export const NETWORK_DROPDOWN_OPEN = 'UI_NETWORK_DROPDOWN_OPEN'; +export const NETWORK_DROPDOWN_CLOSE = 'UI_NETWORK_DROPDOWN_CLOSE'; // remote state -export const UPDATE_METAMASK_STATE = 'UPDATE_METAMASK_STATE' -export const SELECTED_ADDRESS_CHANGED = 'SELECTED_ADDRESS_CHANGED' -export const FORGOT_PASSWORD = 'FORGOT_PASSWORD' -export const CLOSE_WELCOME_SCREEN = 'CLOSE_WELCOME_SCREEN' +export const UPDATE_METAMASK_STATE = 'UPDATE_METAMASK_STATE'; +export const SELECTED_ADDRESS_CHANGED = 'SELECTED_ADDRESS_CHANGED'; +export const FORGOT_PASSWORD = 'FORGOT_PASSWORD'; +export const CLOSE_WELCOME_SCREEN = 'CLOSE_WELCOME_SCREEN'; // unlock screen -export const UNLOCK_IN_PROGRESS = 'UNLOCK_IN_PROGRESS' -export const UNLOCK_FAILED = 'UNLOCK_FAILED' -export const UNLOCK_SUCCEEDED = 'UNLOCK_SUCCEEDED' -export const LOCK_METAMASK = 'LOCK_METAMASK' +export const UNLOCK_IN_PROGRESS = 'UNLOCK_IN_PROGRESS'; +export const UNLOCK_FAILED = 'UNLOCK_FAILED'; +export const UNLOCK_SUCCEEDED = 'UNLOCK_SUCCEEDED'; +export const LOCK_METAMASK = 'LOCK_METAMASK'; // error handling -export const DISPLAY_WARNING = 'DISPLAY_WARNING' -export const HIDE_WARNING = 'HIDE_WARNING' +export const DISPLAY_WARNING = 'DISPLAY_WARNING'; +export const HIDE_WARNING = 'HIDE_WARNING'; // accounts screen -export const SHOW_ACCOUNT_DETAIL = 'SHOW_ACCOUNT_DETAIL' -export const SHOW_ACCOUNTS_PAGE = 'SHOW_ACCOUNTS_PAGE' -export const SHOW_CONF_TX_PAGE = 'SHOW_CONF_TX_PAGE' -export const SET_CURRENT_FIAT = 'SET_CURRENT_FIAT' +export const SHOW_ACCOUNT_DETAIL = 'SHOW_ACCOUNT_DETAIL'; +export const SHOW_ACCOUNTS_PAGE = 'SHOW_ACCOUNTS_PAGE'; +export const SHOW_CONF_TX_PAGE = 'SHOW_CONF_TX_PAGE'; +export const SET_CURRENT_FIAT = 'SET_CURRENT_FIAT'; // account detail screen -export const SHOW_SEND_TOKEN_PAGE = 'SHOW_SEND_TOKEN_PAGE' -export const SHOW_PRIVATE_KEY = 'SHOW_PRIVATE_KEY' -export const SET_ACCOUNT_LABEL = 'SET_ACCOUNT_LABEL' -export const CLEAR_ACCOUNT_DETAILS = 'CLEAR_ACCOUNT_DETAILS' +export const SHOW_SEND_TOKEN_PAGE = 'SHOW_SEND_TOKEN_PAGE'; +export const SHOW_PRIVATE_KEY = 'SHOW_PRIVATE_KEY'; +export const SET_ACCOUNT_LABEL = 'SET_ACCOUNT_LABEL'; +export const CLEAR_ACCOUNT_DETAILS = 'CLEAR_ACCOUNT_DETAILS'; // tx conf screen -export const COMPLETED_TX = 'COMPLETED_TX' -export const TRANSACTION_ERROR = 'TRANSACTION_ERROR' -export const UPDATE_TRANSACTION_PARAMS = 'UPDATE_TRANSACTION_PARAMS' -export const SET_NEXT_NONCE = 'SET_NEXT_NONCE' +export const COMPLETED_TX = 'COMPLETED_TX'; +export const TRANSACTION_ERROR = 'TRANSACTION_ERROR'; +export const UPDATE_TRANSACTION_PARAMS = 'UPDATE_TRANSACTION_PARAMS'; +export const SET_NEXT_NONCE = 'SET_NEXT_NONCE'; // send screen -export const UPDATE_GAS_LIMIT = 'UPDATE_GAS_LIMIT' -export const UPDATE_GAS_PRICE = 'UPDATE_GAS_PRICE' -export const UPDATE_GAS_TOTAL = 'UPDATE_GAS_TOTAL' -export const UPDATE_SEND_HEX_DATA = 'UPDATE_SEND_HEX_DATA' -export const UPDATE_SEND_TOKEN_BALANCE = 'UPDATE_SEND_TOKEN_BALANCE' -export const UPDATE_SEND_TO = 'UPDATE_SEND_TO' -export const UPDATE_SEND_AMOUNT = 'UPDATE_SEND_AMOUNT' -export const UPDATE_SEND_ERRORS = 'UPDATE_SEND_ERRORS' -export const UPDATE_MAX_MODE = 'UPDATE_MAX_MODE' -export const UPDATE_SEND = 'UPDATE_SEND' -export const UPDATE_SEND_TOKEN = 'UPDATE_SEND_TOKEN' -export const CLEAR_SEND = 'CLEAR_SEND' -export const GAS_LOADING_STARTED = 'GAS_LOADING_STARTED' -export const GAS_LOADING_FINISHED = 'GAS_LOADING_FINISHED' -export const UPDATE_SEND_ENS_RESOLUTION = 'UPDATE_SEND_ENS_RESOLUTION' +export const UPDATE_GAS_LIMIT = 'UPDATE_GAS_LIMIT'; +export const UPDATE_GAS_PRICE = 'UPDATE_GAS_PRICE'; +export const UPDATE_GAS_TOTAL = 'UPDATE_GAS_TOTAL'; +export const UPDATE_SEND_HEX_DATA = 'UPDATE_SEND_HEX_DATA'; +export const UPDATE_SEND_TOKEN_BALANCE = 'UPDATE_SEND_TOKEN_BALANCE'; +export const UPDATE_SEND_TO = 'UPDATE_SEND_TO'; +export const UPDATE_SEND_AMOUNT = 'UPDATE_SEND_AMOUNT'; +export const UPDATE_SEND_ERRORS = 'UPDATE_SEND_ERRORS'; +export const UPDATE_MAX_MODE = 'UPDATE_MAX_MODE'; +export const UPDATE_SEND = 'UPDATE_SEND'; +export const UPDATE_SEND_TOKEN = 'UPDATE_SEND_TOKEN'; +export const CLEAR_SEND = 'CLEAR_SEND'; +export const GAS_LOADING_STARTED = 'GAS_LOADING_STARTED'; +export const GAS_LOADING_FINISHED = 'GAS_LOADING_FINISHED'; +export const UPDATE_SEND_ENS_RESOLUTION = 'UPDATE_SEND_ENS_RESOLUTION'; export const UPDATE_SEND_ENS_RESOLUTION_ERROR = - 'UPDATE_SEND_ENS_RESOLUTION_ERROR' + 'UPDATE_SEND_ENS_RESOLUTION_ERROR'; // config screen -export const SET_RPC_TARGET = 'SET_RPC_TARGET' -export const SET_PROVIDER_TYPE = 'SET_PROVIDER_TYPE' -export const UPDATE_TOKENS = 'UPDATE_TOKENS' +export const SET_RPC_TARGET = 'SET_RPC_TARGET'; +export const SET_PROVIDER_TYPE = 'SET_PROVIDER_TYPE'; +export const UPDATE_TOKENS = 'UPDATE_TOKENS'; export const SET_HARDWARE_WALLET_DEFAULT_HD_PATH = - 'SET_HARDWARE_WALLET_DEFAULT_HD_PATH' + 'SET_HARDWARE_WALLET_DEFAULT_HD_PATH'; // loading overlay -export const SHOW_LOADING = 'SHOW_LOADING_INDICATION' -export const HIDE_LOADING = 'HIDE_LOADING_INDICATION' +export const SHOW_LOADING = 'SHOW_LOADING_INDICATION'; +export const HIDE_LOADING = 'HIDE_LOADING_INDICATION'; -export const BUY_ETH = 'BUY_ETH' +export const BUY_ETH = 'BUY_ETH'; -export const TOGGLE_ACCOUNT_MENU = 'TOGGLE_ACCOUNT_MENU' +export const TOGGLE_ACCOUNT_MENU = 'TOGGLE_ACCOUNT_MENU'; -export const SET_USE_BLOCKIE = 'SET_USE_BLOCKIE' -export const SET_USE_NONCEFIELD = 'SET_USE_NONCEFIELD' -export const UPDATE_CUSTOM_NONCE = 'UPDATE_CUSTOM_NONCE' -export const SET_IPFS_GATEWAY = 'SET_IPFS_GATEWAY' +export const SET_USE_BLOCKIE = 'SET_USE_BLOCKIE'; +export const SET_USE_NONCEFIELD = 'SET_USE_NONCEFIELD'; +export const UPDATE_CUSTOM_NONCE = 'UPDATE_CUSTOM_NONCE'; +export const SET_IPFS_GATEWAY = 'SET_IPFS_GATEWAY'; -export const SET_PARTICIPATE_IN_METAMETRICS = 'SET_PARTICIPATE_IN_METAMETRICS' -export const SET_METAMETRICS_SEND_COUNT = 'SET_METAMETRICS_SEND_COUNT' +export const SET_PARTICIPATE_IN_METAMETRICS = 'SET_PARTICIPATE_IN_METAMETRICS'; +export const SET_METAMETRICS_SEND_COUNT = 'SET_METAMETRICS_SEND_COUNT'; // locale -export const SET_CURRENT_LOCALE = 'SET_CURRENT_LOCALE' +export const SET_CURRENT_LOCALE = 'SET_CURRENT_LOCALE'; // Feature Flags -export const UPDATE_FEATURE_FLAGS = 'UPDATE_FEATURE_FLAGS' +export const UPDATE_FEATURE_FLAGS = 'UPDATE_FEATURE_FLAGS'; // Preferences -export const UPDATE_PREFERENCES = 'UPDATE_PREFERENCES' +export const UPDATE_PREFERENCES = 'UPDATE_PREFERENCES'; // Onboarding -export const COMPLETE_ONBOARDING = 'COMPLETE_ONBOARDING' +export const COMPLETE_ONBOARDING = 'COMPLETE_ONBOARDING'; -export const SET_MOUSE_USER_STATE = 'SET_MOUSE_USER_STATE' +export const SET_MOUSE_USER_STATE = 'SET_MOUSE_USER_STATE'; // Network -export const SET_PENDING_TOKENS = 'SET_PENDING_TOKENS' -export const CLEAR_PENDING_TOKENS = 'CLEAR_PENDING_TOKENS' +export const SET_PENDING_TOKENS = 'SET_PENDING_TOKENS'; +export const CLEAR_PENDING_TOKENS = 'CLEAR_PENDING_TOKENS'; -export const SET_FIRST_TIME_FLOW_TYPE = 'SET_FIRST_TIME_FLOW_TYPE' +export const SET_FIRST_TIME_FLOW_TYPE = 'SET_FIRST_TIME_FLOW_TYPE'; -export const SET_SELECTED_SETTINGS_RPC_URL = 'SET_SELECTED_SETTINGS_RPC_URL' -export const SET_NETWORKS_TAB_ADD_MODE = 'SET_NETWORKS_TAB_ADD_MODE' +export const SET_SELECTED_SETTINGS_RPC_URL = 'SET_SELECTED_SETTINGS_RPC_URL'; +export const SET_NETWORKS_TAB_ADD_MODE = 'SET_NETWORKS_TAB_ADD_MODE'; -export const LOADING_METHOD_DATA_STARTED = 'LOADING_METHOD_DATA_STARTED' -export const LOADING_METHOD_DATA_FINISHED = 'LOADING_METHOD_DATA_FINISHED' +export const LOADING_METHOD_DATA_STARTED = 'LOADING_METHOD_DATA_STARTED'; +export const LOADING_METHOD_DATA_FINISHED = 'LOADING_METHOD_DATA_FINISHED'; -export const LOADING_TOKEN_PARAMS_STARTED = 'LOADING_TOKEN_PARAMS_STARTED' -export const LOADING_TOKEN_PARAMS_FINISHED = 'LOADING_TOKEN_PARAMS_FINISHED' +export const LOADING_TOKEN_PARAMS_STARTED = 'LOADING_TOKEN_PARAMS_STARTED'; +export const LOADING_TOKEN_PARAMS_FINISHED = 'LOADING_TOKEN_PARAMS_FINISHED'; -export const SET_REQUEST_ACCOUNT_TABS = 'SET_REQUEST_ACCOUNT_TABS' -export const SET_CURRENT_WINDOW_TAB = 'SET_CURRENT_WINDOW_TAB' -export const SET_OPEN_METAMASK_TAB_IDS = 'SET_OPEN_METAMASK_TAB_IDS' +export const SET_REQUEST_ACCOUNT_TABS = 'SET_REQUEST_ACCOUNT_TABS'; +export const SET_CURRENT_WINDOW_TAB = 'SET_CURRENT_WINDOW_TAB'; +export const SET_OPEN_METAMASK_TAB_IDS = 'SET_OPEN_METAMASK_TAB_IDS'; diff --git a/ui/app/store/actions.js b/ui/app/store/actions.js index 9cf6196d8..e8187d723 100644 --- a/ui/app/store/actions.js +++ b/ui/app/store/actions.js @@ -1,222 +1,225 @@ -import abi from 'human-standard-token-abi' -import pify from 'pify' -import log from 'loglevel' -import { capitalize } from 'lodash' -import getBuyEthUrl from '../../../app/scripts/lib/buy-eth-url' -import { checksumAddress } from '../helpers/utils/util' -import { calcTokenBalance, estimateGasForSend } from '../pages/send/send.utils' +import abi from 'human-standard-token-abi'; +import pify from 'pify'; +import log from 'loglevel'; +import { capitalize } from 'lodash'; +import getBuyEthUrl from '../../../app/scripts/lib/buy-eth-url'; +import { checksumAddress } from '../helpers/utils/util'; +import { calcTokenBalance, estimateGasForSend } from '../pages/send/send.utils'; import { fetchLocale, loadRelativeTimeFormatLocaleData, -} from '../helpers/utils/i18n-helper' -import { getMethodDataAsync } from '../helpers/utils/transactions.util' -import { fetchSymbolAndDecimals } from '../helpers/utils/token-util' -import switchDirection from '../helpers/utils/switch-direction' -import { ENVIRONMENT_TYPE_NOTIFICATION } from '../../../shared/constants/app' -import { hasUnconfirmedTransactions } from '../helpers/utils/confirm-tx.util' -import { setCustomGasLimit } from '../ducks/gas/gas.duck' -import txHelper from '../../lib/tx-helper' -import { getEnvironmentType, addHexPrefix } from '../../../app/scripts/lib/util' +} from '../helpers/utils/i18n-helper'; +import { getMethodDataAsync } from '../helpers/utils/transactions.util'; +import { fetchSymbolAndDecimals } from '../helpers/utils/token-util'; +import switchDirection from '../helpers/utils/switch-direction'; +import { ENVIRONMENT_TYPE_NOTIFICATION } from '../../../shared/constants/app'; +import { hasUnconfirmedTransactions } from '../helpers/utils/confirm-tx.util'; +import { setCustomGasLimit } from '../ducks/gas/gas.duck'; +import txHelper from '../../lib/tx-helper'; +import { + getEnvironmentType, + addHexPrefix, +} from '../../../app/scripts/lib/util'; import { getPermittedAccountsForCurrentTab, getSelectedAddress, -} from '../selectors' -import { switchedToUnconnectedAccount } from '../ducks/alerts/unconnected-account' -import { getUnconnectedAccountAlertEnabledness } from '../ducks/metamask/metamask' -import { LISTED_CONTRACT_ADDRESSES } from '../../../shared/constants/tokens' -import * as actionConstants from './actionConstants' +} from '../selectors'; +import { switchedToUnconnectedAccount } from '../ducks/alerts/unconnected-account'; +import { getUnconnectedAccountAlertEnabledness } from '../ducks/metamask/metamask'; +import { LISTED_CONTRACT_ADDRESSES } from '../../../shared/constants/tokens'; +import * as actionConstants from './actionConstants'; -let background = null -let promisifiedBackground = null +let background = null; +let promisifiedBackground = null; export function _setBackgroundConnection(backgroundConnection) { - background = backgroundConnection - promisifiedBackground = pify(background) + background = backgroundConnection; + promisifiedBackground = pify(background); } export function goHome() { return { type: actionConstants.GO_HOME, - } + }; } // async actions export function tryUnlockMetamask(password) { return (dispatch) => { - dispatch(showLoadingIndication()) - dispatch(unlockInProgress()) - log.debug(`background.submitPassword`) + dispatch(showLoadingIndication()); + dispatch(unlockInProgress()); + log.debug(`background.submitPassword`); return new Promise((resolve, reject) => { background.submitPassword(password, (error) => { if (error) { - reject(error) - return + reject(error); + return; } - resolve() - }) + resolve(); + }); }) .then(() => { - dispatch(unlockSucceeded()) - return forceUpdateMetamaskState(dispatch) + dispatch(unlockSucceeded()); + return forceUpdateMetamaskState(dispatch); }) .then(() => { return new Promise((resolve, reject) => { background.verifySeedPhrase((err) => { if (err) { - dispatch(displayWarning(err.message)) - reject(err) - return + dispatch(displayWarning(err.message)); + reject(err); + return; } - resolve() - }) - }) + resolve(); + }); + }); }) .then(() => { - dispatch(hideLoadingIndication()) + dispatch(hideLoadingIndication()); }) .catch((err) => { - dispatch(unlockFailed(err.message)) - dispatch(hideLoadingIndication()) - return Promise.reject(err) - }) - } + dispatch(unlockFailed(err.message)); + dispatch(hideLoadingIndication()); + return Promise.reject(err); + }); + }; } export function createNewVaultAndRestore(password, seed) { return (dispatch) => { - dispatch(showLoadingIndication()) - log.debug(`background.createNewVaultAndRestore`) - let vault + dispatch(showLoadingIndication()); + log.debug(`background.createNewVaultAndRestore`); + let vault; return new Promise((resolve, reject) => { background.createNewVaultAndRestore(password, seed, (err, _vault) => { if (err) { - reject(err) - return + reject(err); + return; } - vault = _vault - resolve() - }) + vault = _vault; + resolve(); + }); }) .then(() => dispatch(unMarkPasswordForgotten())) .then(() => { - dispatch(showAccountsPage()) - dispatch(hideLoadingIndication()) - return vault + dispatch(showAccountsPage()); + dispatch(hideLoadingIndication()); + return vault; }) .catch((err) => { - dispatch(displayWarning(err.message)) - dispatch(hideLoadingIndication()) - return Promise.reject(err) - }) - } + dispatch(displayWarning(err.message)); + dispatch(hideLoadingIndication()); + return Promise.reject(err); + }); + }; } export function createNewVaultAndGetSeedPhrase(password) { return async (dispatch) => { - dispatch(showLoadingIndication()) + dispatch(showLoadingIndication()); try { - await createNewVault(password) - const seedWords = await verifySeedPhrase() - return seedWords + await createNewVault(password); + const seedWords = await verifySeedPhrase(); + return seedWords; } catch (error) { - dispatch(displayWarning(error.message)) - throw new Error(error.message) + dispatch(displayWarning(error.message)); + throw new Error(error.message); } finally { - dispatch(hideLoadingIndication()) + dispatch(hideLoadingIndication()); } - } + }; } export function unlockAndGetSeedPhrase(password) { return async (dispatch) => { - dispatch(showLoadingIndication()) + dispatch(showLoadingIndication()); try { - await submitPassword(password) - const seedWords = await verifySeedPhrase() - await forceUpdateMetamaskState(dispatch) - return seedWords + await submitPassword(password); + const seedWords = await verifySeedPhrase(); + await forceUpdateMetamaskState(dispatch); + return seedWords; } catch (error) { - dispatch(displayWarning(error.message)) - throw new Error(error.message) + dispatch(displayWarning(error.message)); + throw new Error(error.message); } finally { - dispatch(hideLoadingIndication()) + dispatch(hideLoadingIndication()); } - } + }; } export function submitPassword(password) { return new Promise((resolve, reject) => { background.submitPassword(password, (error) => { if (error) { - reject(error) - return + reject(error); + return; } - resolve() - }) - }) + resolve(); + }); + }); } export function createNewVault(password) { return new Promise((resolve, reject) => { background.createNewVaultAndKeychain(password, (error) => { if (error) { - reject(error) - return + reject(error); + return; } - resolve(true) - }) - }) + resolve(true); + }); + }); } export function verifyPassword(password) { return new Promise((resolve, reject) => { background.verifyPassword(password, (error) => { if (error) { - reject(error) - return + reject(error); + return; } - resolve(true) - }) - }) + resolve(true); + }); + }); } export function verifySeedPhrase() { return new Promise((resolve, reject) => { background.verifySeedPhrase((error, seedWords) => { if (error) { - reject(error) - return + reject(error); + return; } - resolve(seedWords) - }) - }) + resolve(seedWords); + }); + }); } export function requestRevealSeedWords(password) { return async (dispatch) => { - dispatch(showLoadingIndication()) - log.debug(`background.verifyPassword`) + dispatch(showLoadingIndication()); + log.debug(`background.verifyPassword`); try { - await verifyPassword(password) - const seedWords = await verifySeedPhrase() - return seedWords + await verifyPassword(password); + const seedWords = await verifySeedPhrase(); + return seedWords; } catch (error) { - dispatch(displayWarning(error.message)) - throw new Error(error.message) + dispatch(displayWarning(error.message)); + throw new Error(error.message); } finally { - dispatch(hideLoadingIndication()) + dispatch(hideLoadingIndication()); } - } + }; } export function tryReverseResolveAddress(address) { @@ -224,222 +227,229 @@ export function tryReverseResolveAddress(address) { return new Promise((resolve) => { background.tryReverseResolveAddress(address, (err) => { if (err) { - log.error(err) + log.error(err); } - resolve() - }) - }) - } + resolve(); + }); + }); + }; } export function fetchInfoToSync() { return (dispatch) => { - log.debug(`background.fetchInfoToSync`) + log.debug(`background.fetchInfoToSync`); return new Promise((resolve, reject) => { background.fetchInfoToSync((err, result) => { if (err) { - dispatch(displayWarning(err.message)) - reject(err) - return + dispatch(displayWarning(err.message)); + reject(err); + return; } - resolve(result) - }) - }) - } + resolve(result); + }); + }); + }; } export function resetAccount() { return (dispatch) => { - dispatch(showLoadingIndication()) + dispatch(showLoadingIndication()); return new Promise((resolve, reject) => { background.resetAccount((err, account) => { - dispatch(hideLoadingIndication()) + dispatch(hideLoadingIndication()); if (err) { - dispatch(displayWarning(err.message)) - reject(err) - return + dispatch(displayWarning(err.message)); + reject(err); + return; } - log.info(`Transaction history reset for ${account}`) - dispatch(showAccountsPage()) - resolve(account) - }) - }) - } + log.info(`Transaction history reset for ${account}`); + dispatch(showAccountsPage()); + resolve(account); + }); + }); + }; } export function removeAccount(address) { return async (dispatch) => { - dispatch(showLoadingIndication()) + dispatch(showLoadingIndication()); try { await new Promise((resolve, reject) => { background.removeAccount(address, (error, account) => { if (error) { - reject(error) - return + reject(error); + return; } - resolve(account) - }) - }) - await forceUpdateMetamaskState(dispatch) + resolve(account); + }); + }); + await forceUpdateMetamaskState(dispatch); } catch (error) { - dispatch(displayWarning(error.message)) - throw error + dispatch(displayWarning(error.message)); + throw error; } finally { - dispatch(hideLoadingIndication()) + dispatch(hideLoadingIndication()); } - log.info(`Account removed: ${address}`) - dispatch(showAccountsPage()) - } + log.info(`Account removed: ${address}`); + dispatch(showAccountsPage()); + }; } export function importNewAccount(strategy, args) { return async (dispatch) => { - let newState - dispatch(showLoadingIndication('This may take a while, please be patient.')) + let newState; + dispatch( + showLoadingIndication('This may take a while, please be patient.'), + ); try { - log.debug(`background.importAccountWithStrategy`) - await promisifiedBackground.importAccountWithStrategy(strategy, args) - log.debug(`background.getState`) - newState = await promisifiedBackground.getState() + log.debug(`background.importAccountWithStrategy`); + await promisifiedBackground.importAccountWithStrategy(strategy, args); + log.debug(`background.getState`); + newState = await promisifiedBackground.getState(); } catch (err) { - dispatch(displayWarning(err.message)) - throw err + dispatch(displayWarning(err.message)); + throw err; } finally { - dispatch(hideLoadingIndication()) + dispatch(hideLoadingIndication()); } - dispatch(updateMetamaskState(newState)) + dispatch(updateMetamaskState(newState)); if (newState.selectedAddress) { dispatch({ type: actionConstants.SHOW_ACCOUNT_DETAIL, value: newState.selectedAddress, - }) + }); } - return newState - } + return newState; + }; } export function addNewAccount() { - log.debug(`background.addNewAccount`) + log.debug(`background.addNewAccount`); return async (dispatch, getState) => { - const oldIdentities = getState().metamask.identities - dispatch(showLoadingIndication()) + const oldIdentities = getState().metamask.identities; + dispatch(showLoadingIndication()); - let newIdentities + let newIdentities; try { - const { identities } = await promisifiedBackground.addNewAccount() - newIdentities = identities + const { identities } = await promisifiedBackground.addNewAccount(); + newIdentities = identities; } catch (error) { - dispatch(displayWarning(error.message)) - throw error + dispatch(displayWarning(error.message)); + throw error; } finally { - dispatch(hideLoadingIndication()) + dispatch(hideLoadingIndication()); } const newAccountAddress = Object.keys(newIdentities).find( (address) => !oldIdentities[address], - ) - await forceUpdateMetamaskState(dispatch) - return newAccountAddress - } + ); + await forceUpdateMetamaskState(dispatch); + return newAccountAddress; + }; } export function checkHardwareStatus(deviceName, hdPath) { - log.debug(`background.checkHardwareStatus`, deviceName, hdPath) + log.debug(`background.checkHardwareStatus`, deviceName, hdPath); return async (dispatch) => { - dispatch(showLoadingIndication()) + dispatch(showLoadingIndication()); - let unlocked + let unlocked; try { unlocked = await promisifiedBackground.checkHardwareStatus( deviceName, hdPath, - ) + ); } catch (error) { - log.error(error) - dispatch(displayWarning(error.message)) - throw error + log.error(error); + dispatch(displayWarning(error.message)); + throw error; } finally { - dispatch(hideLoadingIndication()) + dispatch(hideLoadingIndication()); } - await forceUpdateMetamaskState(dispatch) - return unlocked - } + await forceUpdateMetamaskState(dispatch); + return unlocked; + }; } export function forgetDevice(deviceName) { - log.debug(`background.forgetDevice`, deviceName) + log.debug(`background.forgetDevice`, deviceName); return async (dispatch) => { - dispatch(showLoadingIndication()) + dispatch(showLoadingIndication()); try { - await promisifiedBackground.forgetDevice(deviceName) + await promisifiedBackground.forgetDevice(deviceName); } catch (error) { - log.error(error) - dispatch(displayWarning(error.message)) - throw error + log.error(error); + dispatch(displayWarning(error.message)); + throw error; } finally { - dispatch(hideLoadingIndication()) + dispatch(hideLoadingIndication()); } - await forceUpdateMetamaskState(dispatch) - } + await forceUpdateMetamaskState(dispatch); + }; } export function connectHardware(deviceName, page, hdPath) { - log.debug(`background.connectHardware`, deviceName, page, hdPath) + log.debug(`background.connectHardware`, deviceName, page, hdPath); return async (dispatch) => { dispatch( showLoadingIndication(`Looking for your ${capitalize(deviceName)}...`), - ) + ); - let accounts + let accounts; try { accounts = await promisifiedBackground.connectHardware( deviceName, page, hdPath, - ) + ); } catch (error) { - log.error(error) - dispatch(displayWarning(error.message)) - throw error + log.error(error); + dispatch(displayWarning(error.message)); + throw error; } finally { - dispatch(hideLoadingIndication()) + dispatch(hideLoadingIndication()); } - await forceUpdateMetamaskState(dispatch) - return accounts - } + await forceUpdateMetamaskState(dispatch); + return accounts; + }; } export function unlockHardwareWalletAccount(index, deviceName, hdPath) { - log.debug(`background.unlockHardwareWalletAccount`, index, deviceName, hdPath) + log.debug( + `background.unlockHardwareWalletAccount`, + index, + deviceName, + hdPath, + ); return (dispatch) => { - dispatch(showLoadingIndication()) + dispatch(showLoadingIndication()); return new Promise((resolve, reject) => { background.unlockHardwareWalletAccount( index, deviceName, hdPath, (err) => { - dispatch(hideLoadingIndication()) + dispatch(hideLoadingIndication()); if (err) { - log.error(err) - dispatch(displayWarning(err.message)) - reject(err) - return + log.error(err); + dispatch(displayWarning(err.message)); + reject(err); + return; } - resolve() + resolve(); }, - ) - }) - } + ); + }); + }; } export function showQrScanner() { @@ -448,23 +458,23 @@ export function showQrScanner() { showModal({ name: 'QR_SCANNER', }), - ) - } + ); + }; } export function setCurrentCurrency(currencyCode) { return async (dispatch) => { - dispatch(showLoadingIndication()) - log.debug(`background.setCurrentCurrency`) - let data + dispatch(showLoadingIndication()); + log.debug(`background.setCurrentCurrency`); + let data; try { - data = await promisifiedBackground.setCurrentCurrency(currencyCode) + data = await promisifiedBackground.setCurrentCurrency(currencyCode); } catch (error) { - log.error(error.stack) - dispatch(displayWarning(error.message)) - return + log.error(error.stack); + dispatch(displayWarning(error.message)); + return; } finally { - dispatch(hideLoadingIndication()) + dispatch(hideLoadingIndication()); } dispatch({ @@ -474,180 +484,180 @@ export function setCurrentCurrency(currencyCode) { conversionRate: data.conversionRate, conversionDate: data.conversionDate, }, - }) - } + }); + }; } export function signMsg(msgData) { - log.debug('action - signMsg') + log.debug('action - signMsg'); return async (dispatch) => { - dispatch(showLoadingIndication()) - log.debug(`actions calling background.signMessage`) - let newState + dispatch(showLoadingIndication()); + log.debug(`actions calling background.signMessage`); + let newState; try { - newState = await promisifiedBackground.signMessage(msgData) + newState = await promisifiedBackground.signMessage(msgData); } catch (error) { - log.error(error) - dispatch(displayWarning(error.message)) - throw error + log.error(error); + dispatch(displayWarning(error.message)); + throw error; } finally { - dispatch(hideLoadingIndication()) + dispatch(hideLoadingIndication()); } - dispatch(updateMetamaskState(newState)) - dispatch(completedTx(msgData.metamaskId)) - dispatch(closeCurrentNotificationWindow()) - return msgData - } + dispatch(updateMetamaskState(newState)); + dispatch(completedTx(msgData.metamaskId)); + dispatch(closeCurrentNotificationWindow()); + return msgData; + }; } export function signPersonalMsg(msgData) { - log.debug('action - signPersonalMsg') + log.debug('action - signPersonalMsg'); return async (dispatch) => { - dispatch(showLoadingIndication()) - log.debug(`actions calling background.signPersonalMessage`) + dispatch(showLoadingIndication()); + log.debug(`actions calling background.signPersonalMessage`); - let newState + let newState; try { - newState = await promisifiedBackground.signPersonalMessage(msgData) + newState = await promisifiedBackground.signPersonalMessage(msgData); } catch (error) { - log.error(error) - dispatch(displayWarning(error.message)) - throw error + log.error(error); + dispatch(displayWarning(error.message)); + throw error; } finally { - dispatch(hideLoadingIndication()) + dispatch(hideLoadingIndication()); } - dispatch(updateMetamaskState(newState)) - dispatch(completedTx(msgData.metamaskId)) - dispatch(closeCurrentNotificationWindow()) - return msgData - } + dispatch(updateMetamaskState(newState)); + dispatch(completedTx(msgData.metamaskId)); + dispatch(closeCurrentNotificationWindow()); + return msgData; + }; } export function decryptMsgInline(decryptedMsgData) { - log.debug('action - decryptMsgInline') + log.debug('action - decryptMsgInline'); return async (dispatch) => { - log.debug(`actions calling background.decryptMessageInline`) + log.debug(`actions calling background.decryptMessageInline`); - let newState + let newState; try { newState = await promisifiedBackground.decryptMessageInline( decryptedMsgData, - ) + ); } catch (error) { - log.error(error) - dispatch(displayWarning(error.message)) - throw error + log.error(error); + dispatch(displayWarning(error.message)); + throw error; } - dispatch(updateMetamaskState(newState)) - return newState.unapprovedDecryptMsgs[decryptedMsgData.metamaskId] - } + dispatch(updateMetamaskState(newState)); + return newState.unapprovedDecryptMsgs[decryptedMsgData.metamaskId]; + }; } export function decryptMsg(decryptedMsgData) { - log.debug('action - decryptMsg') + log.debug('action - decryptMsg'); return async (dispatch) => { - dispatch(showLoadingIndication()) - log.debug(`actions calling background.decryptMessage`) + dispatch(showLoadingIndication()); + log.debug(`actions calling background.decryptMessage`); - let newState + let newState; try { - newState = await promisifiedBackground.decryptMessage(decryptedMsgData) + newState = await promisifiedBackground.decryptMessage(decryptedMsgData); } catch (error) { - log.error(error) - dispatch(displayWarning(error.message)) - throw error + log.error(error); + dispatch(displayWarning(error.message)); + throw error; } finally { - dispatch(hideLoadingIndication()) + dispatch(hideLoadingIndication()); } - dispatch(updateMetamaskState(newState)) - dispatch(completedTx(decryptedMsgData.metamaskId)) - dispatch(closeCurrentNotificationWindow()) - return decryptedMsgData - } + dispatch(updateMetamaskState(newState)); + dispatch(completedTx(decryptedMsgData.metamaskId)); + dispatch(closeCurrentNotificationWindow()); + return decryptedMsgData; + }; } export function encryptionPublicKeyMsg(msgData) { - log.debug('action - encryptionPublicKeyMsg') + log.debug('action - encryptionPublicKeyMsg'); return async (dispatch) => { - dispatch(showLoadingIndication()) - log.debug(`actions calling background.encryptionPublicKey`) + dispatch(showLoadingIndication()); + log.debug(`actions calling background.encryptionPublicKey`); - let newState + let newState; try { - newState = await promisifiedBackground.encryptionPublicKey(msgData) + newState = await promisifiedBackground.encryptionPublicKey(msgData); } catch (error) { - log.error(error) - dispatch(displayWarning(error.message)) - throw error + log.error(error); + dispatch(displayWarning(error.message)); + throw error; } finally { - dispatch(hideLoadingIndication()) + dispatch(hideLoadingIndication()); } - dispatch(updateMetamaskState(newState)) - dispatch(completedTx(msgData.metamaskId)) - dispatch(closeCurrentNotificationWindow()) - return msgData - } + dispatch(updateMetamaskState(newState)); + dispatch(completedTx(msgData.metamaskId)); + dispatch(closeCurrentNotificationWindow()); + return msgData; + }; } export function signTypedMsg(msgData) { - log.debug('action - signTypedMsg') + log.debug('action - signTypedMsg'); return async (dispatch) => { - dispatch(showLoadingIndication()) - log.debug(`actions calling background.signTypedMessage`) + dispatch(showLoadingIndication()); + log.debug(`actions calling background.signTypedMessage`); - let newState + let newState; try { - newState = await promisifiedBackground.signTypedMessage(msgData) + newState = await promisifiedBackground.signTypedMessage(msgData); } catch (error) { - log.error(error) - dispatch(displayWarning(error.message)) - throw error + log.error(error); + dispatch(displayWarning(error.message)); + throw error; } finally { - dispatch(hideLoadingIndication()) + dispatch(hideLoadingIndication()); } - dispatch(updateMetamaskState(newState)) - dispatch(completedTx(msgData.metamaskId)) - dispatch(closeCurrentNotificationWindow()) - return msgData - } + dispatch(updateMetamaskState(newState)); + dispatch(completedTx(msgData.metamaskId)); + dispatch(closeCurrentNotificationWindow()); + return msgData; + }; } export function signTx(txData) { return (dispatch) => { global.ethQuery.sendTransaction(txData, (err) => { if (err) { - dispatch(displayWarning(err.message)) + dispatch(displayWarning(err.message)); } - }) - dispatch(showConfTxPage()) - } + }); + dispatch(showConfTxPage()); + }; } export function setGasLimit(gasLimit) { return { type: actionConstants.UPDATE_GAS_LIMIT, value: gasLimit, - } + }; } export function setGasPrice(gasPrice) { return { type: actionConstants.UPDATE_GAS_PRICE, value: gasPrice, - } + }; } export function setGasTotal(gasTotal) { return { type: actionConstants.UPDATE_GAS_TOTAL, value: gasTotal, - } + }; } export function updateGasData({ @@ -660,7 +670,7 @@ export function updateGasData({ data, }) { return (dispatch) => { - dispatch(gasLoadingStarted()) + dispatch(gasLoadingStarted()); return estimateGasForSend({ estimateGasMethod: promisifiedBackground.estimateGas, blockGasLimit, @@ -672,273 +682,273 @@ export function updateGasData({ data, }) .then((gas) => { - dispatch(setGasLimit(gas)) - dispatch(setCustomGasLimit(gas)) - dispatch(updateSendErrors({ gasLoadingError: null })) - dispatch(gasLoadingFinished()) + dispatch(setGasLimit(gas)); + dispatch(setCustomGasLimit(gas)); + dispatch(updateSendErrors({ gasLoadingError: null })); + dispatch(gasLoadingFinished()); }) .catch((err) => { - log.error(err) - dispatch(updateSendErrors({ gasLoadingError: 'gasLoadingError' })) - dispatch(gasLoadingFinished()) - }) - } + log.error(err); + dispatch(updateSendErrors({ gasLoadingError: 'gasLoadingError' })); + dispatch(gasLoadingFinished()); + }); + }; } export function gasLoadingStarted() { return { type: actionConstants.GAS_LOADING_STARTED, - } + }; } export function gasLoadingFinished() { return { type: actionConstants.GAS_LOADING_FINISHED, - } + }; } export function updateSendTokenBalance({ sendToken, tokenContract, address }) { return (dispatch) => { const tokenBalancePromise = tokenContract ? tokenContract.balanceOf(address) - : Promise.resolve() + : Promise.resolve(); return tokenBalancePromise .then((usersToken) => { if (usersToken) { - const newTokenBalance = calcTokenBalance({ sendToken, usersToken }) - dispatch(setSendTokenBalance(newTokenBalance)) + const newTokenBalance = calcTokenBalance({ sendToken, usersToken }); + dispatch(setSendTokenBalance(newTokenBalance)); } }) .catch((err) => { - log.error(err) - updateSendErrors({ tokenBalance: 'tokenBalanceError' }) - }) - } + log.error(err); + updateSendErrors({ tokenBalance: 'tokenBalanceError' }); + }); + }; } export function updateSendErrors(errorObject) { return { type: actionConstants.UPDATE_SEND_ERRORS, value: errorObject, - } + }; } export function setSendTokenBalance(tokenBalance) { return { type: actionConstants.UPDATE_SEND_TOKEN_BALANCE, value: tokenBalance, - } + }; } export function updateSendHexData(value) { return { type: actionConstants.UPDATE_SEND_HEX_DATA, value, - } + }; } export function updateSendTo(to, nickname = '') { return { type: actionConstants.UPDATE_SEND_TO, value: { to, nickname }, - } + }; } export function updateSendAmount(amount) { return { type: actionConstants.UPDATE_SEND_AMOUNT, value: amount, - } + }; } export function updateCustomNonce(value) { return { type: actionConstants.UPDATE_CUSTOM_NONCE, value, - } + }; } export function setMaxModeTo(bool) { return { type: actionConstants.UPDATE_MAX_MODE, value: bool, - } + }; } export function updateSend(newSend) { return { type: actionConstants.UPDATE_SEND, value: newSend, - } + }; } export function updateSendToken(token) { return { type: actionConstants.UPDATE_SEND_TOKEN, value: token, - } + }; } export function clearSend() { return { type: actionConstants.CLEAR_SEND, - } + }; } export function updateSendEnsResolution(ensResolution) { return { type: actionConstants.UPDATE_SEND_ENS_RESOLUTION, payload: ensResolution, - } + }; } export function updateSendEnsResolutionError(errorMessage) { return { type: actionConstants.UPDATE_SEND_ENS_RESOLUTION_ERROR, payload: errorMessage, - } + }; } export function signTokenTx(tokenAddress, toAddress, amount, txData) { return async (dispatch) => { - dispatch(showLoadingIndication()) + dispatch(showLoadingIndication()); try { - const token = global.eth.contract(abi).at(tokenAddress) - const txPromise = token.transfer(toAddress, addHexPrefix(amount), txData) - dispatch(showConfTxPage()) - dispatch(hideLoadingIndication()) - await txPromise + const token = global.eth.contract(abi).at(tokenAddress); + const txPromise = token.transfer(toAddress, addHexPrefix(amount), txData); + dispatch(showConfTxPage()); + dispatch(hideLoadingIndication()); + await txPromise; } catch (error) { - dispatch(hideLoadingIndication()) - dispatch(displayWarning(error.message)) + dispatch(hideLoadingIndication()); + dispatch(displayWarning(error.message)); } - } + }; } const updateMetamaskStateFromBackground = () => { - log.debug(`background.getState`) + log.debug(`background.getState`); return new Promise((resolve, reject) => { background.getState((error, newState) => { if (error) { - reject(error) - return + reject(error); + return; } - resolve(newState) - }) - }) -} + resolve(newState); + }); + }); +}; export function updateTransaction(txData, dontShowLoadingIndicator) { return async (dispatch) => { - !dontShowLoadingIndicator && dispatch(showLoadingIndication()) + !dontShowLoadingIndicator && dispatch(showLoadingIndication()); try { - await promisifiedBackground.updateTransaction(txData) + await promisifiedBackground.updateTransaction(txData); } catch (error) { - dispatch(updateTransactionParams(txData.id, txData.txParams)) - dispatch(hideLoadingIndication()) - dispatch(txError(error)) - dispatch(goHome()) - log.error(error.message) - throw error + dispatch(updateTransactionParams(txData.id, txData.txParams)); + dispatch(hideLoadingIndication()); + dispatch(txError(error)); + dispatch(goHome()); + log.error(error.message); + throw error; } try { - dispatch(updateTransactionParams(txData.id, txData.txParams)) - const newState = await updateMetamaskStateFromBackground() - dispatch(updateMetamaskState(newState)) - dispatch(showConfTxPage({ id: txData.id })) - return txData + dispatch(updateTransactionParams(txData.id, txData.txParams)); + const newState = await updateMetamaskStateFromBackground(); + dispatch(updateMetamaskState(newState)); + dispatch(showConfTxPage({ id: txData.id })); + return txData; } finally { - dispatch(hideLoadingIndication()) + dispatch(hideLoadingIndication()); } - } + }; } export function addUnapprovedTransaction(txParams, origin) { - log.debug('background.addUnapprovedTransaction') + log.debug('background.addUnapprovedTransaction'); return () => { return new Promise((resolve, reject) => { background.addUnapprovedTransaction(txParams, origin, (err, txMeta) => { if (err) { - reject(err) - return + reject(err); + return; } - resolve(txMeta) - }) - }) - } + resolve(txMeta); + }); + }); + }; } export function updateAndApproveTx(txData, dontShowLoadingIndicator) { return (dispatch) => { - !dontShowLoadingIndicator && dispatch(showLoadingIndication()) + !dontShowLoadingIndicator && dispatch(showLoadingIndication()); return new Promise((resolve, reject) => { background.updateAndApproveTransaction(txData, (err) => { - dispatch(updateTransactionParams(txData.id, txData.txParams)) - dispatch(clearSend()) + dispatch(updateTransactionParams(txData.id, txData.txParams)); + dispatch(clearSend()); if (err) { - dispatch(txError(err)) - dispatch(goHome()) - log.error(err.message) - reject(err) - return + dispatch(txError(err)); + dispatch(goHome()); + log.error(err.message); + reject(err); + return; } - resolve(txData) - }) + resolve(txData); + }); }) .then(() => updateMetamaskStateFromBackground()) .then((newState) => dispatch(updateMetamaskState(newState))) .then(() => { - dispatch(clearSend()) - dispatch(completedTx(txData.id)) - dispatch(hideLoadingIndication()) - dispatch(updateCustomNonce('')) - dispatch(closeCurrentNotificationWindow()) + dispatch(clearSend()); + dispatch(completedTx(txData.id)); + dispatch(hideLoadingIndication()); + dispatch(updateCustomNonce('')); + dispatch(closeCurrentNotificationWindow()); - return txData + return txData; }) .catch((err) => { - dispatch(hideLoadingIndication()) - return Promise.reject(err) - }) - } + dispatch(hideLoadingIndication()); + return Promise.reject(err); + }); + }; } export function completedTx(id) { return (dispatch, getState) => { - const state = getState() + const state = getState(); const { unapprovedTxs, unapprovedMsgs, unapprovedPersonalMsgs, unapprovedTypedMessages, network, - } = state.metamask + } = state.metamask; const unconfirmedActions = txHelper( unapprovedTxs, unapprovedMsgs, unapprovedPersonalMsgs, unapprovedTypedMessages, network, - ) + ); const otherUnconfirmedActions = unconfirmedActions.filter( (tx) => tx.id !== id, - ) + ); dispatch({ type: actionConstants.COMPLETED_TX, value: { id, unconfirmedActionsCount: otherUnconfirmedActions.length, }, - }) - } + }); + }; } export function updateTransactionParams(id, txParams) { @@ -946,136 +956,136 @@ export function updateTransactionParams(id, txParams) { type: actionConstants.UPDATE_TRANSACTION_PARAMS, id, value: txParams, - } + }; } export function txError(err) { return { type: actionConstants.TRANSACTION_ERROR, message: err.message, - } + }; } export function cancelMsg(msgData) { return async (dispatch) => { - dispatch(showLoadingIndication()) + dispatch(showLoadingIndication()); - let newState + let newState; try { - newState = await promisifiedBackground.cancelMessage(msgData.id) + newState = await promisifiedBackground.cancelMessage(msgData.id); } finally { - dispatch(hideLoadingIndication()) + dispatch(hideLoadingIndication()); } - dispatch(updateMetamaskState(newState)) - dispatch(completedTx(msgData.id)) - dispatch(closeCurrentNotificationWindow()) - return msgData - } + dispatch(updateMetamaskState(newState)); + dispatch(completedTx(msgData.id)); + dispatch(closeCurrentNotificationWindow()); + return msgData; + }; } export function cancelPersonalMsg(msgData) { return async (dispatch) => { - dispatch(showLoadingIndication()) + dispatch(showLoadingIndication()); - let newState + let newState; try { - newState = await promisifiedBackground.cancelPersonalMessage(msgData.id) + newState = await promisifiedBackground.cancelPersonalMessage(msgData.id); } finally { - dispatch(hideLoadingIndication()) + dispatch(hideLoadingIndication()); } - dispatch(updateMetamaskState(newState)) - dispatch(completedTx(msgData.id)) - dispatch(closeCurrentNotificationWindow()) - return msgData - } + dispatch(updateMetamaskState(newState)); + dispatch(completedTx(msgData.id)); + dispatch(closeCurrentNotificationWindow()); + return msgData; + }; } export function cancelDecryptMsg(msgData) { return async (dispatch) => { - dispatch(showLoadingIndication()) + dispatch(showLoadingIndication()); - let newState + let newState; try { - newState = await promisifiedBackground.cancelDecryptMessage(msgData.id) + newState = await promisifiedBackground.cancelDecryptMessage(msgData.id); } finally { - dispatch(hideLoadingIndication()) + dispatch(hideLoadingIndication()); } - dispatch(updateMetamaskState(newState)) - dispatch(completedTx(msgData.id)) - dispatch(closeCurrentNotificationWindow()) - return msgData - } + dispatch(updateMetamaskState(newState)); + dispatch(completedTx(msgData.id)); + dispatch(closeCurrentNotificationWindow()); + return msgData; + }; } export function cancelEncryptionPublicKeyMsg(msgData) { return async (dispatch) => { - dispatch(showLoadingIndication()) + dispatch(showLoadingIndication()); - let newState + let newState; try { newState = await promisifiedBackground.cancelEncryptionPublicKey( msgData.id, - ) + ); } finally { - dispatch(hideLoadingIndication()) + dispatch(hideLoadingIndication()); } - dispatch(updateMetamaskState(newState)) - dispatch(completedTx(msgData.id)) - dispatch(closeCurrentNotificationWindow()) - return msgData - } + dispatch(updateMetamaskState(newState)); + dispatch(completedTx(msgData.id)); + dispatch(closeCurrentNotificationWindow()); + return msgData; + }; } export function cancelTypedMsg(msgData) { return async (dispatch) => { - dispatch(showLoadingIndication()) + dispatch(showLoadingIndication()); - let newState + let newState; try { - newState = await promisifiedBackground.cancelTypedMessage(msgData.id) + newState = await promisifiedBackground.cancelTypedMessage(msgData.id); } finally { - dispatch(hideLoadingIndication()) + dispatch(hideLoadingIndication()); } - dispatch(updateMetamaskState(newState)) - dispatch(completedTx(msgData.id)) - dispatch(closeCurrentNotificationWindow()) - return msgData - } + dispatch(updateMetamaskState(newState)); + dispatch(completedTx(msgData.id)); + dispatch(closeCurrentNotificationWindow()); + return msgData; + }; } export function cancelTx(txData, _showLoadingIndication = true) { return (dispatch) => { - _showLoadingIndication && dispatch(showLoadingIndication()) + _showLoadingIndication && dispatch(showLoadingIndication()); return new Promise((resolve, reject) => { background.cancelTransaction(txData.id, (error) => { if (error) { - reject(error) - return + reject(error); + return; } - resolve() - }) + resolve(); + }); }) .then(() => updateMetamaskStateFromBackground()) .then((newState) => dispatch(updateMetamaskState(newState))) .then(() => { - dispatch(clearSend()) - dispatch(completedTx(txData.id)) - dispatch(hideLoadingIndication()) - dispatch(closeCurrentNotificationWindow()) + dispatch(clearSend()); + dispatch(completedTx(txData.id)); + dispatch(hideLoadingIndication()); + dispatch(closeCurrentNotificationWindow()); - return txData + return txData; }) .catch((error) => { - dispatch(hideLoadingIndication()) - throw error - }) - } + dispatch(hideLoadingIndication()); + throw error; + }); + }; } /** @@ -1085,41 +1095,41 @@ export function cancelTx(txData, _showLoadingIndication = true) { */ export function cancelTxs(txDataList) { return async (dispatch) => { - dispatch(showLoadingIndication()) + dispatch(showLoadingIndication()); try { - const txIds = txDataList.map(({ id }) => id) + const txIds = txDataList.map(({ id }) => id); const cancellations = txIds.map( (id) => new Promise((resolve, reject) => { background.cancelTransaction(id, (err) => { if (err) { - reject(err) - return + reject(err); + return; } - resolve() - }) + resolve(); + }); }), - ) + ); - await Promise.all(cancellations) + await Promise.all(cancellations); - const newState = await updateMetamaskStateFromBackground() - dispatch(updateMetamaskState(newState)) - dispatch(clearSend()) + const newState = await updateMetamaskStateFromBackground(); + dispatch(updateMetamaskState(newState)); + dispatch(clearSend()); txIds.forEach((id) => { - dispatch(completedTx(id)) - }) + dispatch(completedTx(id)); + }); } finally { if (getEnvironmentType() === ENVIRONMENT_TYPE_NOTIFICATION) { - global.platform.closeCurrentWindow() + global.platform.closeCurrentWindow(); } else { - dispatch(hideLoadingIndication()) + dispatch(hideLoadingIndication()); } } - } + }; } export function markPasswordForgotten() { @@ -1128,43 +1138,43 @@ export function markPasswordForgotten() { await new Promise((resolve, reject) => { return background.markPasswordForgotten((error) => { if (error) { - reject(error) - return + reject(error); + return; } - resolve() - }) - }) + resolve(); + }); + }); } finally { // TODO: handle errors - dispatch(hideLoadingIndication()) - dispatch(forgotPassword()) - await forceUpdateMetamaskState(dispatch) + dispatch(hideLoadingIndication()); + dispatch(forgotPassword()); + await forceUpdateMetamaskState(dispatch); } - } + }; } export function unMarkPasswordForgotten() { return (dispatch) => { return new Promise((resolve) => { background.unMarkPasswordForgotten(() => { - dispatch(forgotPassword(false)) - resolve() - }) - }).then(() => forceUpdateMetamaskState(dispatch)) - } + dispatch(forgotPassword(false)); + resolve(); + }); + }).then(() => forceUpdateMetamaskState(dispatch)); + }; } export function forgotPassword(forgotPasswordState = true) { return { type: actionConstants.FORGOT_PASSWORD, value: forgotPasswordState, - } + }; } export function closeWelcomeScreen() { return { type: actionConstants.CLOSE_WELCOME_SCREEN, - } + }; } // @@ -1174,149 +1184,149 @@ export function closeWelcomeScreen() { export function unlockInProgress() { return { type: actionConstants.UNLOCK_IN_PROGRESS, - } + }; } export function unlockFailed(message) { return { type: actionConstants.UNLOCK_FAILED, value: message, - } + }; } export function unlockSucceeded(message) { return { type: actionConstants.UNLOCK_SUCCEEDED, value: message, - } + }; } export function updateMetamaskState(newState) { return (dispatch, getState) => { - const { metamask: currentState } = getState() + const { metamask: currentState } = getState(); - const { currentLocale, selectedAddress } = currentState + const { currentLocale, selectedAddress } = currentState; const { currentLocale: newLocale, selectedAddress: newSelectedAddress, - } = newState + } = newState; if (currentLocale && newLocale && currentLocale !== newLocale) { - dispatch(updateCurrentLocale(newLocale)) + dispatch(updateCurrentLocale(newLocale)); } if (selectedAddress !== newSelectedAddress) { - dispatch({ type: actionConstants.SELECTED_ADDRESS_CHANGED }) + dispatch({ type: actionConstants.SELECTED_ADDRESS_CHANGED }); } dispatch({ type: actionConstants.UPDATE_METAMASK_STATE, value: newState, - }) - } + }); + }; } const backgroundSetLocked = () => { return new Promise((resolve, reject) => { background.setLocked((error) => { if (error) { - reject(error) - return + reject(error); + return; } - resolve() - }) - }) -} + resolve(); + }); + }); +}; export function lockMetamask() { - log.debug(`background.setLocked`) + log.debug(`background.setLocked`); return (dispatch) => { - dispatch(showLoadingIndication()) + dispatch(showLoadingIndication()); return backgroundSetLocked() .then(() => updateMetamaskStateFromBackground()) .catch((error) => { - dispatch(displayWarning(error.message)) - return Promise.reject(error) + dispatch(displayWarning(error.message)); + return Promise.reject(error); }) .then((newState) => { - dispatch(updateMetamaskState(newState)) - dispatch(hideLoadingIndication()) - dispatch({ type: actionConstants.LOCK_METAMASK }) + dispatch(updateMetamaskState(newState)); + dispatch(hideLoadingIndication()); + dispatch({ type: actionConstants.LOCK_METAMASK }); }) .catch(() => { - dispatch(hideLoadingIndication()) - dispatch({ type: actionConstants.LOCK_METAMASK }) - }) - } + dispatch(hideLoadingIndication()); + dispatch({ type: actionConstants.LOCK_METAMASK }); + }); + }; } async function _setSelectedAddress(dispatch, address) { - log.debug(`background.setSelectedAddress`) - const tokens = await promisifiedBackground.setSelectedAddress(address) - dispatch(updateTokens(tokens)) + log.debug(`background.setSelectedAddress`); + const tokens = await promisifiedBackground.setSelectedAddress(address); + dispatch(updateTokens(tokens)); } export function setSelectedAddress(address) { return async (dispatch) => { - dispatch(showLoadingIndication()) - log.debug(`background.setSelectedAddress`) + dispatch(showLoadingIndication()); + log.debug(`background.setSelectedAddress`); try { - await _setSelectedAddress(dispatch, address) + await _setSelectedAddress(dispatch, address); } catch (error) { - dispatch(displayWarning(error.message)) - return + dispatch(displayWarning(error.message)); + return; } finally { - dispatch(hideLoadingIndication()) + dispatch(hideLoadingIndication()); } - } + }; } export function showAccountDetail(address) { return async (dispatch, getState) => { - dispatch(showLoadingIndication()) - log.debug(`background.setSelectedAddress`) + dispatch(showLoadingIndication()); + log.debug(`background.setSelectedAddress`); - const state = getState() + const state = getState(); const unconnectedAccountAccountAlertIsEnabled = getUnconnectedAccountAlertEnabledness( state, - ) - const activeTabOrigin = state.activeTab.origin - const selectedAddress = getSelectedAddress(state) + ); + const activeTabOrigin = state.activeTab.origin; + const selectedAddress = getSelectedAddress(state); const permittedAccountsForCurrentTab = getPermittedAccountsForCurrentTab( state, - ) + ); const currentTabIsConnectedToPreviousAddress = Boolean(activeTabOrigin) && - permittedAccountsForCurrentTab.includes(selectedAddress) + permittedAccountsForCurrentTab.includes(selectedAddress); const currentTabIsConnectedToNextAddress = Boolean(activeTabOrigin) && - permittedAccountsForCurrentTab.includes(address) + permittedAccountsForCurrentTab.includes(address); const switchingToUnconnectedAddress = currentTabIsConnectedToPreviousAddress && - !currentTabIsConnectedToNextAddress + !currentTabIsConnectedToNextAddress; try { - await _setSelectedAddress(dispatch, address) + await _setSelectedAddress(dispatch, address); } catch (error) { - dispatch(displayWarning(error.message)) - return + dispatch(displayWarning(error.message)); + return; } finally { - dispatch(hideLoadingIndication()) + dispatch(hideLoadingIndication()); } dispatch({ type: actionConstants.SHOW_ACCOUNT_DETAIL, value: address, - }) + }); if ( unconnectedAccountAccountAlertIsEnabled && switchingToUnconnectedAddress ) { - dispatch(switchedToUnconnectedAccount()) - await setUnconnectedAccountAlertShown(activeTabOrigin) + dispatch(switchedToUnconnectedAccount()); + await setUnconnectedAccountAlertShown(activeTabOrigin); } - } + }; } export function addPermittedAccount(origin, address) { @@ -1324,14 +1334,14 @@ export function addPermittedAccount(origin, address) { await new Promise((resolve, reject) => { background.addPermittedAccount(origin, address, (error) => { if (error) { - reject(error) - return + reject(error); + return; } - resolve() - }) - }) - await forceUpdateMetamaskState(dispatch) - } + resolve(); + }); + }); + await forceUpdateMetamaskState(dispatch); + }; } export function removePermittedAccount(origin, address) { @@ -1339,27 +1349,27 @@ export function removePermittedAccount(origin, address) { await new Promise((resolve, reject) => { background.removePermittedAccount(origin, address, (error) => { if (error) { - reject(error) - return + reject(error); + return; } - resolve() - }) - }) - await forceUpdateMetamaskState(dispatch) - } + resolve(); + }); + }); + await forceUpdateMetamaskState(dispatch); + }; } export function showAccountsPage() { return { type: actionConstants.SHOW_ACCOUNTS_PAGE, - } + }; } export function showConfTxPage({ id } = {}) { return { type: actionConstants.SHOW_CONF_TX_PAGE, id, - } + }; } export function addToken( @@ -1370,38 +1380,38 @@ export function addToken( dontShowLoadingIndicator, ) { return (dispatch) => { - !dontShowLoadingIndicator && dispatch(showLoadingIndication()) + !dontShowLoadingIndicator && dispatch(showLoadingIndication()); return new Promise((resolve, reject) => { background.addToken(address, symbol, decimals, image, (err, tokens) => { - dispatch(hideLoadingIndication()) + dispatch(hideLoadingIndication()); if (err) { - dispatch(displayWarning(err.message)) - reject(err) - return + dispatch(displayWarning(err.message)); + reject(err); + return; } - dispatch(updateTokens(tokens)) - resolve(tokens) - }) - }) - } + dispatch(updateTokens(tokens)); + resolve(tokens); + }); + }); + }; } export function removeToken(address) { return (dispatch) => { - dispatch(showLoadingIndication()) + dispatch(showLoadingIndication()); return new Promise((resolve, reject) => { background.removeToken(address, (err, tokens) => { - dispatch(hideLoadingIndication()) + dispatch(hideLoadingIndication()); if (err) { - dispatch(displayWarning(err.message)) - reject(err) - return + dispatch(displayWarning(err.message)); + reject(err); + return; } - dispatch(updateTokens(tokens)) - resolve(tokens) - }) - }) - } + dispatch(updateTokens(tokens)); + resolve(tokens); + }); + }); + }; } export function addTokens(tokens) { @@ -1411,62 +1421,62 @@ export function addTokens(tokens) { tokens.map(({ address, symbol, decimals }) => dispatch(addToken(address, symbol, decimals)), ), - ) + ); } return Promise.all( Object.entries(tokens).map(([_, { address, symbol, decimals }]) => dispatch(addToken(address, symbol, decimals)), ), - ) - } + ); + }; } export function removeSuggestedTokens() { return (dispatch) => { - dispatch(showLoadingIndication()) + dispatch(showLoadingIndication()); return new Promise((resolve) => { background.removeSuggestedTokens((err, suggestedTokens) => { - dispatch(hideLoadingIndication()) + dispatch(hideLoadingIndication()); if (err) { - dispatch(displayWarning(err.message)) + dispatch(displayWarning(err.message)); } - dispatch(clearPendingTokens()) + dispatch(clearPendingTokens()); if (getEnvironmentType() === ENVIRONMENT_TYPE_NOTIFICATION) { - global.platform.closeCurrentWindow() - return + global.platform.closeCurrentWindow(); + return; } - resolve(suggestedTokens) - }) + resolve(suggestedTokens); + }); }) .then(() => updateMetamaskStateFromBackground()) .then((suggestedTokens) => dispatch(updateMetamaskState({ ...suggestedTokens })), - ) - } + ); + }; } export function addKnownMethodData(fourBytePrefix, methodData) { return () => { - background.addKnownMethodData(fourBytePrefix, methodData) - } + background.addKnownMethodData(fourBytePrefix, methodData); + }; } export function updateTokens(newTokens) { return { type: actionConstants.UPDATE_TOKENS, newTokens, - } + }; } export function clearPendingTokens() { return { type: actionConstants.CLEAR_PENDING_TOKENS, - } + }; } export function createCancelTransaction(txId, customGasPrice) { - log.debug('background.cancelTransaction') - let newTxId + log.debug('background.cancelTransaction'); + let newTxId; return (dispatch) => { return new Promise((resolve, reject) => { @@ -1475,26 +1485,26 @@ export function createCancelTransaction(txId, customGasPrice) { customGasPrice, (err, newState) => { if (err) { - dispatch(displayWarning(err.message)) - reject(err) - return + dispatch(displayWarning(err.message)); + reject(err); + return; } - const { currentNetworkTxList } = newState - const { id } = currentNetworkTxList[currentNetworkTxList.length - 1] - newTxId = id - resolve(newState) + const { currentNetworkTxList } = newState; + const { id } = currentNetworkTxList[currentNetworkTxList.length - 1]; + newTxId = id; + resolve(newState); }, - ) + ); }) .then((newState) => dispatch(updateMetamaskState(newState))) - .then(() => newTxId) - } + .then(() => newTxId); + }; } export function createSpeedUpTransaction(txId, customGasPrice, customGasLimit) { - log.debug('background.createSpeedUpTransaction') - let newTx + log.debug('background.createSpeedUpTransaction'); + let newTx; return (dispatch) => { return new Promise((resolve, reject) => { @@ -1504,25 +1514,25 @@ export function createSpeedUpTransaction(txId, customGasPrice, customGasLimit) { customGasLimit, (err, newState) => { if (err) { - dispatch(displayWarning(err.message)) - reject(err) - return + dispatch(displayWarning(err.message)); + reject(err); + return; } - const { currentNetworkTxList } = newState - newTx = currentNetworkTxList[currentNetworkTxList.length - 1] - resolve(newState) + const { currentNetworkTxList } = newState; + newTx = currentNetworkTxList[currentNetworkTxList.length - 1]; + resolve(newState); }, - ) + ); }) .then((newState) => dispatch(updateMetamaskState(newState))) - .then(() => newTx) - } + .then(() => newTx); + }; } export function createRetryTransaction(txId, customGasPrice, customGasLimit) { - log.debug('background.createRetryTransaction') - let newTx + log.debug('background.createRetryTransaction'); + let newTx; return (dispatch) => { return new Promise((resolve, reject) => { @@ -1532,20 +1542,20 @@ export function createRetryTransaction(txId, customGasPrice, customGasLimit) { customGasLimit, (err, newState) => { if (err) { - dispatch(displayWarning(err.message)) - reject(err) - return + dispatch(displayWarning(err.message)); + reject(err); + return; } - const { currentNetworkTxList } = newState - newTx = currentNetworkTxList[currentNetworkTxList.length - 1] - resolve(newState) + const { currentNetworkTxList } = newState; + newTx = currentNetworkTxList[currentNetworkTxList.length - 1]; + resolve(newState); }, - ) + ); }) .then((newState) => dispatch(updateMetamaskState(newState))) - .then(() => newTx) - } + .then(() => newTx); + }; } // @@ -1554,24 +1564,24 @@ export function createRetryTransaction(txId, customGasPrice, customGasLimit) { export function setProviderType(type) { return async (dispatch) => { - log.debug(`background.setProviderType`, type) + log.debug(`background.setProviderType`, type); try { - await promisifiedBackground.setProviderType(type) + await promisifiedBackground.setProviderType(type); } catch (error) { - log.error(error) - dispatch(displayWarning('Had a problem changing networks!')) - return + log.error(error); + dispatch(displayWarning('Had a problem changing networks!')); + return; } - dispatch(updateProviderType(type)) - } + dispatch(updateProviderType(type)); + }; } export function updateProviderType(type) { return { type: actionConstants.SET_PROVIDER_TYPE, value: type, - } + }; } export function updateAndSetCustomRpc( @@ -1584,7 +1594,7 @@ export function updateAndSetCustomRpc( return async (dispatch) => { log.debug( `background.updateAndSetCustomRpc: ${newRpc} ${chainId} ${ticker} ${nickname}`, - ) + ); try { await promisifiedBackground.updateAndSetCustomRpc( @@ -1593,18 +1603,18 @@ export function updateAndSetCustomRpc( ticker, nickname || newRpc, rpcPrefs, - ) + ); } catch (error) { - log.error(error) - dispatch(displayWarning('Had a problem changing networks!')) - return + log.error(error); + dispatch(displayWarning('Had a problem changing networks!')); + return; } dispatch({ type: actionConstants.SET_RPC_TARGET, value: newRpc, - }) - } + }); + }; } export function editRpc( @@ -1616,13 +1626,13 @@ export function editRpc( rpcPrefs, ) { return async (dispatch) => { - log.debug(`background.delRpcTarget: ${oldRpc}`) + log.debug(`background.delRpcTarget: ${oldRpc}`); try { - promisifiedBackground.delCustomRpc(oldRpc) + promisifiedBackground.delCustomRpc(oldRpc); } catch (error) { - log.error(error) - dispatch(displayWarning('Had a problem removing network!')) - return + log.error(error); + dispatch(displayWarning('Had a problem removing network!')); + return; } try { @@ -1632,25 +1642,25 @@ export function editRpc( ticker, nickname || newRpc, rpcPrefs, - ) + ); } catch (error) { - log.error(error) - dispatch(displayWarning('Had a problem changing networks!')) - return + log.error(error); + dispatch(displayWarning('Had a problem changing networks!')); + return; } dispatch({ type: actionConstants.SET_RPC_TARGET, value: newRpc, - }) - } + }); + }; } export function setRpcTarget(newRpc, chainId, ticker = 'ETH', nickname) { return async (dispatch) => { log.debug( `background.setRpcTarget: ${newRpc} ${chainId} ${ticker} ${nickname}`, - ) + ); try { await promisifiedBackground.setCustomRpc( @@ -1658,66 +1668,66 @@ export function setRpcTarget(newRpc, chainId, ticker = 'ETH', nickname) { chainId, ticker, nickname || newRpc, - ) + ); } catch (error) { - log.error(error) - dispatch(displayWarning('Had a problem changing networks!')) + log.error(error); + dispatch(displayWarning('Had a problem changing networks!')); } - } + }; } export function rollbackToPreviousProvider() { return async (dispatch) => { try { - await promisifiedBackground.rollbackToPreviousProvider() + await promisifiedBackground.rollbackToPreviousProvider(); } catch (error) { - log.error(error) - dispatch(displayWarning('Had a problem changing networks!')) + log.error(error); + dispatch(displayWarning('Had a problem changing networks!')); } - } + }; } export function delRpcTarget(oldRpc) { return (dispatch) => { - log.debug(`background.delRpcTarget: ${oldRpc}`) + log.debug(`background.delRpcTarget: ${oldRpc}`); return new Promise((resolve, reject) => { background.delCustomRpc(oldRpc, (err) => { if (err) { - log.error(err) - dispatch(displayWarning('Had a problem removing network!')) - reject(err) - return + log.error(err); + dispatch(displayWarning('Had a problem removing network!')); + reject(err); + return; } - resolve() - }) - }) - } + resolve(); + }); + }); + }; } // Calls the addressBookController to add a new address. export function addToAddressBook(recipient, nickname = '', memo = '') { - log.debug(`background.addToAddressBook`) + log.debug(`background.addToAddressBook`); return async (dispatch, getState) => { - const { chainId } = getState().metamask.provider + const { chainId } = getState().metamask.provider; - let set + let set; try { set = await promisifiedBackground.setAddressBook( checksumAddress(recipient), nickname, chainId, memo, - ) + ); } catch (error) { - log.error(error) - dispatch(displayWarning('Address book failed to update')) - throw error + log.error(error); + dispatch(displayWarning('Address book failed to update')); + throw error; } if (!set) { - dispatch(displayWarning('Address book failed to update')) + dispatch(displayWarning('Address book failed to update')); } - } + }; } /** @@ -1725,40 +1735,40 @@ export function addToAddressBook(recipient, nickname = '', memo = '') { * @param {string} addressToRemove - Address of the entry to remove from the address book */ export function removeFromAddressBook(chainId, addressToRemove) { - log.debug(`background.removeFromAddressBook`) + log.debug(`background.removeFromAddressBook`); return async () => { await promisifiedBackground.removeFromAddressBook( chainId, checksumAddress(addressToRemove), - ) - } + ); + }; } export function showNetworkDropdown() { return { type: actionConstants.NETWORK_DROPDOWN_OPEN, - } + }; } export function hideNetworkDropdown() { return { type: actionConstants.NETWORK_DROPDOWN_CLOSE, - } + }; } export function showModal(payload) { return { type: actionConstants.MODAL_OPEN, payload, - } + }; } export function hideModal(payload) { return { type: actionConstants.MODAL_CLOSE, payload, - } + }; } export function closeCurrentNotificationWindow() { @@ -1767,17 +1777,17 @@ export function closeCurrentNotificationWindow() { getEnvironmentType() === ENVIRONMENT_TYPE_NOTIFICATION && !hasUnconfirmedTransactions(getState()) ) { - global.platform.closeCurrentWindow() + global.platform.closeCurrentWindow(); - dispatch(closeNotificationWindow()) + dispatch(closeNotificationWindow()); } - } + }; } export function closeNotificationWindow() { return { type: actionConstants.CLOSE_NOTIFICATION_WINDOW, - } + }; } export function showSidebar({ transitionName, type, props }) { @@ -1788,26 +1798,26 @@ export function showSidebar({ transitionName, type, props }) { type, props, }, - } + }; } export function hideSidebar() { return { type: actionConstants.SIDEBAR_CLOSE, - } + }; } export function showAlert(msg) { return { type: actionConstants.ALERT_OPEN, value: msg, - } + }; } export function hideAlert() { return { type: actionConstants.ALERT_CLOSE, - } + }; } /** @@ -1819,412 +1829,412 @@ export function qrCodeDetected(qrCodeData) { return { type: actionConstants.QR_CODE_DETECTED, value: qrCodeData, - } + }; } export function showLoadingIndication(message) { return { type: actionConstants.SHOW_LOADING, value: message, - } + }; } export function setHardwareWalletDefaultHdPath({ device, path }) { return { type: actionConstants.SET_HARDWARE_WALLET_DEFAULT_HD_PATH, value: { device, path }, - } + }; } export function hideLoadingIndication() { return { type: actionConstants.HIDE_LOADING, - } + }; } export function displayWarning(text) { return { type: actionConstants.DISPLAY_WARNING, value: text, - } + }; } export function hideWarning() { return { type: actionConstants.HIDE_WARNING, - } + }; } export function exportAccount(password, address) { return function (dispatch) { - dispatch(showLoadingIndication()) + dispatch(showLoadingIndication()); - log.debug(`background.verifyPassword`) + log.debug(`background.verifyPassword`); return new Promise((resolve, reject) => { background.verifyPassword(password, function (err) { if (err) { - log.error('Error in verifying password.') - dispatch(hideLoadingIndication()) - dispatch(displayWarning('Incorrect Password.')) - reject(err) - return + log.error('Error in verifying password.'); + dispatch(hideLoadingIndication()); + dispatch(displayWarning('Incorrect Password.')); + reject(err); + return; } - log.debug(`background.exportAccount`) + log.debug(`background.exportAccount`); background.exportAccount(address, function (err2, result) { - dispatch(hideLoadingIndication()) + dispatch(hideLoadingIndication()); if (err2) { - log.error(err2) - dispatch(displayWarning('Had a problem exporting the account.')) - reject(err2) - return + log.error(err2); + dispatch(displayWarning('Had a problem exporting the account.')); + reject(err2); + return; } - dispatch(showPrivateKey(result)) - resolve(result) - }) - }) - }) - } + dispatch(showPrivateKey(result)); + resolve(result); + }); + }); + }); + }; } export function exportAccounts(password, addresses) { return function (dispatch) { - log.debug(`background.submitPassword`) + log.debug(`background.submitPassword`); return new Promise((resolve, reject) => { background.submitPassword(password, function (err) { if (err) { - log.error('Error in submitting password.') - reject(err) - return + log.error('Error in submitting password.'); + reject(err); + return; } - log.debug(`background.exportAccounts`) + log.debug(`background.exportAccounts`); const accountPromises = addresses.map( (address) => new Promise((resolve2, reject2) => background.exportAccount(address, function (err2, result) { if (err2) { - log.error(err2) + log.error(err2); dispatch( displayWarning('Had a problem exporting the account.'), - ) - reject2(err2) - return + ); + reject2(err2); + return; } - resolve2(result) + resolve2(result); }), ), - ) - resolve(Promise.all(accountPromises)) - }) - }) - } + ); + resolve(Promise.all(accountPromises)); + }); + }); + }; } export function showPrivateKey(key) { return { type: actionConstants.SHOW_PRIVATE_KEY, value: key, - } + }; } export function setAccountLabel(account, label) { return (dispatch) => { - dispatch(showLoadingIndication()) - log.debug(`background.setAccountLabel`) + dispatch(showLoadingIndication()); + log.debug(`background.setAccountLabel`); return new Promise((resolve, reject) => { background.setAccountLabel(account, label, (err) => { - dispatch(hideLoadingIndication()) + dispatch(hideLoadingIndication()); if (err) { - dispatch(displayWarning(err.message)) - reject(err) - return + dispatch(displayWarning(err.message)); + reject(err); + return; } dispatch({ type: actionConstants.SET_ACCOUNT_LABEL, value: { account, label }, - }) - resolve(account) - }) - }) - } + }); + resolve(account); + }); + }); + }; } export function clearAccountDetails() { return { type: actionConstants.CLEAR_ACCOUNT_DETAILS, - } + }; } export function showSendTokenPage() { return { type: actionConstants.SHOW_SEND_TOKEN_PAGE, - } + }; } export function buyEth(opts) { return (dispatch) => { - const url = getBuyEthUrl(opts) - global.platform.openTab({ url }) + const url = getBuyEthUrl(opts); + global.platform.openTab({ url }); dispatch({ type: actionConstants.BUY_ETH, - }) - } + }); + }; } export function setFeatureFlag(feature, activated, notificationType) { return (dispatch) => { - dispatch(showLoadingIndication()) + dispatch(showLoadingIndication()); return new Promise((resolve, reject) => { background.setFeatureFlag( feature, activated, (err, updatedFeatureFlags) => { - dispatch(hideLoadingIndication()) + dispatch(hideLoadingIndication()); if (err) { - dispatch(displayWarning(err.message)) - reject(err) - return + dispatch(displayWarning(err.message)); + reject(err); + return; } - dispatch(updateFeatureFlags(updatedFeatureFlags)) - notificationType && dispatch(showModal({ name: notificationType })) - resolve(updatedFeatureFlags) + dispatch(updateFeatureFlags(updatedFeatureFlags)); + notificationType && dispatch(showModal({ name: notificationType })); + resolve(updatedFeatureFlags); }, - ) - }) - } + ); + }); + }; } export function updateFeatureFlags(updatedFeatureFlags) { return { type: actionConstants.UPDATE_FEATURE_FLAGS, value: updatedFeatureFlags, - } + }; } export function setPreference(preference, value) { return (dispatch) => { - dispatch(showLoadingIndication()) + dispatch(showLoadingIndication()); return new Promise((resolve, reject) => { background.setPreference(preference, value, (err, updatedPreferences) => { - dispatch(hideLoadingIndication()) + dispatch(hideLoadingIndication()); if (err) { - dispatch(displayWarning(err.message)) - reject(err) - return + dispatch(displayWarning(err.message)); + reject(err); + return; } - dispatch(updatePreferences(updatedPreferences)) - resolve(updatedPreferences) - }) - }) - } + dispatch(updatePreferences(updatedPreferences)); + resolve(updatedPreferences); + }); + }); + }; } export function updatePreferences(value) { return { type: actionConstants.UPDATE_PREFERENCES, value, - } + }; } export function setDefaultHomeActiveTabName(value) { return async () => { - await promisifiedBackground.setDefaultHomeActiveTabName(value) - } + await promisifiedBackground.setDefaultHomeActiveTabName(value); + }; } export function setUseNativeCurrencyAsPrimaryCurrencyPreference(value) { - return setPreference('useNativeCurrencyAsPrimaryCurrency', value) + return setPreference('useNativeCurrencyAsPrimaryCurrency', value); } export function setShowFiatConversionOnTestnetsPreference(value) { - return setPreference('showFiatInTestnets', value) + return setPreference('showFiatInTestnets', value); } export function setAutoLockTimeLimit(value) { - return setPreference('autoLockTimeLimit', value) + return setPreference('autoLockTimeLimit', value); } export function setCompletedOnboarding() { return async (dispatch) => { - dispatch(showLoadingIndication()) + dispatch(showLoadingIndication()); try { - await promisifiedBackground.completeOnboarding() - dispatch(completeOnboarding()) + await promisifiedBackground.completeOnboarding(); + dispatch(completeOnboarding()); } catch (err) { - dispatch(displayWarning(err.message)) - throw err + dispatch(displayWarning(err.message)); + throw err; } finally { - dispatch(hideLoadingIndication()) + dispatch(hideLoadingIndication()); } - } + }; } export function completeOnboarding() { return { type: actionConstants.COMPLETE_ONBOARDING, - } + }; } export function setMouseUserState(isMouseUser) { return { type: actionConstants.SET_MOUSE_USER_STATE, value: isMouseUser, - } + }; } export async function forceUpdateMetamaskState(dispatch) { - log.debug(`background.getState`) + log.debug(`background.getState`); - let newState + let newState; try { - newState = await promisifiedBackground.getState() + newState = await promisifiedBackground.getState(); } catch (error) { - dispatch(displayWarning(error.message)) - throw error + dispatch(displayWarning(error.message)); + throw error; } - dispatch(updateMetamaskState(newState)) - return newState + dispatch(updateMetamaskState(newState)); + return newState; } export function toggleAccountMenu() { return { type: actionConstants.TOGGLE_ACCOUNT_MENU, - } + }; } export function setParticipateInMetaMetrics(val) { return (dispatch) => { - log.debug(`background.setParticipateInMetaMetrics`) + log.debug(`background.setParticipateInMetaMetrics`); return new Promise((resolve, reject) => { background.setParticipateInMetaMetrics(val, (err, metaMetricsId) => { - log.debug(err) + log.debug(err); if (err) { - dispatch(displayWarning(err.message)) - reject(err) - return + dispatch(displayWarning(err.message)); + reject(err); + return; } dispatch({ type: actionConstants.SET_PARTICIPATE_IN_METAMETRICS, value: val, - }) - resolve([val, metaMetricsId]) - }) - }) - } + }); + resolve([val, metaMetricsId]); + }); + }); + }; } export function setMetaMetricsSendCount(val) { return (dispatch) => { - log.debug(`background.setMetaMetricsSendCount`) + log.debug(`background.setMetaMetricsSendCount`); return new Promise((resolve, reject) => { background.setMetaMetricsSendCount(val, (err) => { if (err) { - dispatch(displayWarning(err.message)) - reject(err) - return + dispatch(displayWarning(err.message)); + reject(err); + return; } dispatch({ type: actionConstants.SET_METAMETRICS_SEND_COUNT, value: val, - }) - resolve(val) - }) - }) - } + }); + resolve(val); + }); + }); + }; } export function setUseBlockie(val) { return (dispatch) => { - dispatch(showLoadingIndication()) - log.debug(`background.setUseBlockie`) + dispatch(showLoadingIndication()); + log.debug(`background.setUseBlockie`); background.setUseBlockie(val, (err) => { - dispatch(hideLoadingIndication()) + dispatch(hideLoadingIndication()); if (err) { - dispatch(displayWarning(err.message)) + dispatch(displayWarning(err.message)); } - }) + }); dispatch({ type: actionConstants.SET_USE_BLOCKIE, value: val, - }) - } + }); + }; } export function setUseNonceField(val) { return (dispatch) => { - dispatch(showLoadingIndication()) - log.debug(`background.setUseNonceField`) + dispatch(showLoadingIndication()); + log.debug(`background.setUseNonceField`); background.setUseNonceField(val, (err) => { - dispatch(hideLoadingIndication()) + dispatch(hideLoadingIndication()); if (err) { - dispatch(displayWarning(err.message)) + dispatch(displayWarning(err.message)); } - }) + }); dispatch({ type: actionConstants.SET_USE_NONCEFIELD, value: val, - }) - } + }); + }; } export function setUsePhishDetect(val) { return (dispatch) => { - dispatch(showLoadingIndication()) - log.debug(`background.setUsePhishDetect`) + dispatch(showLoadingIndication()); + log.debug(`background.setUsePhishDetect`); background.setUsePhishDetect(val, (err) => { - dispatch(hideLoadingIndication()) + dispatch(hideLoadingIndication()); if (err) { - dispatch(displayWarning(err.message)) + dispatch(displayWarning(err.message)); } - }) - } + }); + }; } export function setIpfsGateway(val) { return (dispatch) => { - dispatch(showLoadingIndication()) - log.debug(`background.setIpfsGateway`) + dispatch(showLoadingIndication()); + log.debug(`background.setIpfsGateway`); background.setIpfsGateway(val, (err) => { - dispatch(hideLoadingIndication()) + dispatch(hideLoadingIndication()); if (err) { - dispatch(displayWarning(err.message)) + dispatch(displayWarning(err.message)); } else { dispatch({ type: actionConstants.SET_IPFS_GATEWAY, value: val, - }) + }); } - }) - } + }); + }; } export function updateCurrentLocale(key) { return async (dispatch) => { - dispatch(showLoadingIndication()) + dispatch(showLoadingIndication()); try { - await loadRelativeTimeFormatLocaleData(key) - const localeMessages = await fetchLocale(key) - const textDirection = await promisifiedBackground.setCurrentLocale(key) - await switchDirection(textDirection) - dispatch(setCurrentLocale(key, localeMessages)) + await loadRelativeTimeFormatLocaleData(key); + const localeMessages = await fetchLocale(key); + const textDirection = await promisifiedBackground.setCurrentLocale(key); + await switchDirection(textDirection); + dispatch(setCurrentLocale(key, localeMessages)); } catch (error) { - dispatch(displayWarning(error.message)) - return + dispatch(displayWarning(error.message)); + return; } finally { - dispatch(hideLoadingIndication()) + dispatch(hideLoadingIndication()); } - } + }; } export function setCurrentLocale(locale, messages) { @@ -2234,12 +2244,12 @@ export function setCurrentLocale(locale, messages) { locale, messages, }, - } + }; } export function setPendingTokens(pendingTokens) { - const { customToken = {}, selectedTokens = {} } = pendingTokens - const { address, symbol, decimals } = customToken + const { customToken = {}, selectedTokens = {} } = pendingTokens; + const { address, symbol, decimals } = customToken; const tokens = address && symbol && decimals ? { @@ -2249,27 +2259,27 @@ export function setPendingTokens(pendingTokens) { isCustom: true, }, } - : selectedTokens + : selectedTokens; Object.keys(tokens).forEach((tokenAddress) => { tokens[tokenAddress].unlisted = !LISTED_CONTRACT_ADDRESSES.includes( tokenAddress.toLowerCase(), - ) - }) + ); + }); return { type: actionConstants.SET_PENDING_TOKENS, payload: tokens, - } + }; } // Swaps export function setSwapsLiveness(swapsFeatureIsLive) { return async (dispatch) => { - await promisifiedBackground.setSwapsLiveness(swapsFeatureIsLive) - await forceUpdateMetamaskState(dispatch) - } + await promisifiedBackground.setSwapsLiveness(swapsFeatureIsLive); + await forceUpdateMetamaskState(dispatch); + }; } export function fetchAndSetQuotes(fetchParams, fetchParamsMetaData) { @@ -2280,117 +2290,117 @@ export function fetchAndSetQuotes(fetchParams, fetchParamsMetaData) { ] = await promisifiedBackground.fetchAndSetQuotes( fetchParams, fetchParamsMetaData, - ) - await forceUpdateMetamaskState(dispatch) - return [quotes, selectedAggId] - } + ); + await forceUpdateMetamaskState(dispatch); + return [quotes, selectedAggId]; + }; } export function setSelectedQuoteAggId(aggId) { return async (dispatch) => { - await promisifiedBackground.setSelectedQuoteAggId(aggId) - await forceUpdateMetamaskState(dispatch) - } + await promisifiedBackground.setSelectedQuoteAggId(aggId); + await forceUpdateMetamaskState(dispatch); + }; } export function setSwapsTokens(tokens) { return async (dispatch) => { - await promisifiedBackground.setSwapsTokens(tokens) - await forceUpdateMetamaskState(dispatch) - } + await promisifiedBackground.setSwapsTokens(tokens); + await forceUpdateMetamaskState(dispatch); + }; } export function resetBackgroundSwapsState() { return async (dispatch) => { - const id = await promisifiedBackground.resetSwapsState() - await forceUpdateMetamaskState(dispatch) - return id - } + const id = await promisifiedBackground.resetSwapsState(); + await forceUpdateMetamaskState(dispatch); + return id; + }; } export function setCustomApproveTxData(data) { return async (dispatch) => { - await promisifiedBackground.setCustomApproveTxData(data) - await forceUpdateMetamaskState(dispatch) - } + await promisifiedBackground.setCustomApproveTxData(data); + await forceUpdateMetamaskState(dispatch); + }; } export function setSwapsTxGasPrice(gasPrice) { return async (dispatch) => { - await promisifiedBackground.setSwapsTxGasPrice(gasPrice) - await forceUpdateMetamaskState(dispatch) - } + await promisifiedBackground.setSwapsTxGasPrice(gasPrice); + await forceUpdateMetamaskState(dispatch); + }; } export function setSwapsTxGasLimit(gasLimit) { return async (dispatch) => { - await promisifiedBackground.setSwapsTxGasLimit(gasLimit, true) - await forceUpdateMetamaskState(dispatch) - } + await promisifiedBackground.setSwapsTxGasLimit(gasLimit, true); + await forceUpdateMetamaskState(dispatch); + }; } export function customSwapsGasParamsUpdated(gasLimit, gasPrice) { return async (dispatch) => { - await promisifiedBackground.setSwapsTxGasPrice(gasPrice) - await promisifiedBackground.setSwapsTxGasLimit(gasLimit, true) - await forceUpdateMetamaskState(dispatch) - } + await promisifiedBackground.setSwapsTxGasPrice(gasPrice); + await promisifiedBackground.setSwapsTxGasLimit(gasLimit, true); + await forceUpdateMetamaskState(dispatch); + }; } export function setTradeTxId(tradeTxId) { return async (dispatch) => { - await promisifiedBackground.setTradeTxId(tradeTxId) - await forceUpdateMetamaskState(dispatch) - } + await promisifiedBackground.setTradeTxId(tradeTxId); + await forceUpdateMetamaskState(dispatch); + }; } export function setApproveTxId(approveTxId) { return async (dispatch) => { - await promisifiedBackground.setApproveTxId(approveTxId) - await forceUpdateMetamaskState(dispatch) - } + await promisifiedBackground.setApproveTxId(approveTxId); + await forceUpdateMetamaskState(dispatch); + }; } export function safeRefetchQuotes() { return async (dispatch) => { - await promisifiedBackground.safeRefetchQuotes() - await forceUpdateMetamaskState(dispatch) - } + await promisifiedBackground.safeRefetchQuotes(); + await forceUpdateMetamaskState(dispatch); + }; } export function stopPollingForQuotes() { return async (dispatch) => { - await promisifiedBackground.stopPollingForQuotes() - await forceUpdateMetamaskState(dispatch) - } + await promisifiedBackground.stopPollingForQuotes(); + await forceUpdateMetamaskState(dispatch); + }; } export function setBackgroundSwapRouteState(routeState) { return async (dispatch) => { - await promisifiedBackground.setBackgroundSwapRouteState(routeState) - await forceUpdateMetamaskState(dispatch) - } + await promisifiedBackground.setBackgroundSwapRouteState(routeState); + await forceUpdateMetamaskState(dispatch); + }; } export function resetSwapsPostFetchState() { return async (dispatch) => { - await promisifiedBackground.resetPostFetchState() - await forceUpdateMetamaskState(dispatch) - } + await promisifiedBackground.resetPostFetchState(); + await forceUpdateMetamaskState(dispatch); + }; } export function setSwapsErrorKey(errorKey) { return async (dispatch) => { - await promisifiedBackground.setSwapsErrorKey(errorKey) - await forceUpdateMetamaskState(dispatch) - } + await promisifiedBackground.setSwapsErrorKey(errorKey); + await forceUpdateMetamaskState(dispatch); + }; } export function setInitialGasEstimate(initialAggId) { return async (dispatch) => { - await promisifiedBackground.setInitialGasEstimate(initialAggId) - await forceUpdateMetamaskState(dispatch) - } + await promisifiedBackground.setInitialGasEstimate(initialAggId); + await forceUpdateMetamaskState(dispatch); + }; } // Permissions @@ -2399,10 +2409,10 @@ export function requestAccountsPermissionWithId(origin) { return async (dispatch) => { const id = await promisifiedBackground.requestAccountsPermissionWithId( origin, - ) - await forceUpdateMetamaskState(dispatch) - return id - } + ); + await forceUpdateMetamaskState(dispatch); + return id; + }; } /** @@ -2412,8 +2422,8 @@ export function requestAccountsPermissionWithId(origin) { */ export function approvePermissionsRequest(request, accounts) { return () => { - background.approvePermissionsRequest(request, accounts) - } + background.approvePermissionsRequest(request, accounts); + }; } /** @@ -2425,14 +2435,14 @@ export function rejectPermissionsRequest(requestId) { return new Promise((resolve, reject) => { background.rejectPermissionsRequest(requestId, (err) => { if (err) { - dispatch(displayWarning(err.message)) - reject(err) - return + dispatch(displayWarning(err.message)); + reject(err); + return; } - forceUpdateMetamaskState(dispatch).then(resolve).catch(reject) - }) - }) - } + forceUpdateMetamaskState(dispatch).then(resolve).catch(reject); + }); + }); + }; } /** @@ -2440,8 +2450,8 @@ export function rejectPermissionsRequest(requestId) { */ export function removePermissionsFor(domains) { return () => { - background.removePermissionsFor(domains) - } + background.removePermissionsFor(domains); + }; } /** @@ -2449,98 +2459,98 @@ export function removePermissionsFor(domains) { */ export function clearPermissions() { return () => { - background.clearPermissions() - } + background.clearPermissions(); + }; } export function setFirstTimeFlowType(type) { return (dispatch) => { - log.debug(`background.setFirstTimeFlowType`) + log.debug(`background.setFirstTimeFlowType`); background.setFirstTimeFlowType(type, (err) => { if (err) { - dispatch(displayWarning(err.message)) + dispatch(displayWarning(err.message)); } - }) + }); dispatch({ type: actionConstants.SET_FIRST_TIME_FLOW_TYPE, value: type, - }) - } + }); + }; } export function setSelectedSettingsRpcUrl(newRpcUrl) { return { type: actionConstants.SET_SELECTED_SETTINGS_RPC_URL, value: newRpcUrl, - } + }; } export function setNetworksTabAddMode(isInAddMode) { return { type: actionConstants.SET_NETWORKS_TAB_ADD_MODE, value: isInAddMode, - } + }; } export function setLastActiveTime() { return (dispatch) => { background.setLastActiveTime((err) => { if (err) { - dispatch(displayWarning(err.message)) + dispatch(displayWarning(err.message)); } - }) - } + }); + }; } export function setConnectedStatusPopoverHasBeenShown() { return () => { background.setConnectedStatusPopoverHasBeenShown((err) => { if (err) { - throw new Error(err.message) + throw new Error(err.message); } - }) - } + }); + }; } export function setSwapsWelcomeMessageHasBeenShown() { return () => { background.setSwapsWelcomeMessageHasBeenShown((err) => { if (err) { - throw new Error(err.message) + throw new Error(err.message); } - }) - } + }); + }; } export async function setAlertEnabledness(alertId, enabledness) { - await promisifiedBackground.setAlertEnabledness(alertId, enabledness) + await promisifiedBackground.setAlertEnabledness(alertId, enabledness); } export async function setUnconnectedAccountAlertShown(origin) { - await promisifiedBackground.setUnconnectedAccountAlertShown(origin) + await promisifiedBackground.setUnconnectedAccountAlertShown(origin); } export async function setWeb3ShimUsageAlertDismissed(origin) { - await promisifiedBackground.setWeb3ShimUsageAlertDismissed(origin) + await promisifiedBackground.setWeb3ShimUsageAlertDismissed(origin); } export function loadingMethodDataStarted() { return { type: actionConstants.LOADING_METHOD_DATA_STARTED, - } + }; } export function loadingMethodDataFinished() { return { type: actionConstants.LOADING_METHOD_DATA_FINISHED, - } + }; } export function getContractMethodData(data = '') { return (dispatch, getState) => { - const prefixedData = addHexPrefix(data) - const fourBytePrefix = prefixedData.slice(0, 10) - const { knownMethodData } = getState().metamask + const prefixedData = addHexPrefix(data); + const fourBytePrefix = prefixedData.slice(0, 10); + const { knownMethodData } = getState().metamask; if ( (knownMethodData && @@ -2548,72 +2558,72 @@ export function getContractMethodData(data = '') { Object.keys(knownMethodData[fourBytePrefix]).length !== 0) || fourBytePrefix === '0x' ) { - return Promise.resolve(knownMethodData[fourBytePrefix]) + return Promise.resolve(knownMethodData[fourBytePrefix]); } - dispatch(loadingMethodDataStarted()) - log.debug(`loadingMethodData`) + dispatch(loadingMethodDataStarted()); + log.debug(`loadingMethodData`); return getMethodDataAsync(fourBytePrefix).then(({ name, params }) => { - dispatch(loadingMethodDataFinished()) - background.addKnownMethodData(fourBytePrefix, { name, params }) - return { name, params } - }) - } + dispatch(loadingMethodDataFinished()); + background.addKnownMethodData(fourBytePrefix, { name, params }); + return { name, params }; + }); + }; } export function loadingTokenParamsStarted() { return { type: actionConstants.LOADING_TOKEN_PARAMS_STARTED, - } + }; } export function loadingTokenParamsFinished() { return { type: actionConstants.LOADING_TOKEN_PARAMS_FINISHED, - } + }; } export function getTokenParams(tokenAddress) { return (dispatch, getState) => { - const existingTokens = getState().metamask.tokens + const existingTokens = getState().metamask.tokens; const existingToken = existingTokens.find( ({ address }) => tokenAddress === address, - ) + ); if (existingToken) { return Promise.resolve({ symbol: existingToken.symbol, decimals: existingToken.decimals, - }) + }); } - dispatch(loadingTokenParamsStarted()) - log.debug(`loadingTokenParams`) + dispatch(loadingTokenParamsStarted()); + log.debug(`loadingTokenParams`); return fetchSymbolAndDecimals(tokenAddress, existingTokens).then( ({ symbol, decimals }) => { - dispatch(addToken(tokenAddress, symbol, Number(decimals))) - dispatch(loadingTokenParamsFinished()) + dispatch(addToken(tokenAddress, symbol, Number(decimals))); + dispatch(loadingTokenParamsFinished()); }, - ) - } + ); + }; } export function setSeedPhraseBackedUp(seedPhraseBackupState) { return (dispatch) => { - log.debug(`background.setSeedPhraseBackedUp`) + log.debug(`background.setSeedPhraseBackedUp`); return new Promise((resolve, reject) => { background.setSeedPhraseBackedUp(seedPhraseBackupState, (err) => { if (err) { - dispatch(displayWarning(err.message)) - reject(err) - return + dispatch(displayWarning(err.message)); + reject(err); + return; } - forceUpdateMetamaskState(dispatch).then(resolve).catch(reject) - }) - }) - } + forceUpdateMetamaskState(dispatch).then(resolve).catch(reject); + }); + }); + }; } export function initializeThreeBox() { @@ -2621,14 +2631,14 @@ export function initializeThreeBox() { return new Promise((resolve, reject) => { background.initializeThreeBox((err) => { if (err) { - dispatch(displayWarning(err.message)) - reject(err) - return + dispatch(displayWarning(err.message)); + reject(err); + return; } - resolve() - }) - }) - } + resolve(); + }); + }); + }; } export function setShowRestorePromptToFalse() { @@ -2636,14 +2646,14 @@ export function setShowRestorePromptToFalse() { return new Promise((resolve, reject) => { background.setShowRestorePromptToFalse((err) => { if (err) { - dispatch(displayWarning(err.message)) - reject(err) - return + dispatch(displayWarning(err.message)); + reject(err); + return; } - resolve() - }) - }) - } + resolve(); + }); + }); + }; } export function turnThreeBoxSyncingOn() { @@ -2651,14 +2661,14 @@ export function turnThreeBoxSyncingOn() { return new Promise((resolve, reject) => { background.turnThreeBoxSyncingOn((err) => { if (err) { - dispatch(displayWarning(err.message)) - reject(err) - return + dispatch(displayWarning(err.message)); + reject(err); + return; } - resolve() - }) - }) - } + resolve(); + }); + }); + }; } export function restoreFromThreeBox(accountAddress) { @@ -2666,14 +2676,14 @@ export function restoreFromThreeBox(accountAddress) { return new Promise((resolve, reject) => { background.restoreFromThreeBox(accountAddress, (err) => { if (err) { - dispatch(displayWarning(err.message)) - reject(err) - return + dispatch(displayWarning(err.message)); + reject(err); + return; } - resolve() - }) - }) - } + resolve(); + }); + }); + }; } export function getThreeBoxLastUpdated() { @@ -2681,14 +2691,14 @@ export function getThreeBoxLastUpdated() { return new Promise((resolve, reject) => { background.getThreeBoxLastUpdated((err, lastUpdated) => { if (err) { - dispatch(displayWarning(err.message)) - reject(err) - return + dispatch(displayWarning(err.message)); + reject(err); + return; } - resolve(lastUpdated) - }) - }) - } + resolve(lastUpdated); + }); + }); + }; } export function setThreeBoxSyncingPermission(threeBoxSyncingAllowed) { @@ -2696,88 +2706,88 @@ export function setThreeBoxSyncingPermission(threeBoxSyncingAllowed) { return new Promise((resolve, reject) => { background.setThreeBoxSyncingPermission(threeBoxSyncingAllowed, (err) => { if (err) { - dispatch(displayWarning(err.message)) - reject(err) - return + dispatch(displayWarning(err.message)); + reject(err); + return; } - resolve() - }) - }) - } + resolve(); + }); + }); + }; } export function turnThreeBoxSyncingOnAndInitialize() { return async (dispatch) => { - await dispatch(setThreeBoxSyncingPermission(true)) - await dispatch(turnThreeBoxSyncingOn()) - await dispatch(initializeThreeBox(true)) - } + await dispatch(setThreeBoxSyncingPermission(true)); + await dispatch(turnThreeBoxSyncingOn()); + await dispatch(initializeThreeBox(true)); + }; } export function setNextNonce(nextNonce) { return { type: actionConstants.SET_NEXT_NONCE, value: nextNonce, - } + }; } export function getNextNonce() { return (dispatch, getState) => { - const address = getState().metamask.selectedAddress + const address = getState().metamask.selectedAddress; return new Promise((resolve, reject) => { background.getNextNonce(address, (err, nextNonce) => { if (err) { - dispatch(displayWarning(err.message)) - reject(err) - return + dispatch(displayWarning(err.message)); + reject(err); + return; } - dispatch(setNextNonce(nextNonce)) - resolve(nextNonce) - }) - }) - } + dispatch(setNextNonce(nextNonce)); + resolve(nextNonce); + }); + }); + }; } export function setRequestAccountTabIds(requestAccountTabIds) { return { type: actionConstants.SET_REQUEST_ACCOUNT_TABS, value: requestAccountTabIds, - } + }; } export function getRequestAccountTabIds() { return async (dispatch) => { - const requestAccountTabIds = await promisifiedBackground.getRequestAccountTabIds() - dispatch(setRequestAccountTabIds(requestAccountTabIds)) - } + const requestAccountTabIds = await promisifiedBackground.getRequestAccountTabIds(); + dispatch(setRequestAccountTabIds(requestAccountTabIds)); + }; } export function setOpenMetamaskTabsIDs(openMetaMaskTabIDs) { return { type: actionConstants.SET_OPEN_METAMASK_TAB_IDS, value: openMetaMaskTabIDs, - } + }; } export function getOpenMetamaskTabsIds() { return async (dispatch) => { - const openMetaMaskTabIDs = await promisifiedBackground.getOpenMetamaskTabsIds() - dispatch(setOpenMetamaskTabsIDs(openMetaMaskTabIDs)) - } + const openMetaMaskTabIDs = await promisifiedBackground.getOpenMetamaskTabsIds(); + dispatch(setOpenMetamaskTabsIDs(openMetaMaskTabIDs)); + }; } export function setCurrentWindowTab(currentWindowTab) { return { type: actionConstants.SET_CURRENT_WINDOW_TAB, value: currentWindowTab, - } + }; } export function getCurrentWindowTab() { return async (dispatch) => { - const currentWindowTab = await global.platform.currentTab() - dispatch(setCurrentWindowTab(currentWindowTab)) - } + const currentWindowTab = await global.platform.currentTab(); + dispatch(setCurrentWindowTab(currentWindowTab)); + }; } // MetaMetrics @@ -2794,7 +2804,7 @@ export function getCurrentWindowTab() { * @returns {Promise} */ export function trackMetaMetricsEvent(payload, options) { - return promisifiedBackground.trackMetaMetricsEvent(payload, options) + return promisifiedBackground.trackMetaMetricsEvent(payload, options); } /** @@ -2803,5 +2813,5 @@ export function trackMetaMetricsEvent(payload, options) { * @returns {void} */ export function trackMetaMetricsPage(payload, options) { - return promisifiedBackground.trackMetaMetricsPage(payload, options) + return promisifiedBackground.trackMetaMetricsPage(payload, options); } diff --git a/ui/app/store/store.js b/ui/app/store/store.js index 1feddc48e..75cbbab10 100644 --- a/ui/app/store/store.js +++ b/ui/app/store/store.js @@ -1,7 +1,7 @@ -import { createStore, applyMiddleware } from 'redux' -import thunkMiddleware from 'redux-thunk' -import { composeWithDevTools } from 'remote-redux-devtools' -import rootReducer from '../ducks' +import { createStore, applyMiddleware } from 'redux'; +import thunkMiddleware from 'redux-thunk'; +import { composeWithDevTools } from 'remote-redux-devtools'; +import rootReducer from '../ducks'; export default function configureStore(initialState) { const composeEnhancers = composeWithDevTools({ @@ -9,10 +9,10 @@ export default function configureStore(initialState) { hostname: 'localhost', port: 8000, realtime: Boolean(process.env.METAMASK_DEBUG), - }) + }); return createStore( rootReducer, initialState, composeEnhancers(applyMiddleware(thunkMiddleware)), - ) + ); } diff --git a/ui/index.js b/ui/index.js index 660209804..b21c62959 100644 --- a/ui/index.js +++ b/ui/index.js @@ -1,67 +1,67 @@ -import copyToClipboard from 'copy-to-clipboard' -import log from 'loglevel' -import { clone } from 'lodash' -import React from 'react' -import { render } from 'react-dom' -import { getEnvironmentType } from '../app/scripts/lib/util' -import { ALERT_TYPES } from '../shared/constants/alerts' -import { SENTRY_STATE } from '../app/scripts/lib/setupSentry' -import { ENVIRONMENT_TYPE_POPUP } from '../shared/constants/app' -import Root from './app/pages' -import * as actions from './app/store/actions' -import configureStore from './app/store/store' -import txHelper from './lib/tx-helper' +import copyToClipboard from 'copy-to-clipboard'; +import log from 'loglevel'; +import { clone } from 'lodash'; +import React from 'react'; +import { render } from 'react-dom'; +import { getEnvironmentType } from '../app/scripts/lib/util'; +import { ALERT_TYPES } from '../shared/constants/alerts'; +import { SENTRY_STATE } from '../app/scripts/lib/setupSentry'; +import { ENVIRONMENT_TYPE_POPUP } from '../shared/constants/app'; +import Root from './app/pages'; +import * as actions from './app/store/actions'; +import configureStore from './app/store/store'; +import txHelper from './lib/tx-helper'; import { fetchLocale, loadRelativeTimeFormatLocaleData, -} from './app/helpers/utils/i18n-helper' -import switchDirection from './app/helpers/utils/switch-direction' +} from './app/helpers/utils/i18n-helper'; +import switchDirection from './app/helpers/utils/switch-direction'; import { getPermittedAccountsForCurrentTab, getSelectedAddress, -} from './app/selectors' -import { ALERT_STATE } from './app/ducks/alerts' +} from './app/selectors'; +import { ALERT_STATE } from './app/ducks/alerts'; import { getUnconnectedAccountAlertEnabledness, getUnconnectedAccountAlertShown, -} from './app/ducks/metamask/metamask' +} from './app/ducks/metamask/metamask'; -log.setLevel(global.METAMASK_DEBUG ? 'debug' : 'warn') +log.setLevel(global.METAMASK_DEBUG ? 'debug' : 'warn'); export default function launchMetamaskUi(opts, cb) { - const { backgroundConnection } = opts - actions._setBackgroundConnection(backgroundConnection) + const { backgroundConnection } = opts; + actions._setBackgroundConnection(backgroundConnection); // check if we are unlocked first backgroundConnection.getState(function (err, metamaskState) { if (err) { - cb(err) - return + cb(err); + return; } startApp(metamaskState, backgroundConnection, opts).then((store) => { - setupDebuggingHelpers(store) - cb(null, store) - }) - }) + setupDebuggingHelpers(store); + cb(null, store); + }); + }); } async function startApp(metamaskState, backgroundConnection, opts) { // parse opts if (!metamaskState.featureFlags) { - metamaskState.featureFlags = {} + metamaskState.featureFlags = {}; } const currentLocaleMessages = metamaskState.currentLocale ? await fetchLocale(metamaskState.currentLocale) - : {} - const enLocaleMessages = await fetchLocale('en') + : {}; + const enLocaleMessages = await fetchLocale('en'); - await loadRelativeTimeFormatLocaleData('en') + await loadRelativeTimeFormatLocaleData('en'); if (metamaskState.currentLocale) { - await loadRelativeTimeFormatLocaleData(metamaskState.currentLocale) + await loadRelativeTimeFormatLocaleData(metamaskState.currentLocale); } if (metamaskState.textDirection === 'rtl') { - await switchDirection('rtl') + await switchDirection('rtl'); } const draftInitialState = { @@ -77,20 +77,20 @@ async function startApp(metamaskState, backgroundConnection, opts) { current: currentLocaleMessages, en: enLocaleMessages, }, - } + }; if (getEnvironmentType() === ENVIRONMENT_TYPE_POPUP) { - const { origin } = draftInitialState.activeTab + const { origin } = draftInitialState.activeTab; const permittedAccountsForCurrentTab = getPermittedAccountsForCurrentTab( draftInitialState, - ) - const selectedAddress = getSelectedAddress(draftInitialState) + ); + const selectedAddress = getSelectedAddress(draftInitialState); const unconnectedAccountAlertShownOrigins = getUnconnectedAccountAlertShown( draftInitialState, - ) + ); const unconnectedAccountAlertIsEnabled = getUnconnectedAccountAlertEnabledness( draftInitialState, - ) + ); if ( origin && @@ -101,12 +101,12 @@ async function startApp(metamaskState, backgroundConnection, opts) { ) { draftInitialState[ALERT_TYPES.unconnectedAccount] = { state: ALERT_STATE.OPEN, - } - actions.setUnconnectedAccountAlertShown(origin) + }; + actions.setUnconnectedAccountAlertShown(origin); } } - const store = configureStore(draftInitialState) + const store = configureStore(draftInitialState); // if unconfirmed txs, start on txConf page const unapprovedTxsAll = txHelper( @@ -117,37 +117,37 @@ async function startApp(metamaskState, backgroundConnection, opts) { metamaskState.unapprovedEncryptionPublicKeyMsgs, metamaskState.unapprovedTypedMessages, metamaskState.network, - ) - const numberOfUnapprovedTx = unapprovedTxsAll.length + ); + const numberOfUnapprovedTx = unapprovedTxsAll.length; if (numberOfUnapprovedTx > 0) { store.dispatch( actions.showConfTxPage({ id: unapprovedTxsAll[0].id, }), - ) + ); } backgroundConnection.on('update', function (state) { - store.dispatch(actions.updateMetamaskState(state)) - }) + store.dispatch(actions.updateMetamaskState(state)); + }); // global metamask api - used by tooling global.metamask = { updateCurrentLocale: (code) => { - store.dispatch(actions.updateCurrentLocale(code)) + store.dispatch(actions.updateCurrentLocale(code)); }, setProviderType: (type) => { - store.dispatch(actions.setProviderType(type)) + store.dispatch(actions.setProviderType(type)); }, setFeatureFlag: (key, value) => { - store.dispatch(actions.setFeatureFlag(key, value)) + store.dispatch(actions.setFeatureFlag(key, value)); }, - } + }; // start app - render(, opts.container) + render(, opts.container); - return store + return store; } /** @@ -165,54 +165,54 @@ async function startApp(metamaskState, backgroundConnection, opts) { function maskObject(object, mask) { return Object.keys(object).reduce((state, key) => { if (mask[key] === true) { - state[key] = object[key] + state[key] = object[key]; } else if (mask[key]) { - state[key] = maskObject(object[key], mask[key]) + state[key] = maskObject(object[key], mask[key]); } - return state - }, {}) + return state; + }, {}); } function setupDebuggingHelpers(store) { window.getCleanAppState = function () { - const state = clone(store.getState()) - state.version = global.platform.getVersion() - state.browser = window.navigator.userAgent - return state - } + const state = clone(store.getState()); + state.version = global.platform.getVersion(); + state.browser = window.navigator.userAgent; + return state; + }; window.getSentryState = function () { - const fullState = store.getState() - const debugState = maskObject(fullState, SENTRY_STATE) + const fullState = store.getState(); + const debugState = maskObject(fullState, SENTRY_STATE); return { browser: window.navigator.userAgent, store: debugState, version: global.platform.getVersion(), - } - } + }; + }; } window.logStateString = function (cb) { - const state = window.getCleanAppState() + const state = window.getCleanAppState(); global.platform.getPlatformInfo((err, platform) => { if (err) { - cb(err) - return + cb(err); + return; } - state.platform = platform - const stateString = JSON.stringify(state, null, 2) - cb(null, stateString) - }) -} + state.platform = platform; + const stateString = JSON.stringify(state, null, 2); + cb(null, stateString); + }); +}; window.logState = function (toClipboard) { return window.logStateString((err, result) => { if (err) { - console.error(err.message) + console.error(err.message); } else if (toClipboard) { - copyToClipboard(result) - console.log('State log copied') + copyToClipboard(result); + console.log('State log copied'); } else { - console.log(result) + console.log(result); } - }) -} + }); +}; diff --git a/ui/lib/account-link.js b/ui/lib/account-link.js index 0b9a3242d..9d7014487 100644 --- a/ui/lib/account-link.js +++ b/ui/lib/account-link.js @@ -3,25 +3,25 @@ export default function getAccountLink(address, network, rpcPrefs) { return `${rpcPrefs.blockExplorerUrl.replace( /\/+$/u, '', - )}/address/${address}` + )}/address/${address}`; } // eslint-disable-next-line radix - const net = parseInt(network) + const net = parseInt(network); switch (net) { case 1: // main net - return `https://etherscan.io/address/${address}` + return `https://etherscan.io/address/${address}`; case 2: // morden test net - return `https://morden.etherscan.io/address/${address}` + return `https://morden.etherscan.io/address/${address}`; case 3: // ropsten test net - return `https://ropsten.etherscan.io/address/${address}` + return `https://ropsten.etherscan.io/address/${address}`; case 4: // rinkeby test net - return `https://rinkeby.etherscan.io/address/${address}` + return `https://rinkeby.etherscan.io/address/${address}`; case 42: // kovan test net - return `https://kovan.etherscan.io/address/${address}` + return `https://kovan.etherscan.io/address/${address}`; case 5: // goerli test net - return `https://goerli.etherscan.io/address/${address}` + return `https://goerli.etherscan.io/address/${address}`; default: - return '' + return ''; } } diff --git a/ui/lib/etherscan-prefix-for-network.js b/ui/lib/etherscan-prefix-for-network.js index 82e92f3b1..9fb740090 100644 --- a/ui/lib/etherscan-prefix-for-network.js +++ b/ui/lib/etherscan-prefix-for-network.js @@ -1,4 +1,4 @@ -import * as networkEnums from '../../shared/constants/network' +import * as networkEnums from '../../shared/constants/network'; /** * Gets the etherscan.io URL prefix for a given network ID. @@ -9,15 +9,15 @@ import * as networkEnums from '../../shared/constants/network' export function getEtherscanNetworkPrefix(networkId) { switch (networkId) { case networkEnums.ROPSTEN_NETWORK_ID: - return 'ropsten.' + return 'ropsten.'; case networkEnums.RINKEBY_NETWORK_ID: - return 'rinkeby.' + return 'rinkeby.'; case networkEnums.KOVAN_NETWORK_ID: - return 'kovan.' + return 'kovan.'; case networkEnums.GOERLI_NETWORK_ID: - return 'goerli.' + return 'goerli.'; default: // also covers mainnet - return '' + return ''; } } diff --git a/ui/lib/icon-factory.js b/ui/lib/icon-factory.js index fa3f2bbf3..ca254317b 100644 --- a/ui/lib/icon-factory.js +++ b/ui/lib/icon-factory.js @@ -1,69 +1,69 @@ -import { isValidAddress } from 'ethereumjs-util' -import contractMap from '@metamask/contract-metadata' -import { checksumAddress } from '../app/helpers/utils/util' +import { isValidAddress } from 'ethereumjs-util'; +import contractMap from '@metamask/contract-metadata'; +import { checksumAddress } from '../app/helpers/utils/util'; -let iconFactory +let iconFactory; export default function iconFactoryGenerator(jazzicon) { if (!iconFactory) { - iconFactory = new IconFactory(jazzicon) + iconFactory = new IconFactory(jazzicon); } - return iconFactory + return iconFactory; } function IconFactory(jazzicon) { - this.jazzicon = jazzicon - this.cache = {} + this.jazzicon = jazzicon; + this.cache = {}; } IconFactory.prototype.iconForAddress = function (address, diameter) { - const addr = checksumAddress(address) + const addr = checksumAddress(address); if (iconExistsFor(addr)) { - return imageElFor(addr) + return imageElFor(addr); } - return this.generateIdenticonSvg(address, diameter) -} + return this.generateIdenticonSvg(address, diameter); +}; // returns svg dom element IconFactory.prototype.generateIdenticonSvg = function (address, diameter) { - const cacheId = `${address}:${diameter}` + const cacheId = `${address}:${diameter}`; // check cache, lazily generate and populate cache const identicon = this.cache[cacheId] || - (this.cache[cacheId] = this.generateNewIdenticon(address, diameter)) + (this.cache[cacheId] = this.generateNewIdenticon(address, diameter)); // create a clean copy so you can modify it - const cleanCopy = identicon.cloneNode(true) - return cleanCopy -} + const cleanCopy = identicon.cloneNode(true); + return cleanCopy; +}; // creates a new identicon IconFactory.prototype.generateNewIdenticon = function (address, diameter) { - const numericRepresentation = jsNumberForAddress(address) - const identicon = this.jazzicon(diameter, numericRepresentation) - return identicon -} + const numericRepresentation = jsNumberForAddress(address); + const identicon = this.jazzicon(diameter, numericRepresentation); + return identicon; +}; // util function iconExistsFor(address) { return ( contractMap[address] && isValidAddress(address) && contractMap[address].logo - ) + ); } function imageElFor(address) { - const contract = contractMap[address] - const fileName = contract.logo - const path = `images/contract/${fileName}` - const img = document.createElement('img') - img.src = path - img.style.width = '100%' - return img + const contract = contractMap[address]; + const fileName = contract.logo; + const path = `images/contract/${fileName}`; + const img = document.createElement('img'); + img.src = path; + img.style.width = '100%'; + return img; } function jsNumberForAddress(address) { - const addr = address.slice(2, 10) - const seed = parseInt(addr, 16) - return seed + const addr = address.slice(2, 10); + const seed = parseInt(addr, 16); + return seed; } diff --git a/ui/lib/is-mobile-view.js b/ui/lib/is-mobile-view.js index d8ddb4d93..310d49d6e 100644 --- a/ui/lib/is-mobile-view.js +++ b/ui/lib/is-mobile-view.js @@ -1,6 +1,6 @@ // Checks if viewport at invoke time fits mobile dimensions // isMobileView :: () => Bool const isMobileView = () => - window.matchMedia('screen and (max-width: 575px)').matches + window.matchMedia('screen and (max-width: 575px)').matches; -export default isMobileView +export default isMobileView; diff --git a/ui/lib/shallow-with-context.js b/ui/lib/shallow-with-context.js index ccc0a8b99..9cfb1bd75 100644 --- a/ui/lib/shallow-with-context.js +++ b/ui/lib/shallow-with-context.js @@ -1,7 +1,7 @@ -import { shallow } from 'enzyme' +import { shallow } from 'enzyme'; export default function shallowWithContext(jsxComponent) { return shallow(jsxComponent, { context: { t: (str1, str2) => (str2 ? str1 + str2 : str1) }, - }) + }); } diff --git a/ui/lib/storage-helpers.js b/ui/lib/storage-helpers.js index 737147405..a85d7fd48 100644 --- a/ui/lib/storage-helpers.js +++ b/ui/lib/storage-helpers.js @@ -1,23 +1,23 @@ -import localforage from 'localforage' +import localforage from 'localforage'; export async function getStorageItem(key) { try { - const serializedData = await localforage.getItem(key) + const serializedData = await localforage.getItem(key); if (serializedData === null) { - return undefined + return undefined; } - return JSON.parse(serializedData) + return JSON.parse(serializedData); } catch (err) { - return undefined + return undefined; } } export async function setStorageItem(key, value) { try { - const serializedData = JSON.stringify(value) - await localforage.setItem(key, serializedData) + const serializedData = JSON.stringify(value); + await localforage.setItem(key, serializedData); } catch (err) { - console.warn(err) + console.warn(err); } } diff --git a/ui/lib/test-timeout.js b/ui/lib/test-timeout.js index 9d9505f09..8c29780a1 100644 --- a/ui/lib/test-timeout.js +++ b/ui/lib/test-timeout.js @@ -1,5 +1,5 @@ export default function timeout(time) { return new Promise((resolve) => { - setTimeout(resolve, time || 1500) - }) + setTimeout(resolve, time || 1500); + }); } diff --git a/ui/lib/tx-helper.js b/ui/lib/tx-helper.js index 6493d67c8..698f0157a 100644 --- a/ui/lib/tx-helper.js +++ b/ui/lib/tx-helper.js @@ -1,5 +1,5 @@ -import log from 'loglevel' -import { valuesFor } from '../app/helpers/utils/util' +import log from 'loglevel'; +import { valuesFor } from '../app/helpers/utils/util'; export default function txHelper( unapprovedTxs, @@ -10,7 +10,7 @@ export default function txHelper( typedMessages, network, ) { - log.debug('tx-helper called with params:') + log.debug('tx-helper called with params:'); log.debug({ unapprovedTxs, unapprovedMsgs, @@ -19,42 +19,42 @@ export default function txHelper( encryptionPublicKeyMsgs, typedMessages, network, - }) + }); const txValues = network ? valuesFor(unapprovedTxs).filter( (txMeta) => txMeta.metamaskNetworkId === network, ) - : valuesFor(unapprovedTxs) - log.debug(`tx helper found ${txValues.length} unapproved txs`) + : valuesFor(unapprovedTxs); + log.debug(`tx helper found ${txValues.length} unapproved txs`); - const msgValues = valuesFor(unapprovedMsgs) - log.debug(`tx helper found ${msgValues.length} unsigned messages`) - let allValues = txValues.concat(msgValues) + const msgValues = valuesFor(unapprovedMsgs); + log.debug(`tx helper found ${msgValues.length} unsigned messages`); + let allValues = txValues.concat(msgValues); - const personalValues = valuesFor(personalMsgs) + const personalValues = valuesFor(personalMsgs); log.debug( `tx helper found ${personalValues.length} unsigned personal messages`, - ) - allValues = allValues.concat(personalValues) + ); + allValues = allValues.concat(personalValues); - const decryptValues = valuesFor(decryptMsgs) - log.debug(`tx helper found ${decryptValues.length} decrypt requests`) - allValues = allValues.concat(decryptValues) + const decryptValues = valuesFor(decryptMsgs); + log.debug(`tx helper found ${decryptValues.length} decrypt requests`); + allValues = allValues.concat(decryptValues); - const encryptionPublicKeyValues = valuesFor(encryptionPublicKeyMsgs) + const encryptionPublicKeyValues = valuesFor(encryptionPublicKeyMsgs); log.debug( `tx helper found ${encryptionPublicKeyValues.length} encryptionPublicKey requests`, - ) - allValues = allValues.concat(encryptionPublicKeyValues) + ); + allValues = allValues.concat(encryptionPublicKeyValues); - const typedValues = valuesFor(typedMessages) - log.debug(`tx helper found ${typedValues.length} unsigned typed messages`) - allValues = allValues.concat(typedValues) + const typedValues = valuesFor(typedMessages); + log.debug(`tx helper found ${typedValues.length} unsigned typed messages`); + allValues = allValues.concat(typedValues); allValues = allValues.sort((a, b) => { - return a.time - b.time - }) + return a.time - b.time; + }); - return allValues + return allValues; } diff --git a/ui/lib/webcam-utils.js b/ui/lib/webcam-utils.js index 6c451fd21..7dd4dd499 100644 --- a/ui/lib/webcam-utils.js +++ b/ui/lib/webcam-utils.js @@ -1,41 +1,41 @@ -'use strict' +'use strict'; import { ENVIRONMENT_TYPE_POPUP, PLATFORM_BRAVE, PLATFORM_FIREFOX, -} from '../../shared/constants/app' -import { getEnvironmentType, getPlatform } from '../../app/scripts/lib/util' +} from '../../shared/constants/app'; +import { getEnvironmentType, getPlatform } from '../../app/scripts/lib/util'; class WebcamUtils { static async checkStatus() { - const isPopup = getEnvironmentType() === ENVIRONMENT_TYPE_POPUP + const isPopup = getEnvironmentType() === ENVIRONMENT_TYPE_POPUP; const isFirefoxOrBrave = - getPlatform() === (PLATFORM_FIREFOX || PLATFORM_BRAVE) + getPlatform() === (PLATFORM_FIREFOX || PLATFORM_BRAVE); - const devices = await window.navigator.mediaDevices.enumerateDevices() - const webcams = devices.filter((device) => device.kind === 'videoinput') - const hasWebcam = webcams.length > 0 + const devices = await window.navigator.mediaDevices.enumerateDevices(); + const webcams = devices.filter((device) => device.kind === 'videoinput'); + const hasWebcam = webcams.length > 0; // A non-empty-string label implies that the webcam has been granted permission, as // otherwise the label is kept blank to prevent fingerprinting const hasWebcamPermissions = webcams.some( (webcam) => webcam.label && webcam.label.length > 0, - ) + ); if (hasWebcam) { - let environmentReady = true + let environmentReady = true; if ((isFirefoxOrBrave && isPopup) || (isPopup && !hasWebcamPermissions)) { - environmentReady = false + environmentReady = false; } return { permissions: hasWebcamPermissions, environmentReady, - } + }; } - const error = new Error('No webcam found') - error.type = 'NO_WEBCAM_FOUND' - throw error + const error = new Error('No webcam found'); + error.type = 'NO_WEBCAM_FOUND'; + throw error; } } -export default WebcamUtils +export default WebcamUtils; diff --git a/yarn.lock b/yarn.lock index 4808fa604..fff1a8a76 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2069,10 +2069,10 @@ web3 "^0.20.7" web3-provider-engine "^16.0.1" -"@metamask/eslint-config@^4.1.0": - version "4.1.0" - resolved "https://registry.yarnpkg.com/@metamask/eslint-config/-/eslint-config-4.1.0.tgz#ace2357af2d9c7d04da40a337fc7f4a81a048921" - integrity sha512-oc4ONdFB1h2yxBebVj4ACYzGzArB8ZQKiFVNCDlYiTCyeQ/GR4+EUwg0KvlO33LlXCRbAhO3CX0nChbvIB8hEw== +"@metamask/eslint-config@^5.0.0": + version "5.0.0" + resolved "https://registry.yarnpkg.com/@metamask/eslint-config/-/eslint-config-5.0.0.tgz#70c1ca854ce9b3b1cabd89cb736e8bb36127d164" + integrity sha512-eZt17NofPMmtoNjmBGOhUdAmyL0C+2/smtqAkVhpzZsU2ZGv+4Kekn8p8gcNONOYN8EotpWUxGkN1CTdVLdWZw== "@metamask/eth-ledger-bridge-keyring@^0.2.6": version "0.2.6" From 143d0b316adde2779589345efe8137d5c629bb5d Mon Sep 17 00:00:00 2001 From: Adam Magan Date: Thu, 4 Feb 2021 18:32:17 +0000 Subject: [PATCH 36/48] Update readme to node 14 (#10374) Follows on from the work done to upgrade Node to version 14 https://github.com/MetaMask/metamask-extension/pull/9514 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 545f1218c..0075770e9 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ To learn how to contribute to the MetaMask project itself, visit our [Internal D ## Building locally -- Install [Node.js](https://nodejs.org) version 10 +- Install [Node.js](https://nodejs.org) version 14 - If you are using [nvm](https://github.com/creationix/nvm#installation) (recommended) running `nvm use` will automatically choose the right node version for you. - Install [Yarn](https://yarnpkg.com/en/docs/install) - Install dependencies: `yarn` From 2d777c917806438c10104ed412a781e8ac3a0192 Mon Sep 17 00:00:00 2001 From: Erik Marks <25517051+rekmarks@users.noreply.github.com> Date: Thu, 4 Feb 2021 10:41:21 -0800 Subject: [PATCH 37/48] Update allow-scripts config (#10375) --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index fde50dfbb..224deefa6 100644 --- a/package.json +++ b/package.json @@ -303,7 +303,6 @@ "optipng-bin": true, "gifsicle": true, "jpegtran-bin": true, - "scrypt": true, "chromedriver": true, "geckodriver": true, "@sentry/cli": true, @@ -324,7 +323,8 @@ "gc-stats": false, "github:assemblyscript/assemblyscript": false, "tiny-secp256k1": false, - "@lavamoat/preinstall-always-fail": false + "@lavamoat/preinstall-always-fail": false, + "fsevents": false } } } From 418662c3658231fed4ddd9ff30204de9793d9fcc Mon Sep 17 00:00:00 2001 From: Thomas Huang Date: Thu, 4 Feb 2021 10:50:58 -0800 Subject: [PATCH 38/48] Move ganache server from test setup to individual test file. (#9703) --- test/helper.js | 8 -------- .../unit/app/controllers/metamask-controller-test.js | 12 ++++++++++++ 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/test/helper.js b/test/helper.js index 5731a905e..749577c40 100644 --- a/test/helper.js +++ b/test/helper.js @@ -1,4 +1,3 @@ -import Ganache from 'ganache-core'; import nock from 'nock'; import Enzyme from 'enzyme'; import Adapter from 'enzyme-adapter-react-16'; @@ -31,13 +30,6 @@ process.on('exit', () => { Enzyme.configure({ adapter: new Adapter() }); -// ganache server -const server = Ganache.server(); -server.listen(8545); - -server.on('error', console.error); -server.on('clientError', console.error); - log.setDefaultLevel(5); global.log = log; diff --git a/test/unit/app/controllers/metamask-controller-test.js b/test/unit/app/controllers/metamask-controller-test.js index ab7d9d85f..d92da4ed4 100644 --- a/test/unit/app/controllers/metamask-controller-test.js +++ b/test/unit/app/controllers/metamask-controller-test.js @@ -11,6 +11,10 @@ import createTxMeta from '../../../lib/createTxMeta'; import { addHexPrefix } from '../../../../app/scripts/lib/util'; import { TRANSACTION_STATUSES } from '../../../../shared/constants/transaction'; +const Ganache = require('../../../e2e/ganache'); + +const ganacheServer = new Ganache(); + const threeBoxSpies = { init: sinon.stub(), getThreeBoxSyncingState: sinon.stub().returns(true), @@ -90,6 +94,10 @@ describe('MetaMaskController', function () { const sandbox = sinon.createSandbox(); const noop = () => undefined; + before(async function () { + await ganacheServer.start(); + }); + beforeEach(function () { nock('https://min-api.cryptocompare.com') .persist() @@ -133,6 +141,10 @@ describe('MetaMaskController', function () { sandbox.restore(); }); + after(async function () { + await ganacheServer.quit(); + }); + describe('#getAccounts', function () { it('returns first address when dapp calls web3.eth.getAccounts', async function () { const password = 'a-fake-password'; From 6a6b27a04d1544cd342aceeeba11e9fe1d09f437 Mon Sep 17 00:00:00 2001 From: kumavis Date: Fri, 5 Feb 2021 23:41:45 +0800 Subject: [PATCH 39/48] "yarn setup" - the new way to install your deps (#10379) * deps - run "yarn setup" to install deps * doc - add "yarn setup" to local dev instructions --- README.md | 2 +- package.json | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 0075770e9..6ea6e204c 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ To learn how to contribute to the MetaMask project itself, visit our [Internal D - Install [Node.js](https://nodejs.org) version 14 - If you are using [nvm](https://github.com/creationix/nvm#installation) (recommended) running `nvm use` will automatically choose the right node version for you. - Install [Yarn](https://yarnpkg.com/en/docs/install) -- Install dependencies: `yarn` +- Install dependencies: `yarn setup` (not the usual install command) - Copy the `.metamaskrc.dist` file to `.metamaskrc` - Replace the `INFURA_PROJECT_ID` value with your own personal [Infura Project ID](https://infura.io/docs). - If debugging MetaMetrics, you'll need to add a value for `SEGMENT_WRITE_KEY` [Segment write key](https://segment.com/docs/connections/find-writekey/). diff --git a/package.json b/package.json index 224deefa6..a0e1886c6 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,7 @@ "version": "0.0.0", "private": true, "scripts": { + "setup": "yarn install && yarn allow-scripts", "start": "yarn build dev", "dist": "yarn build prod", "build": "node development/build/index.js", From 33ab480fbebbc1b7af17dc0c0f465acfc96f4edb Mon Sep 17 00:00:00 2001 From: Dan J Miller Date: Fri, 5 Feb 2021 13:41:10 -0330 Subject: [PATCH 40/48] Swaps token sources/verification messaging update (#10346) * Update standard swaps build quote screen token verification message * Add actionable warning token verification message to swaps build quote screen * Simplify swapTokenVerification translations * Use original verifyThisTokenOn message instead of swapsConfirmTokenAddressOnEtherscan * Restore verifyThisTokenOn message to hi locale * Support type and the withRightButton option as parameters on the actionable message component * Use 'continue' in place of swapPriceDifferenceAcknowledgementNoFiat message * Use wrapperClassName property on infotooltip in actionable-message * Remove unnecessary change * Lint fix --- app/_locales/en/messages.json | 17 ++++- .../actionable-message/actionable-message.js | 32 +++++++++- .../pages/swaps/actionable-message/index.scss | 38 ++++++++++++ ui/app/pages/swaps/build-quote/build-quote.js | 62 +++++++++++++++++-- ui/app/pages/swaps/build-quote/index.scss | 15 ++++- .../view-quote/view-quote-price-difference.js | 4 +- 6 files changed, 153 insertions(+), 15 deletions(-) diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index b8f44b7bb..5cb0c7aea 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -364,6 +364,9 @@ "contactsSettingsDescription": { "message": "Add, edit, remove, and manage your contacts" }, + "continue": { + "message": "Continue" + }, "continueToWyre": { "message": "Continue to Wyre" }, @@ -1735,9 +1738,6 @@ "swapPriceDifferenceAcknowledgement": { "message": "I'm aware" }, - "swapPriceDifferenceAcknowledgementNoFiat": { - "message": "Continue" - }, "swapPriceDifferenceTitle": { "message": "Price difference of ~$1%", "description": "$1 is a number (ex: 1.23) that represents the price difference." @@ -1845,6 +1845,17 @@ "message": "Swap $1 to $2", "description": "Used in the transaction display list to describe a swap. $1 and $2 are the symbols of tokens in involved in a swap." }, + "swapTokenVerificationMessage": { + "message": "Always confirm the token address on $1.", + "description": "Points the user to Etherscan as a place they can verify information about a token. $1 is replaced with the translation for \"Etherscan\" followed by an info icon that shows more info on hover." + }, + "swapTokenVerificationOnlyOneSource": { + "message": "Only verified on 1 source." + }, + "swapTokenVerificationSources": { + "message": "Verified on $1 sources.", + "description": "Indicates the number of token information sources that recognize the symbol + address. $1 is a decimal number." + }, "swapTransactionComplete": { "message": "Transaction complete" }, diff --git a/ui/app/pages/swaps/actionable-message/actionable-message.js b/ui/app/pages/swaps/actionable-message/actionable-message.js index cf24ff9f6..def248f6a 100644 --- a/ui/app/pages/swaps/actionable-message/actionable-message.js +++ b/ui/app/pages/swaps/actionable-message/actionable-message.js @@ -1,15 +1,42 @@ import React from 'react'; import PropTypes from 'prop-types'; import classnames from 'classnames'; +import InfoTooltip from '../../../components/ui/info-tooltip'; + +const CLASSNAME_WARNING = 'actionable-message--warning'; +const CLASSNAME_DANGER = 'actionable-message--danger'; +const CLASSNAME_WITH_RIGHT_BUTTON = 'actionable-message--with-right-button'; + +const typeHash = { + warning: CLASSNAME_WARNING, + danger: CLASSNAME_DANGER, +}; export default function ActionableMessage({ message = '', primaryAction = null, secondaryAction = null, className = '', + infoTooltipText = '', + withRightButton = false, + type = false, }) { + const actionableMessageClassName = classnames( + 'actionable-message', + typeHash[type], + withRightButton ? CLASSNAME_WITH_RIGHT_BUTTON : null, + className, + ); + return ( -
    +
    + {infoTooltipText && ( + + )}
    {message}
    {(primaryAction || secondaryAction) && (
    @@ -52,4 +79,7 @@ ActionableMessage.propTypes = { onClick: PropTypes.func, }), className: PropTypes.string, + type: PropTypes.string, + withRightButton: PropTypes.boolean, + infoTooltipText: PropTypes.string, }; diff --git a/ui/app/pages/swaps/actionable-message/index.scss b/ui/app/pages/swaps/actionable-message/index.scss index 2e5306b40..fd035ee0c 100644 --- a/ui/app/pages/swaps/actionable-message/index.scss +++ b/ui/app/pages/swaps/actionable-message/index.scss @@ -7,6 +7,7 @@ display: flex; flex-flow: column; align-items: center; + position: relative; @include H7; @@ -29,6 +30,12 @@ cursor: pointer; } + &__info-tooltip-wrapper { + position: absolute; + right: 4px; + top: 8px; + } + &--warning { background: $Yellow-100; border: 1px solid $Yellow-500; @@ -57,9 +64,40 @@ &--left-aligned { .actionable-message__message, .actionable-message__actions { + } + } + + &--with-right-button { + padding: 12px; + + .actionable-message__message { justify-content: flex-start; text-align: left; width: 100%; } + + .actionable-message__actions { + justify-content: flex-end; + width: 100%; + } + + .actionable-message__action { + font-weight: normal; + cursor: pointer; + border-radius: 42px; + min-width: 72px; + height: 18px; + display: flex; + justify-content: center; + align-items: center; + + @include H8; + } + } +} + +.actionable-message--warning.actionable-message--with-right-button { + .actionable-message__action { + background: $Yellow-500; } } diff --git a/ui/app/pages/swaps/build-quote/build-quote.js b/ui/app/pages/swaps/build-quote/build-quote.js index 4b0975673..c1a063681 100644 --- a/ui/app/pages/swaps/build-quote/build-quote.js +++ b/ui/app/pages/swaps/build-quote/build-quote.js @@ -14,6 +14,7 @@ import DropdownSearchList from '../dropdown-search-list'; import SlippageButtons from '../slippage-buttons'; import { getTokens } from '../../../ducks/metamask/metamask'; import InfoTooltip from '../../../components/ui/info-tooltip'; +import ActionableMessage from '../actionable-message'; import { fetchQuotesAndSetQuoteState, @@ -65,6 +66,7 @@ export default function BuildQuote({ const [fetchedTokenExchangeRate, setFetchedTokenExchangeRate] = useState( undefined, ); + const [verificationClicked, setVerificationClicked] = useState(false); const balanceError = useSelector(getBalanceError); const fetchParams = useSelector(getFetchParams); @@ -108,6 +110,9 @@ export default function BuildQuote({ const selectedToToken = tokensToSearch.find(({ address }) => address === toToken?.address) || toToken; + const toTokenIsNotEth = + selectedToToken?.address && + selectedToToken?.address !== ETH_SWAPS_TOKEN_OBJECT.address; const { address: fromTokenAddress, @@ -195,6 +200,7 @@ export default function BuildQuote({ dispatch(removeToken(toAddress)); } dispatch(setSwapToToken(token)); + setVerificationClicked(false); }, [dispatch, destinationTokenAddedForSwap, toAddress], ); @@ -369,10 +375,52 @@ export default function BuildQuote({ defaultToAll />
    - {selectedToToken?.address && - selectedToToken?.address !== ETH_SWAPS_TOKEN_OBJECT.address && ( + {toTokenIsNotEth && + (selectedToToken.occurances === 1 ? ( + +
    + {t('swapTokenVerificationOnlyOneSource')} +
    +
    + {t('verifyThisTokenOn', [ + + {t('etherscan')} + , + ])} +
    +
    + } + primaryAction={ + verificationClicked + ? null + : { + label: t('continue'), + onClick: () => setVerificationClicked(true), + } + } + type="warning" + withRightButton + infoTooltipText={t('swapVerifyTokenExplanation')} + /> + ) : (
    - {t('verifyThisTokenOn', [ + + {t('swapTokenVerificationSources', [ + selectedToToken.occurances, + ])} + + {t('swapTokenVerificationMessage', [
    - )} + ))}
    { @@ -415,7 +464,10 @@ export default function BuildQuote({ !Number(inputValue) || !selectedToToken?.address || Number(maxSlippage) === 0 || - Number(maxSlippage) > MAX_ALLOWED_SLIPPAGE + Number(maxSlippage) > MAX_ALLOWED_SLIPPAGE || + (toTokenIsNotEth && + selectedToToken.occurances === 1 && + !verificationClicked) } hideCancel showTermsOfService diff --git a/ui/app/pages/swaps/build-quote/index.scss b/ui/app/pages/swaps/build-quote/index.scss index acc1f7352..b07879076 100644 --- a/ui/app/pages/swaps/build-quote/index.scss +++ b/ui/app/pages/swaps/build-quote/index.scss @@ -122,14 +122,15 @@ width: 100%; color: $Grey-500; margin-top: 4px; - display: flex; - align-items: center; + + .info-tooltip { + display: inline-block; + } } &__token-etherscan-link { color: $Blue-500; cursor: pointer; - margin-right: 4px; } &__token-tooltip-container { @@ -137,6 +138,14 @@ display: flex !important; } + &__bold { + font-weight: bold; + } + + &__underline { + text-decoration: underline; + } + /* Prevents the swaps "Swap to" field from overflowing */ .dropdown-input-pair__to .dropdown-search-list { width: 100%; diff --git a/ui/app/pages/swaps/view-quote/view-quote-price-difference.js b/ui/app/pages/swaps/view-quote/view-quote-price-difference.js index b7589a567..61d1ad52b 100644 --- a/ui/app/pages/swaps/view-quote/view-quote-price-difference.js +++ b/ui/app/pages/swaps/view-quote/view-quote-price-difference.js @@ -30,9 +30,7 @@ export default function ViewQuotePriceDifference(props) { // A calculation error signals we cannot determine dollar value priceDifferenceMessage = t('swapPriceDifferenceUnavailable'); priceDifferenceClass = 'fiat-error'; - priceDifferenceAcknowledgementText = t( - 'swapPriceDifferenceAcknowledgementNoFiat', - ); + priceDifferenceAcknowledgementText = t('continue'); } else { priceDifferenceTitle = t('swapPriceDifferenceTitle', [ priceDifferencePercentage, From 27d6c6e0df1acb0f0e203aecb9ab5925b0868f03 Mon Sep 17 00:00:00 2001 From: Dan J Miller Date: Fri, 5 Feb 2021 14:57:48 -0330 Subject: [PATCH 41/48] Make action elements in actionable message component accessible (#10386) * Make action elements in actionable message component accessible by making them buttons * Remove unnecessary cursor pointer --- .../pages/swaps/actionable-message/actionable-message.js | 8 ++++---- ui/app/pages/swaps/actionable-message/index.scss | 2 -- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/ui/app/pages/swaps/actionable-message/actionable-message.js b/ui/app/pages/swaps/actionable-message/actionable-message.js index def248f6a..df9b9da1d 100644 --- a/ui/app/pages/swaps/actionable-message/actionable-message.js +++ b/ui/app/pages/swaps/actionable-message/actionable-message.js @@ -41,7 +41,7 @@ export default function ActionableMessage({ {(primaryAction || secondaryAction) && (
    {primaryAction && ( -
    {primaryAction.label} -
    + )} {secondaryAction && ( -
    {secondaryAction.label} -
    + )}
    )} diff --git a/ui/app/pages/swaps/actionable-message/index.scss b/ui/app/pages/swaps/actionable-message/index.scss index fd035ee0c..50e871613 100644 --- a/ui/app/pages/swaps/actionable-message/index.scss +++ b/ui/app/pages/swaps/actionable-message/index.scss @@ -27,7 +27,6 @@ &__action { font-weight: bold; - cursor: pointer; } &__info-tooltip-wrapper { @@ -83,7 +82,6 @@ .actionable-message__action { font-weight: normal; - cursor: pointer; border-radius: 42px; min-width: 72px; height: 18px; From 913fd5aad6c4dd9849cee469b038d8d4bd9f562a Mon Sep 17 00:00:00 2001 From: Dan J Miller Date: Fri, 5 Feb 2021 15:16:04 -0330 Subject: [PATCH 42/48] A swaps copy update (#10387) --- app/_locales/en/messages.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index 5cb0c7aea..2b10de408 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -1713,7 +1713,7 @@ "message": "MetaMask fee" }, "swapMetaMaskFeeDescription": { - "message": "We find the best price from the top liquidity sources, every time. A fee of $1% is automatically factored into each quote, which supports ongoing development to make MetaMask even better.", + "message": "We find the best price from the top liquidity sources, every time. A fee of $1% is automatically factored into this quote.", "description": "Provides information about the fee that metamask takes for swaps. $1 is a decimal number." }, "swapNQuotes": { From 531c35bc96d94d43dcad1f9746e42bf06b2d0953 Mon Sep 17 00:00:00 2001 From: David Walsh Date: Fri, 5 Feb 2021 14:40:40 -0600 Subject: [PATCH 43/48] Ensure users reacknowledge price slippage risks when it changes (#10376) --- ui/app/pages/swaps/view-quote/view-quote.js | 22 ++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/ui/app/pages/swaps/view-quote/view-quote.js b/ui/app/pages/swaps/view-quote/view-quote.js index 2c5c43865..f3fd90e58 100644 --- a/ui/app/pages/swaps/view-quote/view-quote.js +++ b/ui/app/pages/swaps/view-quote/view-quote.js @@ -9,6 +9,7 @@ import SelectQuotePopover from '../select-quote-popover'; import { useEthFiatAmount } from '../../../hooks/useEthFiatAmount'; import { useEqualityCheck } from '../../../hooks/useEqualityCheck'; import { useNewMetricEvent } from '../../../hooks/useMetricEvent'; +import { usePrevious } from '../../../hooks/usePrevious'; import { useSwapsEthToken } from '../../../hooks/useSwapsEthToken'; import { MetaMetricsContext } from '../../../contexts/metametrics.new'; import FeeCard from '../fee-card'; @@ -93,6 +94,7 @@ export default function ViewQuote() { acknowledgedPriceDifference, setAcknowledgedPriceDifference, ] = useState(false); + const priceDifferenceRiskyBuckets = ['high', 'medium']; const routeState = useSelector(getBackgroundSwapRouteState); const quotes = useSelector(getQuotes, isEqual); @@ -481,6 +483,24 @@ export default function ViewQuote() { ]); // Price difference warning + const priceSlippageBucket = usedQuote?.priceSlippage?.bucket; + const lastPriceDifferenceBucket = usePrevious(priceSlippageBucket); + + // If the user agreed to a different bucket of risk, make them agree again + useEffect(() => { + if ( + acknowledgedPriceDifference && + lastPriceDifferenceBucket === 'medium' && + priceSlippageBucket === 'high' + ) { + setAcknowledgedPriceDifference(false); + } + }, [ + priceSlippageBucket, + acknowledgedPriceDifference, + lastPriceDifferenceBucket, + ]); + let viewQuotePriceDifferenceComponent = null; const priceSlippageFromSource = useEthFiatAmount( usedQuote?.priceSlippage?.sourceAmountInETH || 0, @@ -510,7 +530,7 @@ export default function ViewQuote() { const shouldShowPriceDifferenceWarning = !showInsufficientWarning && usedQuote && - (['high', 'medium'].includes(usedQuote.priceSlippage.bucket) || + (priceDifferenceRiskyBuckets.includes(priceSlippageBucket) || priceSlippageUnknownFiatValue); if (shouldShowPriceDifferenceWarning) { From b0215738a295024d39ac3dc7d7b6c9d7b5f44f2e Mon Sep 17 00:00:00 2001 From: kumavis Date: Sat, 6 Feb 2021 10:28:54 +0800 Subject: [PATCH 44/48] storybook - i18n toolbar (#10381) * storybook - i18n toolbar * lint fix --- .storybook/i18n.js | 57 +++++++++++++ .storybook/locales.js | 58 +++++++++++++ .storybook/main.js | 1 + .storybook/preview.js | 56 ++++++++----- package.json | 1 + yarn.lock | 189 +++++++++++++++++++++++++++++++++++++++++- 6 files changed, 342 insertions(+), 20 deletions(-) create mode 100644 .storybook/i18n.js create mode 100644 .storybook/locales.js diff --git a/.storybook/i18n.js b/.storybook/i18n.js new file mode 100644 index 000000000..9eadca331 --- /dev/null +++ b/.storybook/i18n.js @@ -0,0 +1,57 @@ +import React, { Component, createContext, useMemo } from 'react'; +import PropTypes from 'prop-types'; +import { getMessage } from '../ui/app/helpers/utils/i18n-helper'; +import { I18nContext } from '../ui/app/contexts/i18n'; + +export { I18nContext } + +export const I18nProvider = (props) => { + const { currentLocale, current, en } = props + + const t = useMemo(() => { + return (key, ...args) => + getMessage(currentLocale, current, key, ...args) || + getMessage(currentLocale, en, key, ...args); + }, [currentLocale, current, en]); + + return ( + {props.children} + ); +}; + +I18nProvider.propTypes = { + currentLocale: PropTypes.string, + current: PropTypes.object, + en: PropTypes.object, + children: PropTypes.node, +}; + +I18nProvider.defaultProps = { + children: undefined, +}; + +export class LegacyI18nProvider extends Component { + static propTypes = { + children: PropTypes.node, + }; + + static defaultProps = { + children: undefined, + }; + + static contextType = I18nContext; + + static childContextTypes = { + t: PropTypes.func, + }; + + getChildContext() { + return { + t: this.context, + }; + } + + render() { + return this.props.children; + } +} diff --git a/.storybook/locales.js b/.storybook/locales.js new file mode 100644 index 000000000..1e92f94d8 --- /dev/null +++ b/.storybook/locales.js @@ -0,0 +1,58 @@ +import * as am from '../app/_locales/am/messages.json'; +import * as ar from '../app/_locales/ar/messages.json'; +import * as bg from '../app/_locales/bg/messages.json'; +import * as bn from '../app/_locales/bn/messages.json'; +import * as ca from '../app/_locales/ca/messages.json'; +import * as cs from '../app/_locales/cs/messages.json'; +import * as da from '../app/_locales/da/messages.json'; +import * as de from '../app/_locales/de/messages.json'; +import * as el from '../app/_locales/el/messages.json'; +import * as en from '../app/_locales/en/messages.json'; +import * as es from '../app/_locales/es/messages.json'; +import * as es_419 from '../app/_locales/es_419/messages.json'; +import * as et from '../app/_locales/et/messages.json'; +import * as fa from '../app/_locales/fa/messages.json'; +import * as fi from '../app/_locales/fi/messages.json'; +import * as fil from '../app/_locales/fil/messages.json'; +import * as fr from '../app/_locales/fr/messages.json'; +import * as gu from '../app/_locales/gu/messages.json'; +import * as he from '../app/_locales/he/messages.json'; +import * as hi from '../app/_locales/hi/messages.json'; +import * as hn from '../app/_locales/hn/messages.json'; +import * as hr from '../app/_locales/hr/messages.json'; +import * as ht from '../app/_locales/ht/messages.json'; +import * as hu from '../app/_locales/hu/messages.json'; +import * as id from '../app/_locales/id/messages.json'; +import * as it from '../app/_locales/it/messages.json'; +import * as ja from '../app/_locales/ja/messages.json'; +import * as kn from '../app/_locales/kn/messages.json'; +import * as ko from '../app/_locales/ko/messages.json'; +import * as lt from '../app/_locales/lt/messages.json'; +import * as lv from '../app/_locales/lv/messages.json'; +import * as ml from '../app/_locales/ml/messages.json'; +import * as mr from '../app/_locales/mr/messages.json'; +import * as ms from '../app/_locales/ms/messages.json'; +import * as nl from '../app/_locales/nl/messages.json'; +import * as no from '../app/_locales/no/messages.json'; +import * as ph from '../app/_locales/ph/messages.json'; +import * as pl from '../app/_locales/pl/messages.json'; +import * as pt from '../app/_locales/pt/messages.json'; +import * as pt_BR from '../app/_locales/pt_BR/messages.json'; +import * as pt_PT from '../app/_locales/pt_PT/messages.json'; +import * as ro from '../app/_locales/ro/messages.json'; +import * as ru from '../app/_locales/ru/messages.json'; +import * as sk from '../app/_locales/sk/messages.json'; +import * as sl from '../app/_locales/sl/messages.json'; +import * as sr from '../app/_locales/sr/messages.json'; +import * as sv from '../app/_locales/sv/messages.json'; +import * as sw from '../app/_locales/sw/messages.json'; +import * as ta from '../app/_locales/ta/messages.json'; +import * as te from '../app/_locales/te/messages.json'; +import * as th from '../app/_locales/th/messages.json'; +import * as tr from '../app/_locales/tr/messages.json'; +import * as uk from '../app/_locales/uk/messages.json'; +import * as vi from '../app/_locales/vi/messages.json'; +import * as zh_CN from '../app/_locales/zh_CN/messages.json'; +import * as zh_TW from '../app/_locales/zh_TW/messages.json'; + +export { am, ar, bg, bn, ca, cs, da, de, el, en, es, es_419, et, fa, fi, fil, fr, gu, he, hi, hn, hr, ht, hu, id, it, ja, kn, ko, lt, lv, ml, mr, ms, nl, no, ph, pl, pt, pt_BR, pt_PT, ro, ru, sk, sl, sr, sv, sw, ta, te, th, tr, uk, vi, zh_CN, zh_TW }; \ No newline at end of file diff --git a/.storybook/main.js b/.storybook/main.js index 8b1860ee5..b2ff41a8e 100644 --- a/.storybook/main.js +++ b/.storybook/main.js @@ -8,6 +8,7 @@ module.exports = { '@storybook/addon-knobs', '@storybook/addon-actions', '@storybook/addon-backgrounds', + '@storybook/addon-toolbars', ], webpackFinal: async (config) => { config.module.strictExportPresence = true diff --git a/.storybook/preview.js b/.storybook/preview.js index c3115997c..8c6c910cf 100644 --- a/.storybook/preview.js +++ b/.storybook/preview.js @@ -1,11 +1,12 @@ import React from 'react' import { addDecorator, addParameters } from '@storybook/react' import { withKnobs } from '@storybook/addon-knobs' -import { I18nProvider, LegacyI18nProvider } from '../ui/app/contexts/i18n' import { Provider } from 'react-redux' import configureStore from '../ui/app/store/store' import '../ui/app/css/index.scss' -import en from '../app/_locales/en/messages' +import localeList from '../app/_locales/index.json' +import * as allLocales from './locales' +import { I18nProvider, LegacyI18nProvider } from './i18n' addParameters({ backgrounds: { @@ -17,6 +18,20 @@ addParameters({ } }) +export const globalTypes = { + locale: { + name: 'Locale', + description: 'internationalization locale', + defaultValue: 'en', + toolbar: { + icon: 'globe', + items: localeList.map(({ code, name }) => { + return { value: code, right: code, title: name } + }) + }, + }, +}; + const styles = { height: '100vh', display: 'flex', @@ -25,25 +40,28 @@ const styles = { } const store = configureStore({ - metamask: { metamask: { currentLocale: 'en' } }, - - localeMessages: { - current: en, - en: en, - }, + metamask: { metamask: { } }, }) -const metamaskDecorator = story => ( - - - -
    - { story() } -
    -
    -
    -
    -) +const metamaskDecorator = (story, context) => { + const currentLocale = context.globals.locale + const current = allLocales[currentLocale] + return ( + + + +
    + { story() } +
    +
    +
    +
    + ) +} addDecorator(withKnobs) addDecorator(metamaskDecorator) diff --git a/package.json b/package.json index a0e1886c6..93b8b7a72 100644 --- a/package.json +++ b/package.json @@ -200,6 +200,7 @@ "@storybook/addon-actions": "^6.1.9", "@storybook/addon-backgrounds": "^6.1.9", "@storybook/addon-knobs": "^6.1.9", + "@storybook/addon-toolbars": "^6.1.17", "@storybook/core": "^6.1.9", "@storybook/react": "^6.1.9", "@storybook/storybook-deployer": "^2.8.6", diff --git a/yarn.lock b/yarn.lock index fff1a8a76..21f567b93 100644 --- a/yarn.lock +++ b/yarn.lock @@ -269,6 +269,11 @@ resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz#2f75a831269d4f677de49986dff59927533cf375" integrity sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg== +"@babel/helper-plugin-utils@^7.12.13": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.12.13.tgz#174254d0f2424d8aefb4dd48057511247b0a9eeb" + integrity sha512-C+10MXCXJLiR6IeG9+Wiejt9jmtFpxUc3MQqCmPY8hfCjyUGl9kT+B2okzEZrtykiwrc4dbCPdDoz0A/HQbDaA== + "@babel/helper-remap-async-to-generator@^7.12.1": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.12.1.tgz#8c4dbbf916314f6047dc05e6a2217074238347fd" @@ -546,6 +551,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" +"@babel/plugin-syntax-module-string-names@^7.12.13": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-module-string-names/-/plugin-syntax-module-string-names-7.12.13.tgz#2188abd8cb621b0446c9626acb54f7aea2527fd1" + integrity sha512-EEoEqJqlqbcwut6727/w9NJs4grtDsICI1Z/805Rr4E5bTo6kLqHvf8meDc8/da346fl2kxIQlqrmnyU6+3pyw== + dependencies: + "@babel/helper-plugin-utils" "^7.12.13" + "@babel/plugin-syntax-nullish-coalescing-operator@^7.8.0": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" @@ -2472,6 +2484,32 @@ react-select "^3.0.8" regenerator-runtime "^0.13.7" +"@storybook/addon-toolbars@^6.1.17": + version "6.1.17" + resolved "https://registry.yarnpkg.com/@storybook/addon-toolbars/-/addon-toolbars-6.1.17.tgz#15a015dc871e26be66340b5641631e649925c5e2" + integrity sha512-hEH4MFNbhCOzHs9yB+V+GH9FHD5MN7dxUfLFYM1tuZPqtotgfrYwCBUTy8m/tSxyOOSM+Y1BSHBozt2h7D23eA== + dependencies: + "@storybook/addons" "6.1.17" + "@storybook/api" "6.1.17" + "@storybook/client-api" "6.1.17" + "@storybook/components" "6.1.17" + core-js "^3.0.1" + +"@storybook/addons@6.1.17": + version "6.1.17" + resolved "https://registry.yarnpkg.com/@storybook/addons/-/addons-6.1.17.tgz#ab0666446acb9fc19c94d7204dc9aafdefb6c7c2" + integrity sha512-3upDPJPzUkls2V3Fozzg+JOcv138bF90pbdRe9YSNu37QvRIL+iQODY7oFygMl+kqjG2F1FGw5EvxAV1mnlwCw== + dependencies: + "@storybook/api" "6.1.17" + "@storybook/channels" "6.1.17" + "@storybook/client-logger" "6.1.17" + "@storybook/core-events" "6.1.17" + "@storybook/router" "6.1.17" + "@storybook/theming" "6.1.17" + core-js "^3.0.1" + global "^4.3.2" + regenerator-runtime "^0.13.7" + "@storybook/addons@6.1.9": version "6.1.9" resolved "https://registry.yarnpkg.com/@storybook/addons/-/addons-6.1.9.tgz#78f3cb27b7d934f091f311f89b6ca312d34f12b8" @@ -2487,6 +2525,31 @@ global "^4.3.2" regenerator-runtime "^0.13.7" +"@storybook/api@6.1.17": + version "6.1.17" + resolved "https://registry.yarnpkg.com/@storybook/api/-/api-6.1.17.tgz#50393ce9b718063b67680212df895eceacc0c11d" + integrity sha512-sthcfuk2EQ3F5R620PBqpI4Pno3g7KQm6YPZA0DXB+LD/z61xH9ToE1gTLF4nzlE6HwghwkXOZyRwDowRdG+7A== + dependencies: + "@reach/router" "^1.3.3" + "@storybook/channels" "6.1.17" + "@storybook/client-logger" "6.1.17" + "@storybook/core-events" "6.1.17" + "@storybook/csf" "0.0.1" + "@storybook/router" "6.1.17" + "@storybook/semver" "^7.3.2" + "@storybook/theming" "6.1.17" + "@types/reach__router" "^1.3.7" + core-js "^3.0.1" + fast-deep-equal "^3.1.1" + global "^4.3.2" + lodash "^4.17.15" + memoizerific "^1.11.3" + regenerator-runtime "^0.13.7" + store2 "^2.7.1" + telejson "^5.0.2" + ts-dedent "^2.0.0" + util-deprecate "^1.0.2" + "@storybook/api@6.1.9": version "6.1.9" resolved "https://registry.yarnpkg.com/@storybook/api/-/api-6.1.9.tgz#3f9bf00b2b18fa02965079fe775bd713677b30a3" @@ -2512,6 +2575,19 @@ ts-dedent "^2.0.0" util-deprecate "^1.0.2" +"@storybook/channel-postmessage@6.1.17": + version "6.1.17" + resolved "https://registry.yarnpkg.com/@storybook/channel-postmessage/-/channel-postmessage-6.1.17.tgz#309ce67c94637ec13319d4ce360a8f3742ddbaf4" + integrity sha512-2nVqxq4oZdSITqhFOnkh1rmDMjCwHuobnK5Fp3l7ftCkbmiZHMheKK9Tz4Rb803dhXvcGYs0zRS8NjKyxlOLsA== + dependencies: + "@storybook/channels" "6.1.17" + "@storybook/client-logger" "6.1.17" + "@storybook/core-events" "6.1.17" + core-js "^3.0.1" + global "^4.3.2" + qs "^6.6.0" + telejson "^5.0.2" + "@storybook/channel-postmessage@6.1.9": version "6.1.9" resolved "https://registry.yarnpkg.com/@storybook/channel-postmessage/-/channel-postmessage-6.1.9.tgz#5d73c67ba94bcf68b14138bba6c5bb0850c72c5e" @@ -2525,6 +2601,15 @@ qs "^6.6.0" telejson "^5.0.2" +"@storybook/channels@6.1.17": + version "6.1.17" + resolved "https://registry.yarnpkg.com/@storybook/channels/-/channels-6.1.17.tgz#2cc89a6b9727d19c24b15fa3cb15569b469db864" + integrity sha512-MUdj0eKr/AbxevHTSXX7AsgxAz6e5O4ZxoYX5G8ggoqSXrWzws6zRFmUmmTdjpIvVmP2M1Kh4SYFAKcS/AGw9w== + dependencies: + core-js "^3.0.1" + ts-dedent "^2.0.0" + util-deprecate "^1.0.2" + "@storybook/channels@6.1.9": version "6.1.9" resolved "https://registry.yarnpkg.com/@storybook/channels/-/channels-6.1.9.tgz#94f07ff3615b11c07d1902be6b6cd298c0eea55c" @@ -2534,6 +2619,30 @@ ts-dedent "^2.0.0" util-deprecate "^1.0.2" +"@storybook/client-api@6.1.17": + version "6.1.17" + resolved "https://registry.yarnpkg.com/@storybook/client-api/-/client-api-6.1.17.tgz#3ced22f08a47af70ccf8929111bc44b79e9e8ec0" + integrity sha512-Loz/wdh0axgq0PS19tx0tGEFEkFWlYc6YauJGHjygYa1xX7mJ54hDoaTolySCXN1HtfZn08D847yjGSN2oIqVg== + dependencies: + "@storybook/addons" "6.1.17" + "@storybook/channel-postmessage" "6.1.17" + "@storybook/channels" "6.1.17" + "@storybook/client-logger" "6.1.17" + "@storybook/core-events" "6.1.17" + "@storybook/csf" "0.0.1" + "@types/qs" "^6.9.0" + "@types/webpack-env" "^1.15.3" + core-js "^3.0.1" + global "^4.3.2" + lodash "^4.17.15" + memoizerific "^1.11.3" + qs "^6.6.0" + regenerator-runtime "^0.13.7" + stable "^0.1.8" + store2 "^2.7.1" + ts-dedent "^2.0.0" + util-deprecate "^1.0.2" + "@storybook/client-api@6.1.9": version "6.1.9" resolved "https://registry.yarnpkg.com/@storybook/client-api/-/client-api-6.1.9.tgz#d4a8d38bc657f26e4837831b961e085da1954d51" @@ -2558,6 +2667,14 @@ ts-dedent "^2.0.0" util-deprecate "^1.0.2" +"@storybook/client-logger@6.1.17": + version "6.1.17" + resolved "https://registry.yarnpkg.com/@storybook/client-logger/-/client-logger-6.1.17.tgz#0d89aaf824457f19bf9aa585bbcada57595e7d01" + integrity sha512-oqExrxhmws0ihB47sjdynZHd3OpUP4KWkx4udG+74lYIvBH+EZmQ9xF+UofeY3j5p1I9k8ugEcVKy0sqh1yR3w== + dependencies: + core-js "^3.0.1" + global "^4.3.2" + "@storybook/client-logger@6.1.9": version "6.1.9" resolved "https://registry.yarnpkg.com/@storybook/client-logger/-/client-logger-6.1.9.tgz#1d61a64000d4691780d75e19b78fd44adfdb5d9c" @@ -2566,6 +2683,32 @@ core-js "^3.0.1" global "^4.3.2" +"@storybook/components@6.1.17": + version "6.1.17" + resolved "https://registry.yarnpkg.com/@storybook/components/-/components-6.1.17.tgz#f92d36e370ec6039d8c7cee9ef13dda866eed3da" + integrity sha512-rIEll0UTxEKmG4IsSS5K+6DjRLVtX8J+9cg79GSAC7N1ZHUR1UQmjjJaehJa5q/NQ5H8C39acxpT4Py/BcsL2g== + dependencies: + "@popperjs/core" "^2.5.4" + "@storybook/client-logger" "6.1.17" + "@storybook/csf" "0.0.1" + "@storybook/theming" "6.1.17" + "@types/overlayscrollbars" "^1.9.0" + "@types/react-color" "^3.0.1" + "@types/react-syntax-highlighter" "11.0.4" + core-js "^3.0.1" + fast-deep-equal "^3.1.1" + global "^4.3.2" + lodash "^4.17.15" + markdown-to-jsx "^6.11.4" + memoizerific "^1.11.3" + overlayscrollbars "^1.10.2" + polished "^3.4.4" + react-color "^2.17.0" + react-popper-tooltip "^3.1.1" + react-syntax-highlighter "^13.5.0" + react-textarea-autosize "^8.1.1" + ts-dedent "^2.0.0" + "@storybook/components@6.1.9": version "6.1.9" resolved "https://registry.yarnpkg.com/@storybook/components/-/components-6.1.9.tgz#f25d18f3a410cc7e9549ddb3c971c40d9108d4d8" @@ -2592,6 +2735,13 @@ react-textarea-autosize "^8.1.1" ts-dedent "^2.0.0" +"@storybook/core-events@6.1.17": + version "6.1.17" + resolved "https://registry.yarnpkg.com/@storybook/core-events/-/core-events-6.1.17.tgz#697ed916fcb2a411bc9f8bdbfacd0eb9d394eb58" + integrity sha512-xBI7kmyROcqhYNmFv4QBjD77CzV+k/0F051YFS5WicEI4qDWPPvzaShhm96ZrGobUX3+di4pC11gqdsrFeNCEg== + dependencies: + core-js "^3.0.1" + "@storybook/core-events@6.1.9": version "6.1.9" resolved "https://registry.yarnpkg.com/@storybook/core-events/-/core-events-6.1.9.tgz#0a88281837d1aa657a93a9abf7f5aad65b8d68e7" @@ -2751,6 +2901,18 @@ ts-dedent "^2.0.0" webpack "^4.44.2" +"@storybook/router@6.1.17": + version "6.1.17" + resolved "https://registry.yarnpkg.com/@storybook/router/-/router-6.1.17.tgz#96746878c50c6c97c7de5a1b23a9503c5d648775" + integrity sha512-wLqSOB5yLXgNyDGy008RUvjVRtVMq7lhmMRicSIxgJpkakPrMRN8n/nK7pxgQc/xDTphnS0u1nT01i97WszhCg== + dependencies: + "@reach/router" "^1.3.3" + "@types/reach__router" "^1.3.7" + core-js "^3.0.1" + global "^4.3.2" + memoizerific "^1.11.3" + qs "^6.6.0" + "@storybook/router@6.1.9": version "6.1.9" resolved "https://registry.yarnpkg.com/@storybook/router/-/router-6.1.9.tgz#c0b24dc3ab53d58541b81c7abea2f11d7fbbebf6" @@ -2782,6 +2944,24 @@ shelljs "^0.8.1" yargs "^15.0.0" +"@storybook/theming@6.1.17": + version "6.1.17" + resolved "https://registry.yarnpkg.com/@storybook/theming/-/theming-6.1.17.tgz#99cc120a230c30458d833b40c806b9b4dff7b34a" + integrity sha512-LpRuY2aIh2td+qZi7E8cp2oM88LudNMmTsBT6N2/Id69u/a9qQd2cYCA9k9fAsg7rjor+wR/N695jk3SGtoFTw== + dependencies: + "@emotion/core" "^10.1.1" + "@emotion/is-prop-valid" "^0.8.6" + "@emotion/styled" "^10.0.23" + "@storybook/client-logger" "6.1.17" + core-js "^3.0.1" + deep-object-diff "^1.1.0" + emotion-theming "^10.0.19" + global "^4.3.2" + memoizerific "^1.11.3" + polished "^3.4.4" + resolve-from "^5.0.0" + ts-dedent "^2.0.0" + "@storybook/theming@6.1.9": version "6.1.9" resolved "https://registry.yarnpkg.com/@storybook/theming/-/theming-6.1.9.tgz#8c584aa623f3d6e33b1e3b3de2ec1f41bdc5d9ab" @@ -3144,6 +3324,13 @@ "@types/history" "*" "@types/react" "*" +"@types/reach__router@^1.3.7": + version "1.3.7" + resolved "https://registry.yarnpkg.com/@types/reach__router/-/reach__router-1.3.7.tgz#de8ab374259ae7f7499fc1373b9697a5f3cd6428" + integrity sha512-cyBEb8Ef3SJNH5NYEIDGPoMMmYUxROatuxbICusVRQIqZUB85UCt6R2Ok60tKS/TABJsJYaHyNTW3kqbpxlMjg== + dependencies: + "@types/react" "*" + "@types/react-color@^3.0.1": version "3.0.1" resolved "https://registry.yarnpkg.com/@types/react-color/-/react-color-3.0.1.tgz#5433e2f503ea0e0831cbc6fd0c20f8157d93add0" @@ -21378,7 +21565,7 @@ react-motion@^0.5.2: prop-types "^15.5.8" raf "^3.1.0" -react-popper-tooltip@^3.1.0: +react-popper-tooltip@^3.1.0, react-popper-tooltip@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/react-popper-tooltip/-/react-popper-tooltip-3.1.1.tgz#329569eb7b287008f04fcbddb6370452ad3f9eac" integrity sha512-EnERAnnKRptQBJyaee5GJScWNUKQPDD2ywvzZyUjst/wj5U64C8/CnSYLNEmP2hG0IJ3ZhtDxE8oDN+KOyavXQ== From 494c7da7dd8d745acc7a3cc98d8b0f2a2e698d1a Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Mon, 8 Feb 2021 09:05:42 -0330 Subject: [PATCH 45/48] Update `yarn.lock` file (#10393) The lockfile had extraneous packages that were removed upon install. They must have been left behind as a result of a recent merge. --- yarn.lock | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/yarn.lock b/yarn.lock index 21f567b93..070c9502f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -269,11 +269,6 @@ resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz#2f75a831269d4f677de49986dff59927533cf375" integrity sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg== -"@babel/helper-plugin-utils@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.12.13.tgz#174254d0f2424d8aefb4dd48057511247b0a9eeb" - integrity sha512-C+10MXCXJLiR6IeG9+Wiejt9jmtFpxUc3MQqCmPY8hfCjyUGl9kT+B2okzEZrtykiwrc4dbCPdDoz0A/HQbDaA== - "@babel/helper-remap-async-to-generator@^7.12.1": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.12.1.tgz#8c4dbbf916314f6047dc05e6a2217074238347fd" @@ -551,13 +546,6 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-syntax-module-string-names@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-module-string-names/-/plugin-syntax-module-string-names-7.12.13.tgz#2188abd8cb621b0446c9626acb54f7aea2527fd1" - integrity sha512-EEoEqJqlqbcwut6727/w9NJs4grtDsICI1Z/805Rr4E5bTo6kLqHvf8meDc8/da346fl2kxIQlqrmnyU6+3pyw== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - "@babel/plugin-syntax-nullish-coalescing-operator@^7.8.0": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" From 9dc88397dc1c38e54c1ab6f31d1138d47a6203f4 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Mon, 8 Feb 2021 09:11:39 -0330 Subject: [PATCH 46/48] Update `@metamask/inpage-provider` from v8.0.3 to v8.0.4 (#10378) Fixes #10356 There was a bug in the inpage provider that would mistakenly report usage of our injected `web3` instance when the `web3.currentProvider` property was accessed. This was fixed in v8.0.4 of `@metamask/inpage-provider`. --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 93b8b7a72..08dbb9fb9 100644 --- a/package.json +++ b/package.json @@ -83,7 +83,7 @@ "@metamask/eth-ledger-bridge-keyring": "^0.2.6", "@metamask/eth-token-tracker": "^3.0.1", "@metamask/etherscan-link": "^1.4.0", - "@metamask/inpage-provider": "^8.0.3", + "@metamask/inpage-provider": "^8.0.4", "@metamask/jazzicon": "^2.0.0", "@metamask/logo": "^2.5.0", "@metamask/obs-store": "^5.0.0", diff --git a/yarn.lock b/yarn.lock index 070c9502f..efcfa3599 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2108,10 +2108,10 @@ resolved "https://registry.yarnpkg.com/@metamask/forwarder/-/forwarder-1.1.0.tgz#13829d8244bbf19ea658c0b20d21a77b67de0bdd" integrity sha512-Hggj4y0QIjDzKGTXzarhEPIQyFSB2bi2y6YLJNwaT4JmP30UB5Cj6gqoY0M4pj3QT57fzp0BUuGp7F/AUe28tw== -"@metamask/inpage-provider@^8.0.3": - version "8.0.3" - resolved "https://registry.yarnpkg.com/@metamask/inpage-provider/-/inpage-provider-8.0.3.tgz#65f636233a13a00e1f199a421bdfa8099ed28ea4" - integrity sha512-pj9tGNoS1edohuRJzxOuILRqRrQTdgu5mJwMwa9wuOZIMQLFZtr3g2T6vayPBwoNkE1FzLhs/osUqaVQDRfDvQ== +"@metamask/inpage-provider@^8.0.4": + version "8.0.4" + resolved "https://registry.yarnpkg.com/@metamask/inpage-provider/-/inpage-provider-8.0.4.tgz#6534fbdba4445a3aff639e32db66bb0ab5f0cd79" + integrity sha512-jdI0gVWW/0wQvKZe6shXl70cU+vIb8GpAimKFU4udc/HKtgp8tLd21ezq74RaMP/lHR+qq0coOQ2KnOnl8iNNg== dependencies: "@metamask/object-multiplex" "^1.1.0" "@metamask/safe-event-emitter" "^2.0.0" From e66709e4b89e597b9daae7b470835d60f98ec515 Mon Sep 17 00:00:00 2001 From: MetaMask Bot Date: Mon, 8 Feb 2021 14:10:51 +0000 Subject: [PATCH 47/48] Version v9.0.5 --- CHANGELOG.md | 2 ++ app/manifest/_base.json | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 616aaa437..275367a37 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## Current Develop Branch +## 9.0.5 Mon Feb 08 2021 + ## 9.0.4 Fri Jan 22 2021 - [#10285](https://github.com/MetaMask/metamask-extension/pull/10285): Update @metamask/contract-metadata from v1.21.0 to 1.22.0 - [#10174](https://github.com/MetaMask/metamask-extension/pull/10174): Move fox to bottom of 'About' page diff --git a/app/manifest/_base.json b/app/manifest/_base.json index d5758f614..3d2edff7f 100644 --- a/app/manifest/_base.json +++ b/app/manifest/_base.json @@ -78,6 +78,6 @@ "notifications" ], "short_name": "__MSG_appName__", - "version": "9.0.4", + "version": "9.0.5", "web_accessible_resources": ["inpage.js", "phishing.html"] } From 9489dbe67d0dae24306fdde7bb2e9790979b888b Mon Sep 17 00:00:00 2001 From: Dan J Miller Date: Mon, 8 Feb 2021 20:22:04 -0330 Subject: [PATCH 48/48] Update changelog for v9.0.5 (#10398) * Update changelog for v9.0.5 * Update CHANGELOG.md Co-authored-by: Mark Stacey * Update CHANGELOG.md Co-authored-by: Mark Stacey * Add changelog entries for #10326 and #10386 Co-authored-by: Mark Stacey --- CHANGELOG.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 275367a37..508b8416e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,19 @@ ## Current Develop Branch ## 9.0.5 Mon Feb 08 2021 +- [#10278](https://github.com/MetaMask/metamask-extension/pull/10278): Allow editing transaction amount after clicking max +- [#10214](https://github.com/MetaMask/metamask-extension/pull/10214): Standardize size, shape and color of network color indicators +- [#10298](https://github.com/MetaMask/metamask-extension/pull/10298): Use network primary currency instead of always defaulting to ETH in the confirm approve screen +- [#10300](https://github.com/MetaMask/metamask-extension/pull/10300): Add origin to signature request confirmation page +- [#10296](https://github.com/MetaMask/metamask-extension/pull/10296): Add origin to transaction confirmation +- [#10266](https://github.com/MetaMask/metamask-extension/pull/10266): Update `ko` localized messages +- [#10263](https://github.com/MetaMask/metamask-extension/pull/10263): Update `id` localized messages +- [#10347](https://github.com/MetaMask/metamask-extension/pull/10347): Require click of "Continue" button to interact with swap screen if there is a price impact warning for present swap +- [#10373](https://github.com/MetaMask/metamask-extension/pull/10373): Change copy of submit button on swaps screen +- [#10346](https://github.com/MetaMask/metamask-extension/pull/10346): Swaps token sources/verification messaging update +- [#10378](https://github.com/MetaMask/metamask-extension/pull/10378): Stop showing the window.web3 in-app popup if the dapp is just using web3.currentProvider +- [#10326](https://github.com/MetaMask/metamask-extension/pull/10326): Throw error when attempting to get an encryption key via eth_getEncryptionPublicKey when connected to Ledger HW +- [#10386](https://github.com/MetaMask/metamask-extension/pull/10386): Make action buttons on message components in swaps flow accessible ## 9.0.4 Fri Jan 22 2021 - [#10285](https://github.com/MetaMask/metamask-extension/pull/10285): Update @metamask/contract-metadata from v1.21.0 to 1.22.0