diff --git a/.eslintignore b/.eslintignore index a07416923..659550cc7 100644 --- a/.eslintignore +++ b/.eslintignore @@ -3,14 +3,9 @@ node_modules/** dist/** builds/** -test-builds/** +test-*/** docs/** coverage/ -app/scripts/lib/extension-instance.js app/scripts/chromereload.js app/vendor/** - -ui/lib/blockies.js - -package-lock.json diff --git a/.eslintrc.js b/.eslintrc.js index 8ea5865e8..2fbadc34f 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -41,34 +41,22 @@ module.exports = { }, rules: { - /* TODO: Remove these when upgrading to `@metamask/eslint-config@2` */ - 'array-callback-return': 'error', - 'callback-return': 'error', - 'global-require': 'error', - 'guard-for-in': 'error', - /* End v2 rules */ - 'arrow-parens': 'error', - 'no-tabs': 'error', - 'no-mixed-operators': 'error', - 'import/default': 'error', - 'import/export': 'error', - 'import/named': 'error', - 'import/namespace': 'error', - 'import/newline-after-import': 'error', - 'import/no-absolute-path': 'error', - 'import/no-amd': 'error', - 'import/no-anonymous-default-export': 'error', - 'import/no-duplicates': 'error', - 'import/no-dynamic-require': 'error', - 'import/no-mutable-exports': 'error', - 'import/no-named-as-default': 'error', - 'import/no-named-as-default-member': 'error', - 'import/no-named-default': 'error', - 'import/no-self-import': 'error', - 'import/no-unresolved': ['error', { 'commonjs': true }], - 'import/no-unused-modules': 'error', - 'import/no-useless-path-segments': ['error', { 'commonjs': true }], - 'import/no-webpack-loader-syntax': 'error', + 'default-param-last': 'off', + 'require-atomic-updates': 'off', + 'import/no-unassigned-import': 'off', + 'prefer-destructuring': ['error', { + 'VariableDeclarator': { + 'array': false, + 'object': true, + }, + 'AssignmentExpression': { + 'array': false, + 'object': false, + }, + }, { + 'enforceForRenamedProperties': false, + }], + 'prefer-object-spread': 'error', 'react/no-unused-prop-types': 'error', 'react/no-unused-state': 'error', 'react/jsx-boolean-value': 'error', @@ -80,7 +68,7 @@ module.exports = { 'react/jsx-no-duplicate-props': 'error', 'react/jsx-closing-bracket-location': 'error', 'react/jsx-first-prop-new-line': ['error', 'multiline'], - 'react/jsx-max-props-per-line': ['error', { 'maximum': 1, 'when': 'multiline' } ], + 'react/jsx-max-props-per-line': ['error', { 'maximum': 1, 'when': 'multiline' }], 'react/jsx-tag-spacing': ['error', { 'closingSlash': 'never', 'beforeSelfClosing': 'always', @@ -95,11 +83,22 @@ module.exports = { 'logical': 'parens-new-line', 'prop': 'parens-new-line', }], + + 'no-invalid-this': 'off', + 'babel/no-invalid-this': 'error', + 'babel/semi': ['error', 'never'], 'mocha/no-setup-in-describe': 'off', }, overrides: [{ + files: [ + 'test/e2e/**/*.js', + ], + rules: { + 'mocha/no-hooks-for-single-case': 'off', + }, + }, { files: [ 'app/scripts/migrations/*.js', '*.stories.js', @@ -114,6 +113,38 @@ module.exports = { rules: { 'global-require': 'off', }, + }, { + files: [ + 'test/**/*-test.js', + 'test/**/*.spec.js', + ], + rules: { + // Mocha will re-assign `this` in a test context + 'babel/no-invalid-this': 'off', + }, + }, { + files: [ + 'development/**/*.js', + 'test/e2e/benchmark.js', + 'test/helper.js', + ], + rules: { + 'no-process-exit': 'off', + }, + }, { + files: [ + '.eslintrc.js', + 'babel.config.js', + 'nyc.config.js', + 'stylelint.config.js', + 'development/**/*.js', + 'test/e2e/**/*.js', + 'test/env.js', + 'test/setup.js', + ], + parserOptions: { + sourceType: 'script', + }, }], settings: { diff --git a/.storybook/main.js b/.storybook/main.js index 598003cdd..74acf6fb8 100644 --- a/.storybook/main.js +++ b/.storybook/main.js @@ -1,5 +1,5 @@ module.exports = { - stories: ['../ui/app/components/**/*.stories.js'], + stories: ['../ui/app/**/*.stories.js'], addons: [ '@storybook/addon-knobs', '@storybook/addon-actions', diff --git a/.storybook/webpack.config.js b/.storybook/webpack.config.js index f32a01559..be7dfecea 100644 --- a/.storybook/webpack.config.js +++ b/.storybook/webpack.config.js @@ -29,11 +29,13 @@ module.exports = { ], }, plugins: [ - new CopyWebpackPlugin([ - { - from: path.join('node_modules', '@fortawesome', 'fontawesome-free', 'webfonts'), - to: path.join('fonts', 'fontawesome'), - }, - ]), + new CopyWebpackPlugin({ + patterns: [ + { + from: path.join('node_modules', '@fortawesome', 'fontawesome-free', 'webfonts'), + to: path.join('fonts', 'fontawesome'), + }, + ], + }), ], } diff --git a/app/fonts/Euclid/EuclidCircularB-Bold-WebXL.ttf b/app/fonts/Euclid/EuclidCircularB-Bold-WebXL.ttf new file mode 100644 index 000000000..244ebba0a Binary files /dev/null and b/app/fonts/Euclid/EuclidCircularB-Bold-WebXL.ttf differ diff --git a/app/fonts/Euclid/EuclidCircularB-Regular-WebXL.ttf b/app/fonts/Euclid/EuclidCircularB-Regular-WebXL.ttf new file mode 100644 index 000000000..6cf177fe1 Binary files /dev/null and b/app/fonts/Euclid/EuclidCircularB-Regular-WebXL.ttf differ diff --git a/app/fonts/Euclid/EuclidCircularB-RegularItalic-WebXL.ttf b/app/fonts/Euclid/EuclidCircularB-RegularItalic-WebXL.ttf new file mode 100644 index 000000000..35345ba0f Binary files /dev/null and b/app/fonts/Euclid/EuclidCircularB-RegularItalic-WebXL.ttf differ diff --git a/app/scripts/account-import-strategies/index.js b/app/scripts/account-import-strategies/index.js index 7ff8c262f..9a7bc2f8e 100644 --- a/app/scripts/account-import-strategies/index.js +++ b/app/scripts/account-import-strategies/index.js @@ -8,7 +8,7 @@ const accountImporter = { importAccount (strategy, args) { try { const importer = this.strategies[strategy] - const privateKeyHex = importer.apply(null, args) + const privateKeyHex = importer(...args) return Promise.resolve(privateKeyHex) } catch (e) { return Promise.reject(e) diff --git a/app/scripts/background.js b/app/scripts/background.js index adbd1e40e..3df32dfeb 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -1,11 +1,11 @@ /** * @file The entry point for the web extension singleton process. */ - - // these need to run before anything else +/* eslint-disable import/first,import/order */ import './lib/freezeGlobals' import setupFetchDebugging from './lib/setupFetchDebugging' +/* eslint-enable import/order */ setupFetchDebugging() @@ -17,16 +17,16 @@ import pump from 'pump' import debounce from 'debounce-stream' import log from 'loglevel' import extension from 'extensionizer' -import ReadOnlyNetworkStore from './lib/network-store' -import LocalStore from './lib/local-store' import storeTransform from 'obs-store/lib/transform' import asStream from 'obs-store/lib/asStream' -import ExtensionPlatform from './platforms/extension' -import Migrator from './lib/migrator' -import migrations from './migrations' import PortStream from 'extension-port-stream' +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.js' +import NotificationManager from './lib/notification-manager' import MetamaskController from './metamask-controller' import rawFirstTimeState from './first-time-state' import setupSentry from './lib/setupSentry' @@ -39,9 +39,10 @@ import { ENVIRONMENT_TYPE_NOTIFICATION, ENVIRONMENT_TYPE_FULLSCREEN, } from './lib/enums' +/* eslint-enable import/first */ // METAMASK_TEST_CONFIG is used in e2e tests to set the default network to localhost -const firstTimeState = Object.assign({}, rawFirstTimeState, global.METAMASK_TEST_CONFIG) +const firstTimeState = { ...rawFirstTimeState, ...global.METAMASK_TEST_CONFIG } log.setDefaultLevel(process.env.METAMASK_DEBUG ? 'debug' : 'warn') @@ -327,7 +328,7 @@ function setupController (initState, initLangCode) { const isMetaMaskInternalProcess = metamaskInternalProcessHash[processName] if (metamaskBlockedPorts.includes(remotePort.name)) { - return false + return } if (isMetaMaskInternalProcess) { @@ -406,11 +407,11 @@ function setupController (initState, initLangCode) { function updateBadge () { let label = '' const unapprovedTxCount = controller.txController.getUnapprovedTxCount() - const unapprovedMsgCount = controller.messageManager.unapprovedMsgCount - const unapprovedPersonalMsgCount = controller.personalMessageManager.unapprovedPersonalMsgCount - const unapprovedDecryptMsgCount = controller.decryptMessageManager.unapprovedDecryptMsgCount - const unapprovedEncryptionPublicKeyMsgCount = controller.encryptionPublicKeyManager.unapprovedEncryptionPublicKeyMsgCount - const unapprovedTypedMessagesCount = controller.typedMessageManager.unapprovedTypedMessagesCount + const { unapprovedMsgCount } = controller.messageManager + const { unapprovedPersonalMsgCount } = controller.personalMessageManager + const { unapprovedDecryptMsgCount } = controller.decryptMessageManager + const { unapprovedEncryptionPublicKeyMsgCount } = controller.encryptionPublicKeyManager + const { unapprovedTypedMessagesCount } = controller.typedMessageManager const pendingPermissionRequests = Object.keys(controller.permissionsController.permissions.state.permissionsRequests).length const waitingForUnlockCount = controller.appStateController.waitingForUnlock.length const count = unapprovedTxCount + unapprovedMsgCount + unapprovedPersonalMsgCount + unapprovedDecryptMsgCount + unapprovedEncryptionPublicKeyMsgCount + diff --git a/app/scripts/contentscript.js b/app/scripts/contentscript.js index de3066ca8..d85aca3f2 100644 --- a/app/scripts/contentscript.js +++ b/app/scripts/contentscript.js @@ -1,5 +1,5 @@ -import pump from 'pump' import querystring from 'querystring' +import pump from 'pump' import LocalMessageDuplexStream from 'post-message-stream' import ObjectMultiplex from 'obj-multiplex' import extension from 'extensionizer' @@ -10,7 +10,7 @@ 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 inpageSuffix = `//# sourceURL=${extension.runtime.getURL('inpage.js')}\n` const inpageBundle = inpageContent + inpageSuffix // Eventually this streaming injection could be replaced with: @@ -115,7 +115,7 @@ function forwardTrafficBetweenMuxers (channelName, muxA, muxB) { function logStreamDisconnectWarning (remoteLabel, err) { let warningMsg = `MetamaskContentscript - lost connection to ${remoteLabel}` if (err) { - warningMsg += '\n' + err.stack + warningMsg += `\n${err.stack}` } console.warn(warningMsg) } @@ -136,12 +136,11 @@ function shouldInjectProvider () { * @returns {boolean} {@code true} - if the doctype is html or if none exists */ function doctypeCheck () { - const doctype = window.document.doctype + const { doctype } = window.document if (doctype) { return doctype.name === 'html' - } else { - return true } + return true } /** @@ -155,8 +154,8 @@ function doctypeCheck () { */ function suffixCheck () { const prohibitedTypes = [ - /\.xml$/, - /\.pdf$/, + /\.xml$/u, + /\.pdf$/u, ] const currentUrl = window.location.pathname for (let i = 0; i < prohibitedTypes.length; i++) { @@ -202,7 +201,7 @@ function blockedDomainCheck () { let currentRegex for (let i = 0; i < blockedDomains.length; i++) { const blockedDomain = blockedDomains[i].replace('.', '\\.') - currentRegex = new RegExp(`(?:https?:\\/\\/)(?:(?!${blockedDomain}).)*$`) + currentRegex = new RegExp(`(?:https?:\\/\\/)(?:(?!${blockedDomain}).)*$`, 'u') if (!currentRegex.test(currentUrl)) { return true } @@ -228,7 +227,7 @@ function redirectToPhishingWarning () { async function domIsReady () { // already loaded if (['interactive', 'complete'].includes(document.readyState)) { - return + return undefined } // wait for load return new Promise((resolve) => window.addEventListener('DOMContentLoaded', resolve, { once: true })) diff --git a/app/scripts/controllers/alert.js b/app/scripts/controllers/alert.js index 7fdddcdb1..820e1a80b 100644 --- a/app/scripts/controllers/alert.js +++ b/app/scripts/controllers/alert.js @@ -32,24 +32,21 @@ const defaultState = { * alert related state */ export default class AlertController { + /** * @constructor * @param {AlertControllerOptions} [opts] - Controller configuration parameters */ constructor (opts = {}) { const { initState, preferencesStore } = opts - const state = Object.assign( - {}, - defaultState, - initState, - { - unconnectedAccountAlertShownOrigins: {}, - }, - ) + const state = { + ...defaultState, + ...initState, + unconnectedAccountAlertShownOrigins: {}, + } this.store = new ObservableStore(state) - const { selectedAddress } = preferencesStore.getState() - this.selectedAddress = selectedAddress + this.selectedAddress = preferencesStore.getState().selectedAddress preferencesStore.subscribe(({ selectedAddress }) => { const currentState = this.store.getState() diff --git a/app/scripts/controllers/app-state.js b/app/scripts/controllers/app-state.js index 17bae2973..c29b76a40 100644 --- a/app/scripts/controllers/app-state.js +++ b/app/scripts/controllers/app-state.js @@ -1,7 +1,8 @@ -import ObservableStore from 'obs-store' import EventEmitter from 'events' +import ObservableStore from 'obs-store' export default class AppStateController extends EventEmitter { + /** * @constructor * @param opts @@ -15,16 +16,14 @@ export default class AppStateController extends EventEmitter { showUnlockRequest, preferencesStore, } = opts - const { preferences } = preferencesStore.getState() - super() - this.onInactiveTimeout = onInactiveTimeout || (() => {}) - this.store = new ObservableStore(Object.assign({ + this.onInactiveTimeout = onInactiveTimeout || (() => undefined) + this.store = new ObservableStore({ timeoutMinutes: 0, connectedStatusPopoverHasBeenShown: true, - defaultHomeActiveTabName: null, - }, initState)) + defaultHomeActiveTabName: null, ...initState, + }) this.timer = null this.isUnlocked = isUnlocked @@ -40,6 +39,7 @@ export default class AppStateController extends EventEmitter { } }) + const { preferences } = preferencesStore.getState() this._setInactiveTimeout(preferences.autoLockTimeLimit) } diff --git a/app/scripts/controllers/cached-balances.js b/app/scripts/controllers/cached-balances.js index 3cee10df0..87ca28662 100644 --- a/app/scripts/controllers/cached-balances.js +++ b/app/scripts/controllers/cached-balances.js @@ -12,6 +12,7 @@ import ObservableStore from 'obs-store' * a cache of account balances in local storage */ export default class CachedBalancesController { + /** * Creates a new controller instance * @@ -23,9 +24,7 @@ export default class CachedBalancesController { this.accountTracker = accountTracker this.getNetwork = getNetwork - const initState = Object.assign({ - cachedBalances: {}, - }, opts.initState) + const initState = { cachedBalances: {}, ...opts.initState } this.store = new ObservableStore(initState) this._registerUpdates() diff --git a/app/scripts/controllers/detect-tokens.js b/app/scripts/controllers/detect-tokens.js index 6b7424f98..40980990c 100644 --- a/app/scripts/controllers/detect-tokens.js +++ b/app/scripts/controllers/detect-tokens.js @@ -1,17 +1,19 @@ import Web3 from 'web3' import contracts from 'eth-contract-metadata' import { warn } from 'loglevel' +import SINGLE_CALL_BALANCES_ABI from 'single-call-balance-checker-abi' import { MAINNET } from './network/enums' + // By default, poll every 3 minutes const DEFAULT_INTERVAL = 180 * 1000 -import SINGLE_CALL_BALANCES_ABI from 'single-call-balance-checker-abi' - const SINGLE_CALL_BALANCES_ADDRESS = '0xb1f8e55c7f64d203c1400b9d8555d050f94adf39' + /** * A controller that polls for token exchange * rates based on a user's current token list */ export default class DetectTokensController { + /** * Creates a DetectTokensController * diff --git a/app/scripts/controllers/ens/index.js b/app/scripts/controllers/ens/index.js index e44a97ca3..d900bf4e6 100644 --- a/app/scripts/controllers/ens/index.js +++ b/app/scripts/controllers/ens/index.js @@ -1,6 +1,6 @@ +import punycode from 'punycode' import ethUtil from 'ethereumjs-util' import ObservableStore from 'obs-store' -import punycode from 'punycode' import log from 'loglevel' import Ens from './ens' diff --git a/app/scripts/controllers/incoming-transactions.js b/app/scripts/controllers/incoming-transactions.js index 7e8aa87d0..de588f38b 100644 --- a/app/scripts/controllers/incoming-transactions.js +++ b/app/scripts/controllers/incoming-transactions.js @@ -40,7 +40,7 @@ export default class IncomingTransactionsController { }) } - const initState = Object.assign({ + const initState = { incomingTransactions: {}, incomingTxLastFetchedBlocksByNetwork: { [ROPSTEN]: null, @@ -48,8 +48,8 @@ export default class IncomingTransactionsController { [KOVAN]: null, [GOERLI]: null, [MAINNET]: null, - }, - }, opts.initState) + }, ...opts.initState, + } this.store = new ObservableStore(initState) this.preferencesController.store.subscribe(pairwise((prevState, currState) => { @@ -265,9 +265,8 @@ function pairwise (fn) { if (first) { first = false return fn(value, value) - } else { - return fn(cache, value) } + return fn(cache, value) } finally { cache = value } diff --git a/app/scripts/controllers/network/createLocalhostClient.js b/app/scripts/controllers/network/createLocalhostClient.js index 447892016..efd19801c 100644 --- a/app/scripts/controllers/network/createLocalhostClient.js +++ b/app/scripts/controllers/network/createLocalhostClient.js @@ -26,7 +26,6 @@ function delay (time) { return new Promise((resolve) => setTimeout(resolve, time)) } - function createEstimateGasMiddleware () { return createAsyncMiddleware(async (req, _, next) => { if (req.method === 'eth_estimateGas' && inTest) { diff --git a/app/scripts/controllers/network/middleware/pending.js b/app/scripts/controllers/network/middleware/pending.js index c869389e7..1a67688c9 100644 --- a/app/scripts/controllers/network/middleware/pending.js +++ b/app/scripts/controllers/network/middleware/pending.js @@ -1,15 +1,17 @@ -import { formatTxMetaForRpcResult } from '../util' import createAsyncMiddleware from 'json-rpc-engine/src/createAsyncMiddleware' +import { formatTxMetaForRpcResult } from '../util' export function createPendingNonceMiddleware ({ getPendingNonce }) { return createAsyncMiddleware(async (req, res, next) => { const { method, params } = req if (method !== 'eth_getTransactionCount') { - return next() + next() + return } const [param, blockRef] = params if (blockRef !== 'pending') { - return next() + next() + return } res.result = await getPendingNonce(param) }) @@ -19,12 +21,14 @@ export function createPendingTxMiddleware ({ getPendingTransactionByHash }) { return createAsyncMiddleware(async (req, res, next) => { const { method, params } = req if (method !== 'eth_getTransactionByHash') { - return next() + next() + return } const [hash] = params const txMeta = getPendingTransactionByHash(hash) if (!txMeta) { - return next() + next() + return } res.result = formatTxMetaForRpcResult(txMeta) }) diff --git a/app/scripts/controllers/network/network.js b/app/scripts/controllers/network/network.js index f5efc58bd..29e878cc8 100644 --- a/app/scripts/controllers/network/network.js +++ b/app/scripts/controllers/network/network.js @@ -6,13 +6,11 @@ import EthQuery from 'eth-query' 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 createMetamaskMiddleware from './createMetamaskMiddleware' import createInfuraClient from './createInfuraClient' import createJsonRpcClient from './createJsonRpcClient' import createLocalhostClient from './createLocalhostClient' -import { createSwappableProxy, createEventEmitterProxy } from 'swappable-obj-proxy' - -const networks = { networkList: {} } import { RINKEBY, @@ -21,8 +19,10 @@ import { INFURA_PROVIDER_TYPES, } from './enums' +const networks = { networkList: {} } + const env = process.env.METAMASK_ENV -const METAMASK_DEBUG = process.env.METAMASK_DEBUG +const { METAMASK_DEBUG } = process.env let defaultProviderConfigType if (process.env.IN_TEST === 'true') { @@ -93,15 +93,15 @@ export default class NetworkController extends EventEmitter { setNetworkState (network, type) { if (network === 'loading') { - return this.networkStore.putState(network) + this.networkStore.putState(network) + return } // type must be defined if (!type) { return } - network = networks.networkList[type]?.chainId || network - return this.networkStore.putState(network) + this.networkStore.putState(networks.networkList[type]?.chainId || network) } isNetworkLoading () { @@ -111,7 +111,8 @@ export default class NetworkController extends EventEmitter { lookupNetwork () { // Prevent firing when provider is not defined. if (!this._provider) { - return log.warn('NetworkController - lookupNetwork aborted due to missing provider') + log.warn('NetworkController - lookupNetwork aborted due to missing provider') + return } const { type } = this.providerStore.getState() const ethQuery = new EthQuery(this._provider) @@ -120,9 +121,10 @@ export default class NetworkController extends EventEmitter { const currentNetwork = this.getNetworkState() if (initialNetwork === currentNetwork) { if (err) { - return this.setNetworkState('loading') + this.setNetworkState('loading') + return } - log.info('web3.getNetwork returned ' + network) + log.info(`web3.getNetwork returned ${network}`) this.setNetworkState(network, type) } }) @@ -210,7 +212,7 @@ export default class NetworkController extends EventEmitter { log.info('NetworkController - configureStandardProvider', rpcUrl) const networkClient = createJsonRpcClient({ rpcUrl }) // hack to add a 'rpc' network with chainId - networks.networkList['rpc'] = { + networks.networkList.rpc = { chainId, rpcUrl, ticker: ticker || 'ETH', @@ -220,7 +222,7 @@ export default class NetworkController extends EventEmitter { let settings = { network: chainId, } - settings = Object.assign(settings, networks.networkList['rpc']) + settings = Object.assign(settings, networks.networkList.rpc) this.networkConfig.putState(settings) this._setNetworkClient(networkClient) } diff --git a/app/scripts/controllers/onboarding.js b/app/scripts/controllers/onboarding.js index 7efb4523c..0ff92f5b1 100644 --- a/app/scripts/controllers/onboarding.js +++ b/app/scripts/controllers/onboarding.js @@ -17,6 +17,7 @@ import log from 'loglevel' * state related to onboarding */ export default class OnboardingController { + /** * Creates a new controller instance * @@ -26,13 +27,11 @@ export default class OnboardingController { const initialTransientState = { onboardingTabs: {}, } - const initState = Object.assign( - { - seedPhraseBackedUp: true, - }, - opts.initState, - initialTransientState, - ) + const initState = { + seedPhraseBackedUp: true, + ...opts.initState, + ...initialTransientState, + } this.store = new ObservableStore(initState) this.preferencesController = opts.preferencesController this.completedOnboarding = this.preferencesController.store.getState().completedOnboarding @@ -64,7 +63,7 @@ export default class OnboardingController { log.debug('Ignoring registerOnboarding; user already onboarded') return } - const onboardingTabs = Object.assign({}, 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 diff --git a/app/scripts/controllers/permissions/index.js b/app/scripts/controllers/permissions/index.js index a5aeb7b14..093983343 100644 --- a/app/scripts/controllers/permissions/index.js +++ b/app/scripts/controllers/permissions/index.js @@ -36,7 +36,8 @@ export class PermissionsController { showPermissionRequest, } = {}, restoredPermissions = {}, - restoredState = {}) { + restoredState = {}, + ) { // additional top-level store key set in _initializeMetadataStore this.store = new ObservableStore({ @@ -132,7 +133,7 @@ export class PermissionsController { const req = { method: 'eth_accounts' } const res = {} this.permissions.providerMiddlewareFunction( - { origin }, req, res, () => {}, _end, + { origin }, req, res, () => undefined, _end, ) function _end () { @@ -187,7 +188,7 @@ export class PermissionsController { const res = {} this.permissions.providerMiddlewareFunction( - domain, req, res, () => {}, _end, + domain, req, res, () => undefined, _end, ) function _end (_err) { @@ -334,7 +335,7 @@ export class PermissionsController { .filter((acc) => acc !== account) if (newPermittedAccounts.length === 0) { - this.removePermissionsFor({ [origin]: [ 'eth_accounts' ] }) + this.removePermissionsFor({ [origin]: ['eth_accounts'] }) } else { this.permissions.updateCaveatFor( diff --git a/app/scripts/controllers/permissions/permissionsLog.js b/app/scripts/controllers/permissions/permissionsLog.js index f7997f085..eda7c394a 100644 --- a/app/scripts/controllers/permissions/permissionsLog.js +++ b/app/scripts/controllers/permissions/permissionsLog.js @@ -113,10 +113,11 @@ export default class PermissionsLogController { // eth_requestAccounts is a special case; we need to extract the accounts // from it activityEntry = this.logRequest(req, isInternal) - requestedMethods = [ 'eth_accounts' ] + requestedMethods = ['eth_accounts'] } else { // no-op - return next() + next() + return } // call next with a return handler for capturing the response @@ -291,9 +292,9 @@ export default class PermissionsLogController { // eth_accounts requires special handling, because of information // we store about the accounts const existingEthAccountsEntry = ( - history[origin] && history[origin]['eth_accounts'] + history[origin] && history[origin].eth_accounts ) - const newEthAccountsEntry = newEntries['eth_accounts'] + const newEthAccountsEntry = newEntries.eth_accounts if (existingEthAccountsEntry && newEthAccountsEntry) { @@ -305,7 +306,7 @@ export default class PermissionsLogController { ) // merge old and new eth_accounts history entries - newOriginHistory['eth_accounts'] = { + newOriginHistory.eth_accounts = { lastApproved, accounts: { ...existingEthAccountsEntry.accounts, @@ -363,7 +364,7 @@ export default class PermissionsLogController { } } } - return [ ...accounts ] + return [...accounts] } } diff --git a/app/scripts/controllers/permissions/permissionsMethodMiddleware.js b/app/scripts/controllers/permissions/permissionsMethodMiddleware.js index 075f67cf8..ec5066b9c 100644 --- a/app/scripts/controllers/permissions/permissionsMethodMiddleware.js +++ b/app/scripts/controllers/permissions/permissionsMethodMiddleware.js @@ -24,12 +24,13 @@ export default function createPermissionsMethodMiddleware ({ // 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': + case 'eth_accounts': { res.result = await getAccounts() return + } - case 'eth_requestAccounts': + case 'eth_requestAccounts': { if (isProcessingRequestAccounts) { res.error = ethErrors.rpc.resourceUnavailable( @@ -73,19 +74,21 @@ export default function createPermissionsMethodMiddleware ({ } return + } // custom method for getting metadata from the requesting domain, // sent automatically by the inpage provider when it's initialized - case 'wallet_sendDomainMetadata': + case 'wallet_sendDomainMetadata': { if (typeof req.domainMetadata?.name === 'string') { addDomainMetadata(req.origin, req.domainMetadata) } res.result = true return + } // register return handler to send accountsChanged notification - case 'wallet_requestPermissions': + case 'wallet_requestPermissions': { if ('eth_accounts' in req.params?.[0]) { @@ -101,6 +104,7 @@ export default function createPermissionsMethodMiddleware ({ } } break + } default: break diff --git a/app/scripts/controllers/preferences.js b/app/scripts/controllers/preferences.js index 47fa73746..c82a1adbc 100644 --- a/app/scripts/controllers/preferences.js +++ b/app/scripts/controllers/preferences.js @@ -1,7 +1,7 @@ import ObservableStore from 'obs-store' -import { addInternalMethodPrefix } from './permissions' import { normalize as normalizeAddress } from 'eth-sig-util' import { isValidAddress, sha3, bufferToHex } from 'ethereumjs-util' +import { addInternalMethodPrefix } from './permissions' export default class PreferencesController { @@ -26,7 +26,7 @@ export default class PreferencesController { * */ constructor (opts = {}) { - const initState = Object.assign({ + const initState = { frequentRpcListDetail: [], accountTokens: {}, assetImages: {}, @@ -61,8 +61,8 @@ export default class PreferencesController { metaMetricsSendCount: 0, // ENS decentralized website resolution - ipfsGateway: 'dweb.link', - }, opts.initState) + ipfsGateway: 'dweb.link', ...opts.initState, + } this.diagnostics = opts.diagnostics this.network = opts.network @@ -152,7 +152,6 @@ export default class PreferencesController { this.store.updateState({ firstTimeFlowType: type }) } - getSuggestedTokens () { return this.store.getState().suggestedTokens } @@ -178,7 +177,7 @@ export default class PreferencesController { * @param {string} methodData - Corresponding data method */ addKnownMethodData (fourBytePrefix, methodData) { - const knownMethodData = this.store.getState().knownMethodData + const { knownMethodData } = this.store.getState() knownMethodData[fourBytePrefix] = methodData this.store.updateState({ knownMethodData }) } @@ -198,7 +197,7 @@ export default class PreferencesController { ) { const { type, options } = req.params switch (type) { - case 'ERC20': + case 'ERC20': { const result = await this._handleWatchAssetERC20(options) if (result instanceof Error) { end(result) @@ -207,6 +206,7 @@ export default class PreferencesController { end() } return + } default: end(new Error(`Asset of type ${type} not supported`)) return @@ -214,7 +214,6 @@ export default class PreferencesController { } next() - return } /** @@ -227,7 +226,7 @@ export default class PreferencesController { const textDirection = (['ar', 'dv', 'fa', 'he', 'ku'].includes(key)) ? 'rtl' : 'auto' this.store.updateState({ currentLocale: key, - textDirection: textDirection, + textDirection, }) return textDirection } @@ -263,8 +262,8 @@ export default class PreferencesController { * @returns {string} - the address that was removed */ removeAddress (address) { - const identities = this.store.getState().identities - const accountTokens = this.store.getState().accountTokens + const { identities } = this.store.getState() + const { accountTokens } = this.store.getState() if (!identities[address]) { throw new Error(`${address} can't be deleted cause it was not found`) } @@ -281,7 +280,6 @@ export default class PreferencesController { return address } - /** * Adds addresses to the identities object without removing identities * @@ -289,8 +287,7 @@ export default class PreferencesController { * */ addAddresses (addresses) { - const identities = this.store.getState().identities - const accountTokens = this.store.getState().accountTokens + const { identities, accountTokens } = this.store.getState() addresses.forEach((address) => { // skip if already exists if (identities[address]) { @@ -419,7 +416,7 @@ export default class PreferencesController { async addToken (rawAddress, symbol, decimals, image) { const address = normalizeAddress(rawAddress) const newEntry = { address, symbol, decimals } - const tokens = this.store.getState().tokens + const { tokens } = this.store.getState() const assetImages = this.getAssetImages() const previousEntry = tokens.find((token) => { return token.address === address @@ -444,7 +441,7 @@ export default class PreferencesController { * */ removeToken (rawAddress) { - const tokens = this.store.getState().tokens + const { tokens } = this.store.getState() const assetImages = this.getAssetImages() const updatedTokens = tokens.filter((token) => token.address !== rawAddress) delete assetImages[rawAddress] @@ -470,7 +467,7 @@ export default class PreferencesController { */ setAccountLabel (account, label) { if (!account) { - throw new Error('setAccountLabel requires a valid address, got ' + String(account)) + throw new Error(`setAccountLabel requires a valid address, got ${String(account)}`) } const address = normalizeAddress(account) const { identities } = this.store.getState() @@ -491,7 +488,6 @@ export default class PreferencesController { * */ - updateRpc (newRpcDetails) { const rpcList = this.getFrequentRpcListDetail() const index = rpcList.findIndex((element) => { @@ -508,6 +504,7 @@ export default class PreferencesController { } return Promise.resolve(rpcList) } + /** * Adds custom RPC url to state. * @@ -528,7 +525,8 @@ export default class PreferencesController { } if (url !== 'http://localhost:8545') { let checkedChainId - if (!!chainId && !Number.isNaN(parseInt(chainId))) { + // eslint-disable-next-line radix + if (Boolean(chainId) && !Number.isNaN(parseInt(chainId))) { checkedChainId = chainId } rpcList.push({ rpcUrl: url, chainId: checkedChainId, ticker, nickname, rpcPrefs }) @@ -686,8 +684,9 @@ export default class PreferencesController { * */ _getTokenRelatedStates (selectedAddress) { - const accountTokens = this.store.getState().accountTokens + const { accountTokens } = this.store.getState() if (!selectedAddress) { + // eslint-disable-next-line no-param-reassign selectedAddress = this.store.getState().selectedAddress } const providerType = this.network.providerStore.getState().type diff --git a/app/scripts/controllers/threebox.js b/app/scripts/controllers/threebox.js index bca43d9f6..080fac6cc 100644 --- a/app/scripts/controllers/threebox.js +++ b/app/scripts/controllers/threebox.js @@ -1,16 +1,19 @@ import ObservableStore from 'obs-store' +/* eslint-disable import/first,import/order */ const Box = process.env.IN_TEST ? require('../../../development/mock-3box') : require('3box') +/* eslint-enable import/order */ import log from 'loglevel' -import migrations from '../migrations' -import Migrator from '../lib/migrator' import JsonRpcEngine from 'json-rpc-engine' import providerFromEngine from 'eth-json-rpc-middleware/providerFromEngine' -import createMetamaskMiddleware from './network/createMetamaskMiddleware' +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 @@ -33,16 +36,15 @@ export default class ThreeBoxController { if (origin !== '3Box') { return [] } - const isUnlocked = getKeyringControllerState().isUnlocked + const { isUnlocked } = getKeyringControllerState() const accounts = await this.keyringController.getAccounts() if (isUnlocked && accounts[0]) { const appKeyAddress = await this.keyringController.getAppKeyAddress(accounts[0], 'wallet://3box.metamask.io') return [appKeyAddress] - } else { - return [] } + return [] }, processPersonalMessage: async (msgParams) => { const accounts = await this.keyringController.getAccounts() @@ -123,7 +125,7 @@ export default class ThreeBoxController { const threeBoxConfig = await Box.getConfig(this.address) backupExists = threeBoxConfig.spaces && threeBoxConfig.spaces.metamask } catch (e) { - if (e.message.match(/^Error: Invalid response \(404\)/)) { + if (e.message.match(/^Error: Invalid response \(404\)/u)) { backupExists = false } else { throw e diff --git a/app/scripts/controllers/token-rates.js b/app/scripts/controllers/token-rates.js index 4ef8b8ff8..bbc4ad778 100644 --- a/app/scripts/controllers/token-rates.js +++ b/app/scripts/controllers/token-rates.js @@ -3,7 +3,6 @@ import log from 'loglevel' import { normalize as normalizeAddress } from 'eth-sig-util' import ethUtil from 'ethereumjs-util' - // By default, poll every 3 minutes const DEFAULT_INTERVAL = 180 * 1000 @@ -12,6 +11,7 @@ const DEFAULT_INTERVAL = 180 * 1000 * rates based on a user's current token list */ export default class TokenRatesController { + /** * Creates a TokenRatesController * diff --git a/app/scripts/controllers/transactions/index.js b/app/scripts/controllers/transactions/index.js index fd9856705..96ac1c5fd 100644 --- a/app/scripts/controllers/transactions/index.js +++ b/app/scripts/controllers/transactions/index.js @@ -6,9 +6,8 @@ import EthQuery from 'ethjs-query' import { ethErrors } from 'eth-json-rpc-errors' import abi from 'human-standard-token-abi' import abiDecoder from 'abi-decoder' - -abiDecoder.addABI(abi) - +import NonceTracker from 'nonce-tracker' +import log from 'loglevel' import { TOKEN_METHOD_APPROVE, TOKEN_METHOD_TRANSFER, @@ -16,16 +15,14 @@ import { SEND_ETHER_ACTION_KEY, DEPLOY_CONTRACT_ACTION_KEY, CONTRACT_INTERACTION_KEY, -} from '../../../../ui/app/helpers/constants/transactions.js' - +} from '../../../../ui/app/helpers/constants/transactions' +import cleanErrorStack from '../../lib/cleanErrorStack' +import { hexToBn, bnToHex, BnMultiplyByFraction } from '../../lib/util' +import { TRANSACTION_NO_CONTRACT_ERROR_KEY } from '../../../../ui/app/helpers/constants/error-keys' import TransactionStateManager from './tx-state-manager' import TxGasUtil from './tx-gas-utils' import PendingTransactionTracker from './pending-tx-tracker' -import NonceTracker from 'nonce-tracker' import * as txUtils from './lib/util' -import cleanErrorStack from '../../lib/cleanErrorStack' -import log from 'loglevel' - import { TRANSACTION_TYPE_CANCEL, TRANSACTION_TYPE_RETRY, @@ -33,8 +30,7 @@ import { TRANSACTION_STATUS_APPROVED, } from './enums' -import { hexToBn, bnToHex, BnMultiplyByFraction } from '../../lib/util' -import { TRANSACTION_NO_CONTRACT_ERROR_KEY } from '../../../../ui/app/helpers/constants/error-keys' +abiDecoder.addABI(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 @@ -53,7 +49,6 @@ const MAX_MEMSTORE_TX_LIST_SIZE = 100 // Number of transactions (by unique nonce
- nonceTracker calculating nonces - @class @param {Object} - opts @param {Object} opts.initState - initial transaction list default is an empty array @@ -133,12 +128,12 @@ export default class TransactionController extends EventEmitter { */ getChainId () { const networkState = this.networkStore.getState() + // eslint-disable-next-line radix const integerChainId = parseInt(networkState) if (Number.isNaN(integerChainId)) { return 0 - } else { - return integerChainId } + return integerChainId } /** @@ -200,6 +195,7 @@ export default class TransactionController extends EventEmitter { const normalizedTxParams = txUtils.normalizeTxParams(txParams) txUtils.validateTxParams(normalizedTxParams) + /** `generateTxMeta` adds the default txMeta properties to the passed object. These include the tx's `id`. As we use the id for determining order of @@ -232,7 +228,7 @@ export default class TransactionController extends EventEmitter { } } - txMeta['origin'] = origin + txMeta.origin = origin const { transactionCategory, getCodeResponse } = await this._determineTransactionCategory(txParams) txMeta.transactionCategory = transactionCategory @@ -271,6 +267,7 @@ export default class TransactionController extends EventEmitter { const defaultGasPrice = await this._getDefaultGasPrice(txMeta) const { gasLimit: defaultGasLimit, simulationFails } = await this._getDefaultGasLimit(txMeta, getCodeResponse) + // eslint-disable-next-line no-param-reassign txMeta = this.txStateManager.getTx(txMeta.id) if (simulationFails) { txMeta.simulationFails = simulationFails @@ -287,11 +284,11 @@ export default class TransactionController extends EventEmitter { /** * Gets default gas price, or returns `undefined` if gas price is already set * @param {Object} txMeta - The txMeta object - * @returns {Promise} The default gas price + * @returns {Promise} The default gas price */ async _getDefaultGasPrice (txMeta) { if (txMeta.txParams.gasPrice) { - return + return undefined } const gasPrice = await this.query.gasPrice() @@ -472,8 +469,8 @@ export default class TransactionController extends EventEmitter { // this is try-catch wrapped so that we can guarantee that the nonceLock is released try { this.txStateManager.setTxStatusFailed(txId, err) - } catch (err) { - log.error(err) + } catch (err2) { + log.error(err2) } // must set transaction to submitted/failed before releasing lock if (nonceLock) { @@ -495,7 +492,7 @@ export default class TransactionController extends EventEmitter { const txMeta = this.txStateManager.getTx(txId) // add network/chain id const chainId = this.getChainId() - const txParams = Object.assign({}, txMeta.txParams, { chainId }) + const txParams = { ...txMeta.txParams, chainId } // sign tx const fromAddress = txParams.from const ethTx = new Transaction(txParams) @@ -560,9 +557,9 @@ export default class TransactionController extends EventEmitter { // It seems that sometimes the numerical values being returned from // this.query.getTransactionReceipt are BN instances and not strings. - const gasUsed = typeof txReceipt.gasUsed !== 'string' - ? txReceipt.gasUsed.toString(16) - : txReceipt.gasUsed + const gasUsed = typeof txReceipt.gasUsed === 'string' + ? txReceipt.gasUsed + : txReceipt.gasUsed.toString(16) txMeta.txReceipt = { ...txReceipt, @@ -604,19 +601,25 @@ export default class TransactionController extends EventEmitter { // /** maps methods for convenience*/ _mapMethods () { + /** @returns {Object} - the state in transaction controller */ this.getState = () => this.memStore.getState() + /** @returns {string|number} - the network number stored in networkStore */ this.getNetwork = () => this.networkStore.getState() + /** @returns {string} - the user selected address */ this.getSelectedAddress = () => this.preferencesStore.getState().selectedAddress + /** @returns {array} - transactions whos status is unapproved */ this.getUnapprovedTxCount = () => 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 + /** see txStateManager */ this.getFilteredTxList = (opts) => this.txStateManager.getFilteredTxList(opts) } @@ -684,7 +687,7 @@ export default class TransactionController extends EventEmitter { if (!('retryCount' in txMeta)) { txMeta.retryCount = 0 } - txMeta.retryCount++ + txMeta.retryCount += 1 this.txStateManager.updateTx(txMeta, 'transactions/pending-tx-tracker#event: tx:retry') }) } @@ -700,7 +703,7 @@ export default class TransactionController extends EventEmitter { TOKEN_METHOD_APPROVE, TOKEN_METHOD_TRANSFER, TOKEN_METHOD_TRANSFER_FROM, - ].find((tokenMethodName) => tokenMethodName === name && name.toLowerCase()) + ].find((methodName) => methodName === name && name.toLowerCase()) let result if (txParams.data && tokenMethodName) { @@ -754,8 +757,7 @@ export default class TransactionController extends EventEmitter { _setupBlockTrackerListener () { let listenersAreActive = false const latestBlockHandler = this._onLatestBlock.bind(this) - const blockTracker = this.blockTracker - const txStateManager = this.txStateManager + const { blockTracker, txStateManager } = this txStateManager.on('tx:status-update', updateSubscription) updateSubscription() diff --git a/app/scripts/controllers/transactions/pending-tx-tracker.js b/app/scripts/controllers/transactions/pending-tx-tracker.js index a901707a8..e1b33cb2f 100644 --- a/app/scripts/controllers/transactions/pending-tx-tracker.js +++ b/app/scripts/controllers/transactions/pending-tx-tracker.js @@ -15,11 +15,11 @@ import EthQuery from 'ethjs-query' @param {function} config.getPendingTransactions a function for getting an array of transactions, @param {function} config.publishTransaction a async function for publishing raw transactions, - @class */ export default class PendingTransactionTracker extends EventEmitter { + /** * We wait this many blocks before emitting a 'tx:dropped' event * @@ -129,7 +129,7 @@ export default class PendingTransactionTracker extends EventEmitter { // Exponential backoff to limit retries at publishing if (txBlockDistance <= Math.pow(2, retryCount) - 1) { - return + return undefined } // Only auto-submit already-signed txs: @@ -137,7 +137,7 @@ export default class PendingTransactionTracker extends EventEmitter { return this.approveTransaction(txMeta.id) } - const rawTx = txMeta.rawTx + const { rawTx } = txMeta const txHash = await this.publishTransaction(rawTx) // Increment successful tries: @@ -196,7 +196,6 @@ export default class PendingTransactionTracker extends EventEmitter { if (await this._checkIfTxWasDropped(txMeta)) { this.emit('tx:dropped', txId) - return } } @@ -239,11 +238,11 @@ export default class PendingTransactionTracker extends EventEmitter { async _checkIfNonceIsTaken (txMeta) { const address = txMeta.txParams.from const completed = this.getCompletedTransactions(address) - return completed.some((other) => + 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 // and if that is the case, don't consider the transaction to have taken its own nonce - !(other.id === txMeta.id) && other.txParams.nonce === txMeta.txParams.nonce, + (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 1fca82afd..4b897b968 100644 --- a/app/scripts/controllers/transactions/tx-gas-utils.js +++ b/app/scripts/controllers/transactions/tx-gas-utils.js @@ -1,6 +1,6 @@ import EthQuery from 'ethjs-query' -import { hexToBn, BnMultiplyByFraction, bnToHex } from '../../lib/util' import log from 'loglevel' +import { hexToBn, BnMultiplyByFraction, bnToHex } from '../../lib/util' /** * Result of gas analysis, including either a gas estimate for a successful analysis, or @@ -56,7 +56,7 @@ export default class TxGasUtil { @returns {string} - the estimated gas limit as a hex string */ async estimateTxGas (txMeta) { - const txParams = txMeta.txParams + const { txParams } = txMeta // estimate tx gas requirements return await this.query.estimateGas(txParams) diff --git a/app/scripts/controllers/transactions/tx-state-manager.js b/app/scripts/controllers/transactions/tx-state-manager.js index b8adf8deb..b5c7e3353 100644 --- a/app/scripts/controllers/transactions/tx-state-manager.js +++ b/app/scripts/controllers/transactions/tx-state-manager.js @@ -1,9 +1,10 @@ import EventEmitter from 'safe-event-emitter' import ObservableStore from 'obs-store' import log from 'loglevel' -import { generateHistoryEntry, replayHistory, snapshotFromTxMeta } from './lib/tx-state-history-helpers' import createId from '../../lib/random-id' +import { generateHistoryEntry, replayHistory, snapshotFromTxMeta } from './lib/tx-state-history-helpers' import { getFinalStates, normalizeTxParams } from './lib/util' + /** TransactionStateManager is responsible for the state of a transaction and storing the transaction @@ -31,9 +32,8 @@ export default class TransactionStateManager extends EventEmitter { super() this.store = new ObservableStore( - Object.assign({ - transactions: [], - }, initState)) + { transactions: [], ...initState }, + ) this.txHistoryLimit = txHistoryLimit this.getNetwork = getNetwork } @@ -47,13 +47,13 @@ export default class TransactionStateManager extends EventEmitter { if (netId === 'loading') { throw new Error('MetaMask is having trouble connecting to the network') } - return Object.assign({ + return { id: createId(), time: (new Date()).getTime(), status: 'unapproved', metamaskNetworkId: netId, - loadingDefaults: true, - }, opts) + loadingDefaults: true, ...opts, + } } /** @@ -164,10 +164,10 @@ export default class TransactionStateManager extends EventEmitter { txMeta.txParams = this.normalizeAndValidateTxParams(txMeta.txParams) } - this.once(`${txMeta.id}:signed`, function () { + this.once(`${txMeta.id}:signed`, () => { this.removeAllListeners(`${txMeta.id}:rejected`) }) - this.once(`${txMeta.id}:rejected`, function () { + this.once(`${txMeta.id}:rejected`, () => { this.removeAllListeners(`${txMeta.id}:signed`) }) // initialize history @@ -178,7 +178,7 @@ export default class TransactionStateManager extends EventEmitter { const transactions = this.getFullTxList() const txCount = transactions.length - const txHistoryLimit = this.txHistoryLimit + const { txHistoryLimit } = this // checks if the length of the tx history is // longer then desired persistence limit @@ -202,6 +202,7 @@ export default class TransactionStateManager extends EventEmitter { this._saveTxList(transactions) return txMeta } + /** @param {number} txId @returns {Object} - the txMeta who matches the given id if none found @@ -241,7 +242,6 @@ export default class TransactionStateManager extends EventEmitter { this._saveTxList(txList) } - /** merges txParams obj onto txMeta.txParams use extend to ensure that all fields are filled @@ -262,6 +262,7 @@ export default class TransactionStateManager extends EventEmitter { if (typeof txParams.data === 'undefined') { delete txParams.data } + // eslint-disable-next-line no-param-reassign txParams = normalizeTxParams(txParams, false) this.validateTxParams(txParams) return txParams @@ -325,6 +326,7 @@ export default class TransactionStateManager extends EventEmitter { }) return filteredTxList } + /** @param {string} key - the key to check @@ -339,9 +341,8 @@ export default class TransactionStateManager extends EventEmitter { return txList.filter((txMeta) => { if (key in txMeta.txParams) { return filter(txMeta.txParams[key]) - } else { - return filter(txMeta[key]) } + return filter(txMeta[key]) }) } @@ -372,6 +373,7 @@ export default class TransactionStateManager extends EventEmitter { setTxStatusUnapproved (txId) { this._setTxStatus(txId, 'unapproved') } + /** should update the status of the tx to 'approved'. @param {number} txId - the txMeta Id @@ -416,7 +418,6 @@ export default class TransactionStateManager extends EventEmitter { this._setTxStatus(txId, 'dropped') } - /** should update the status of the tx to 'failed'. and put the error on the txMeta @@ -424,7 +425,7 @@ export default class TransactionStateManager extends EventEmitter { @param {erroObject} err - error object */ setTxStatusFailed (txId, err) { - const error = !err ? new Error('Internal metamask failure') : err + const error = err || new Error('Internal metamask failure') const txMeta = this.getTx(txId) txMeta.err = { diff --git a/app/scripts/inpage.js b/app/scripts/inpage.js index c7c92face..546f0a362 100644 --- a/app/scripts/inpage.js +++ b/app/scripts/inpage.js @@ -30,12 +30,14 @@ const restoreContextAfterImports = () => { cleanContextForImports() +/* eslint-disable import/first */ import log from 'loglevel' import LocalMessageDuplexStream from 'post-message-stream' import { initProvider } from '@metamask/inpage-provider' // TODO:deprecate:2020 -import setupWeb3 from './lib/setupWeb3.js' +import setupWeb3 from './lib/setupWeb3' +/* eslint-enable import/first */ restoreContextAfterImports() @@ -58,7 +60,6 @@ initProvider({ // TODO:deprecate:2020 // Setup web3 - if (typeof window.web3 !== 'undefined') { throw new Error(`MetaMask detected another web3. MetaMask will not work reliably with another web3 extension. diff --git a/app/scripts/lib/ComposableObservableStore.js b/app/scripts/lib/ComposableObservableStore.js index 3f8b99af4..ef8e91f22 100644 --- a/app/scripts/lib/ComposableObservableStore.js +++ b/app/scripts/lib/ComposableObservableStore.js @@ -5,6 +5,7 @@ import ObservableStore from 'obs-store' * structure of child stores based on configuration */ export default class ComposableObservableStore extends ObservableStore { + /** * Create a new store * @@ -25,7 +26,7 @@ export default class ComposableObservableStore extends ObservableStore { this.config = config this.removeAllListeners() for (const key in config) { - if (config.hasOwnProperty(key)) { + if (Object.prototype.hasOwnProperty.call(config, key)) { config[key].subscribe((state) => { this.updateState({ [key]: state }) }) @@ -42,7 +43,7 @@ export default class ComposableObservableStore extends ObservableStore { getFlatState () { let flatState = {} for (const key in this.config) { - if (this.config.hasOwnProperty(key)) { + if (Object.prototype.hasOwnProperty.call(this.config, key)) { const controller = this.config[key] const state = controller.getState ? controller.getState() : controller.state flatState = { ...flatState, ...state } diff --git a/app/scripts/lib/account-tracker.js b/app/scripts/lib/account-tracker.js index 974920ee4..2d97a1382 100644 --- a/app/scripts/lib/account-tracker.js +++ b/app/scripts/lib/account-tracker.js @@ -14,7 +14,6 @@ import log from 'loglevel' import pify from 'pify' import Web3 from 'web3' import SINGLE_CALL_BALANCES_ABI from 'single-call-balance-checker-abi' -import { bnToHex } from './util' import { MAINNET_NETWORK_ID, RINKEBY_NETWORK_ID, ROPSTEN_NETWORK_ID, KOVAN_NETWORK_ID } from '../controllers/network/enums' import { @@ -23,6 +22,7 @@ import { SINGLE_CALL_BALANCES_ADDRESS_ROPSTEN, SINGLE_CALL_BALANCES_ADDRESS_KOVAN, } from '../controllers/network/contract-addresses' +import { bnToHex } from './util' export default class AccountTracker { @@ -92,7 +92,7 @@ export default class AccountTracker { * */ syncWithAddresses (addresses) { - const accounts = this.store.getState().accounts + const { accounts } = this.store.getState() const locals = Object.keys(accounts) const accountsToAdd = [] @@ -121,7 +121,7 @@ export default class AccountTracker { * */ addAccounts (addresses) { - const accounts = this.store.getState().accounts + const { accounts } = this.store.getState() // add initial state for addresses addresses.forEach((address) => { accounts[address] = {} @@ -142,7 +142,7 @@ export default class AccountTracker { * */ removeAccount (addresses) { - const accounts = this.store.getState().accounts + const { accounts } = this.store.getState() // remove each state object addresses.forEach((address) => { delete accounts[address] @@ -194,7 +194,7 @@ export default class AccountTracker { * */ async _updateAccounts () { - const accounts = this.store.getState().accounts + const { accounts } = this.store.getState() const addresses = Object.keys(accounts) const currentNetwork = this.network.getNetworkState() @@ -248,7 +248,7 @@ export default class AccountTracker { * @param {*} deployedContractAddress */ async _updateAccountsViaBalanceChecker (addresses, deployedContractAddress) { - const accounts = this.store.getState().accounts + 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'] @@ -256,7 +256,8 @@ export default class AccountTracker { ethContract.balances(addresses, ethBalance, (error, result) => { if (error) { log.warn(`MetaMask - Account Tracker single call balance fetch failed`, error) - return Promise.all(addresses.map(this._updateAccount.bind(this))) + Promise.all(addresses.map(this._updateAccount.bind(this))) + return } addresses.forEach((address, index) => { const balance = bnToHex(result[index]) diff --git a/app/scripts/lib/background-metametrics.js b/app/scripts/lib/background-metametrics.js index a9baa79b7..7af1125c1 100644 --- a/app/scripts/lib/background-metametrics.js +++ b/app/scripts/lib/background-metametrics.js @@ -2,9 +2,6 @@ import { getBackgroundMetaMetricState } from '../../../ui/app/selectors' import { sendMetaMetricsEvent } from '../../../ui/app/helpers/utils/metametrics.util' export default function backgroundMetaMetricsEvent (metaMaskState, version, eventData) { - - eventData.eventOpts['category'] = 'Background' - const stateEventData = getBackgroundMetaMetricState({ metamask: metaMaskState }) if (stateEventData.participateInMetaMetrics) { sendMetaMetricsEvent({ diff --git a/app/scripts/lib/buy-eth-url.js b/app/scripts/lib/buy-eth-url.js index 46d8909da..a82d3f2b0 100644 --- a/app/scripts/lib/buy-eth-url.js +++ b/app/scripts/lib/buy-eth-url.js @@ -11,6 +11,7 @@ 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) } diff --git a/app/scripts/lib/cleanErrorStack.js b/app/scripts/lib/cleanErrorStack.js index 5b59ff66e..c68c29b9e 100644 --- a/app/scripts/lib/cleanErrorStack.js +++ b/app/scripts/lib/cleanErrorStack.js @@ -4,7 +4,7 @@ * @returns {Error} - Error with clean stack trace. */ export default function cleanErrorStack (err) { - let name = err.name + let { name } = err name = (name === undefined) ? 'Error' : String(name) let msg = err.message @@ -15,7 +15,7 @@ export default function cleanErrorStack (err) { } else if (msg === '') { err.stack = err.name } else { - err.stack = err.name + ': ' + err.message + err.stack = `${err.name}: ${err.message}` } return err diff --git a/app/scripts/lib/createMethodMiddleware.js b/app/scripts/lib/createMethodMiddleware.js index a2b466be1..7a98ce531 100644 --- a/app/scripts/lib/createMethodMiddleware.js +++ b/app/scripts/lib/createMethodMiddleware.js @@ -14,7 +14,7 @@ export default function createMethodMiddleware ({ origin, sendMetrics }) { return function methodMiddleware (req, res, next, end) { switch (req.method) { - case 'metamask_logInjectedWeb3Usage': + case 'metamask_logInjectedWeb3Usage': { const { action, name } = req.params[0] @@ -32,6 +32,7 @@ export default function createMethodMiddleware ({ origin, sendMetrics }) { res.result = true break + } default: return next() diff --git a/app/scripts/lib/createStreamSink.js b/app/scripts/lib/createStreamSink.js index 5a9d0808e..ad0a67959 100644 --- a/app/scripts/lib/createStreamSink.js +++ b/app/scripts/lib/createStreamSink.js @@ -4,7 +4,7 @@ import promiseToCallback from 'promise-to-callback' class AsyncWritableStream extends WritableStream { constructor (asyncWriteFn, _opts) { - const opts = Object.assign({ objectMode: true }, _opts) + const opts = { objectMode: true, ..._opts } super(opts) this._asyncWriteFn = asyncWriteFn } diff --git a/app/scripts/lib/decrypt-message-manager.js b/app/scripts/lib/decrypt-message-manager.js index ca308090f..a31074f12 100644 --- a/app/scripts/lib/decrypt-message-manager.js +++ b/app/scripts/lib/decrypt-message-manager.js @@ -2,11 +2,11 @@ import EventEmitter from 'events' import ObservableStore from 'obs-store' import ethUtil from 'ethereumjs-util' import { ethErrors } from 'eth-json-rpc-errors' +import log from 'loglevel' import createId from './random-id' import { MESSAGE_TYPE } from './enums' -const hexRe = /^[0-9A-Fa-f]+$/g -import log from 'loglevel' +const hexRe = /^[0-9A-Fa-f]+$/ug /** * Represents, and contains data about, an 'eth_decrypt' type decryption request. These are created when a @@ -26,6 +26,7 @@ import log from 'loglevel' */ export default class DecryptMessageManager extends EventEmitter { + /** * Controller in charge of managing - storing, adding, removing, updating - DecryptMessage. * @@ -65,7 +66,8 @@ export default class DecryptMessageManager extends EventEmitter { getUnapprovedMsgs () { return this.messages.filter((msg) => msg.status === 'unapproved') .reduce((result, msg) => { - result[msg.id] = msg; return result + result[msg.id] = msg + return result }, {}) } @@ -82,19 +84,23 @@ export default class DecryptMessageManager extends EventEmitter { addUnapprovedMessageAsync (msgParams, req) { return new Promise((resolve, reject) => { if (!msgParams.from) { - return reject(new Error('MetaMask Decryption: from field is required.')) + reject(new Error('MetaMask Decryption: from field is required.')) + return } const msgId = this.addUnapprovedMessage(msgParams, req) this.once(`${msgId}:finished`, (data) => { switch (data.status) { case 'decrypted': - return resolve(data.rawData) + resolve(data.rawData) + return case 'rejected': - return reject(ethErrors.provider.userRejectedRequest('MetaMask Decryption: User denied message decryption.')) + reject(ethErrors.provider.userRejectedRequest('MetaMask Decryption: User denied message decryption.')) + return case 'errored': - return reject(new Error('This message cannot be decrypted')) + reject(new Error('This message cannot be decrypted')) + return default: - return reject(new Error(`MetaMask Decryption: Unknown problem: ${JSON.stringify(msgParams)}`)) + reject(new Error(`MetaMask Decryption: Unknown problem: ${JSON.stringify(msgParams)}`)) } }) }) @@ -122,8 +128,8 @@ export default class DecryptMessageManager extends EventEmitter { const msgId = createId() const msgData = { id: msgId, - msgParams: msgParams, - time: time, + msgParams, + time, status: 'unapproved', type: MESSAGE_TYPE.ETH_DECRYPT, } @@ -248,7 +254,7 @@ export default class DecryptMessageManager extends EventEmitter { _setMsgStatus (msgId, status) { const msg = this.getMsg(msgId) if (!msg) { - throw new Error('DecryptMessageManager - Message not found for id: "${msgId}".') + throw new Error(`DecryptMessageManager - Message not found for id: "${msgId}".`) } msg.status = status this._updateMsg(msg) diff --git a/app/scripts/lib/encryption-public-key-manager.js b/app/scripts/lib/encryption-public-key-manager.js index 92f09057c..2631dc7d3 100644 --- a/app/scripts/lib/encryption-public-key-manager.js +++ b/app/scripts/lib/encryption-public-key-manager.js @@ -1,8 +1,8 @@ import EventEmitter from 'events' import ObservableStore from 'obs-store' import { ethErrors } from 'eth-json-rpc-errors' -import createId from './random-id' import log from 'loglevel' +import createId from './random-id' import { MESSAGE_TYPE } from './enums' /** @@ -23,6 +23,7 @@ import { MESSAGE_TYPE } from './enums' */ export default class EncryptionPublicKeyManager extends EventEmitter { + /** * Controller in charge of managing - storing, adding, removing, updating - EncryptionPublicKey. * @@ -62,7 +63,8 @@ export default class EncryptionPublicKeyManager extends EventEmitter { getUnapprovedMsgs () { return this.messages.filter((msg) => msg.status === 'unapproved') .reduce((result, msg) => { - result[msg.id] = msg; return result + result[msg.id] = msg + return result }, {}) } @@ -79,17 +81,20 @@ export default class EncryptionPublicKeyManager extends EventEmitter { addUnapprovedMessageAsync (address, req) { return new Promise((resolve, reject) => { if (!address) { - return reject(new Error('MetaMask Message: address field is required.')) + reject(new Error('MetaMask Message: address field is required.')) + return } const msgId = this.addUnapprovedMessage(address, req) this.once(`${msgId}:finished`, (data) => { switch (data.status) { case 'received': - return resolve(data.rawData) + resolve(data.rawData) + return case 'rejected': - return reject(ethErrors.provider.userRejectedRequest('MetaMask EncryptionPublicKey: User denied message EncryptionPublicKey.')) + reject(ethErrors.provider.userRejectedRequest('MetaMask EncryptionPublicKey: User denied message EncryptionPublicKey.')) + return default: - return reject(new Error(`MetaMask EncryptionPublicKey: Unknown problem: ${JSON.stringify(address)}`)) + reject(new Error(`MetaMask EncryptionPublicKey: Unknown problem: ${JSON.stringify(address)}`)) } }) }) @@ -113,7 +118,7 @@ export default class EncryptionPublicKeyManager extends EventEmitter { const msgData = { id: msgId, msgParams: address, - time: time, + time, status: 'unapproved', type: MESSAGE_TYPE.ETH_GET_ENCRYPTION_PUBLIC_KEY, } @@ -243,7 +248,7 @@ export default class EncryptionPublicKeyManager extends EventEmitter { _setMsgStatus (msgId, status) { const msg = this.getMsg(msgId) if (!msg) { - throw new Error('EncryptionPublicKeyManager - Message not found for id: "${msgId}".') + throw new Error(`EncryptionPublicKeyManager - Message not found for id: "${msgId}".`) } msg.status = status this._updateMsg(msg) diff --git a/app/scripts/lib/ens-ipfs/resolver.js b/app/scripts/lib/ens-ipfs/resolver.js index 475432ba1..cc307e617 100644 --- a/app/scripts/lib/ens-ipfs/resolver.js +++ b/app/scripts/lib/ens-ipfs/resolver.js @@ -1,9 +1,9 @@ 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 contentHash from 'content-hash' export default async function resolveEnsToIpfsContentId ({ provider, name }) { const eth = new Eth(provider) @@ -36,7 +36,7 @@ export default async function resolveEnsToIpfsContentId ({ provider, name }) { decodedContentHash = contentHash.helpers.cidV0ToV1Base32(decodedContentHash) } - return { type: type, hash: decodedContentHash } + return { type, hash: decodedContentHash } } if (isLegacyResolver[0]) { // lookup content id diff --git a/app/scripts/lib/ens-ipfs/setup.js b/app/scripts/lib/ens-ipfs/setup.js index d1fc42674..e543a2d66 100644 --- a/app/scripts/lib/ens-ipfs/setup.js +++ b/app/scripts/lib/ens-ipfs/setup.js @@ -1,6 +1,6 @@ import urlUtil from 'url' import extension from 'extensionizer' -import resolveEnsToIpfsContentId from './resolver.js' +import resolveEnsToIpfsContentId from './resolver' const supportedTopLevelDomains = ['eth'] diff --git a/app/scripts/lib/extractEthjsErrorMessage.js b/app/scripts/lib/extractEthjsErrorMessage.js index 6d9d0bf2d..0dde04f06 100644 --- a/app/scripts/lib/extractEthjsErrorMessage.js +++ b/app/scripts/lib/extractEthjsErrorMessage.js @@ -19,7 +19,6 @@ export default function extractEthjsErrorMessage (errorMessage) { const payloadAndError = errorMessage.slice(ethJsRpcSlug.length) const originalError = payloadAndError.slice(payloadAndError.indexOf(errorLabelPrefix) + errorLabelPrefix.length) return originalError - } else { - return errorMessage } + return errorMessage } diff --git a/app/scripts/lib/freezeGlobals.js b/app/scripts/lib/freezeGlobals.js index 6599088d6..b17a84781 100644 --- a/app/scripts/lib/freezeGlobals.js +++ b/app/scripts/lib/freezeGlobals.js @@ -30,11 +30,11 @@ function freeze (target, key, value, enumerable = true) { configurable: false, writable: false, } - if (value !== undefined) { + if (value === undefined) { + target[key] = deepFreeze(target[key]) + } else { opts.value = deepFreeze(value) opts.enumerable = enumerable - } else { - target[key] = deepFreeze(target[key]) } Object.defineProperty(target, key, opts) diff --git a/app/scripts/lib/get-first-preferred-lang-code.js b/app/scripts/lib/get-first-preferred-lang-code.js index 00e50d7f4..d4bb61a8f 100644 --- a/app/scripts/lib/get-first-preferred-lang-code.js +++ b/app/scripts/lib/get-first-preferred-lang-code.js @@ -40,7 +40,7 @@ export default async function getFirstPreferredLangCode () { const firstPreferredLangCode = userPreferredLocaleCodes .map((code) => code.toLowerCase().replace('_', '-')) - .find((code) => existingLocaleCodes.hasOwnProperty(code)) + .find((code) => Object.prototype.hasOwnProperty.call(existingLocaleCodes, code)) return existingLocaleCodes[firstPreferredLangCode] || 'en' } diff --git a/app/scripts/lib/local-store.js b/app/scripts/lib/local-store.js index a0c0a667a..e7f05781c 100644 --- a/app/scripts/lib/local-store.js +++ b/app/scripts/lib/local-store.js @@ -6,11 +6,12 @@ import { checkForError } from './util' * A wrapper around the extension's storage local API */ export default class ExtensionStore { + /** * @constructor */ constructor () { - this.isSupported = !!(extension.storage.local) + this.isSupported = Boolean(extension.storage.local) if (!this.isSupported) { log.error('Storage local API not available.') } @@ -29,9 +30,8 @@ export default class ExtensionStore { // if the object is empty, treat it as undefined if (isEmpty(result)) { return undefined - } else { - return result } + return result } /** @@ -49,7 +49,7 @@ export default class ExtensionStore { * @returns {Object} - the key-value map from local storage */ _get () { - const local = extension.storage.local + const { local } = extension.storage return new Promise((resolve, reject) => { local.get(null, (/** @type {any} */ result) => { const err = checkForError() @@ -69,7 +69,7 @@ export default class ExtensionStore { * @private */ _set (obj) { - const local = extension.storage.local + const { local } = extension.storage return new Promise((resolve, reject) => { local.set(obj, () => { const err = checkForError() diff --git a/app/scripts/lib/message-manager.js b/app/scripts/lib/message-manager.js index b2de1eeab..280003c40 100644 --- a/app/scripts/lib/message-manager.js +++ b/app/scripts/lib/message-manager.js @@ -64,7 +64,8 @@ export default class MessageManager extends EventEmitter { getUnapprovedMsgs () { return this.messages.filter((msg) => msg.status === 'unapproved') .reduce((result, msg) => { - result[msg.id] = msg; return result + result[msg.id] = msg + return result }, {}) } @@ -114,8 +115,8 @@ export default class MessageManager extends EventEmitter { const msgId = createId() const msgData = { id: msgId, - msgParams: msgParams, - time: time, + msgParams, + time, status: 'unapproved', type: MESSAGE_TYPE.ETH_SIGN, } @@ -225,7 +226,7 @@ export default class MessageManager extends EventEmitter { _setMsgStatus (msgId, status) { 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) @@ -278,8 +279,7 @@ function normalizeMsgData (data) { if (data.slice(0, 2) === '0x') { // data is already hex return data - } else { - // data is unicode, convert to hex - return ethUtil.bufferToHex(Buffer.from(data, 'utf8')) } + // data is unicode, convert to hex + return ethUtil.bufferToHex(Buffer.from(data, 'utf8')) } diff --git a/app/scripts/lib/migrator/index.js b/app/scripts/lib/migrator/index.js index a82b93294..5c2f6185f 100644 --- a/app/scripts/lib/migrator/index.js +++ b/app/scripts/lib/migrator/index.js @@ -46,6 +46,7 @@ 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 } catch (err) { // rewrite error message to add context without clobbering stack diff --git a/app/scripts/lib/nodeify.js b/app/scripts/lib/nodeify.js index 5d4eb8c4d..074fba3bb 100644 --- a/app/scripts/lib/nodeify.js +++ b/app/scripts/lib/nodeify.js @@ -15,9 +15,7 @@ const callbackNoop = function (err) { * */ export default function nodeify (fn, context) { - return function () { - // parse arguments - const args = [].slice.call(arguments) + return function (...args) { const lastArg = args[args.length - 1] const lastArgIsCallback = typeof lastArg === 'function' let callback diff --git a/app/scripts/lib/personal-message-manager.js b/app/scripts/lib/personal-message-manager.js index 067c696bd..52c0f9bad 100644 --- a/app/scripts/lib/personal-message-manager.js +++ b/app/scripts/lib/personal-message-manager.js @@ -2,11 +2,11 @@ import EventEmitter from 'events' import ObservableStore from 'obs-store' import ethUtil from 'ethereumjs-util' import { ethErrors } from 'eth-json-rpc-errors' +import log from 'loglevel' import createId from './random-id' import { MESSAGE_TYPE } from './enums' -const hexRe = /^[0-9A-Fa-f]+$/g -import log from 'loglevel' +const hexRe = /^[0-9A-Fa-f]+$/ug /** * Represents, and contains data about, an 'personal_sign' type signature request. These are created when a @@ -28,6 +28,7 @@ import log from 'loglevel' */ export default class PersonalMessageManager extends EventEmitter { + /** * Controller in charge of managing - storing, adding, removing, updating - PersonalMessage. * @@ -68,7 +69,8 @@ export default class PersonalMessageManager extends EventEmitter { getUnapprovedMsgs () { return this.messages.filter((msg) => msg.status === 'unapproved') .reduce((result, msg) => { - result[msg.id] = msg; return result + result[msg.id] = msg + return result }, {}) } @@ -85,17 +87,20 @@ export default class PersonalMessageManager extends EventEmitter { addUnapprovedMessageAsync (msgParams, req) { return new Promise((resolve, reject) => { if (!msgParams.from) { - return reject(new Error('MetaMask Message Signature: from field is required.')) + reject(new Error('MetaMask Message Signature: from field is required.')) + return } const msgId = this.addUnapprovedMessage(msgParams, req) this.once(`${msgId}:finished`, (data) => { switch (data.status) { case 'signed': - return resolve(data.rawSig) + resolve(data.rawSig) + return case 'rejected': - return reject(ethErrors.provider.userRejectedRequest('MetaMask Message Signature: User denied message signature.')) + reject(ethErrors.provider.userRejectedRequest('MetaMask Message Signature: User denied message signature.')) + return default: - return reject(new Error(`MetaMask Message Signature: Unknown problem: ${JSON.stringify(msgParams)}`)) + reject(new Error(`MetaMask Message Signature: Unknown problem: ${JSON.stringify(msgParams)}`)) } }) }) @@ -123,8 +128,8 @@ export default class PersonalMessageManager extends EventEmitter { const msgId = createId() const msgData = { id: msgId, - msgParams: msgParams, - time: time, + msgParams, + time, status: 'unapproved', type: MESSAGE_TYPE.PERSONAL_SIGN, } diff --git a/app/scripts/lib/random-id.js b/app/scripts/lib/random-id.js index f7abc4169..9345fcaad 100644 --- a/app/scripts/lib/random-id.js +++ b/app/scripts/lib/random-id.js @@ -2,6 +2,7 @@ const MAX = Number.MAX_SAFE_INTEGER let idCounter = Math.round(Math.random() * MAX) export default function createRandomId () { - idCounter = idCounter % MAX + idCounter %= MAX + // eslint-disable-next-line no-plusplus return idCounter++ } diff --git a/app/scripts/lib/seed-phrase-verifier.js b/app/scripts/lib/seed-phrase-verifier.js index f07e63a2c..71b9e2819 100644 --- a/app/scripts/lib/seed-phrase-verifier.js +++ b/app/scripts/lib/seed-phrase-verifier.js @@ -30,8 +30,8 @@ const seedPhraseVerifier = { const keyring = new Keyring(opts) const restoredAccounts = await keyring.getAccounts() - log.debug('Created accounts: ' + JSON.stringify(createdAccounts)) - log.debug('Restored accounts: ' + JSON.stringify(restoredAccounts)) + log.debug(`Created accounts: ${JSON.stringify(createdAccounts)}`) + log.debug(`Restored accounts: ${JSON.stringify(restoredAccounts)}`) if (restoredAccounts.length !== createdAccounts.length) { // this should not happen... @@ -40,7 +40,7 @@ const seedPhraseVerifier = { for (let i = 0; i < restoredAccounts.length; i++) { if (restoredAccounts[i].toLowerCase() !== createdAccounts[i].toLowerCase()) { - throw new Error('Not identical accounts! Original: ' + createdAccounts[i] + ', Restored: ' + restoredAccounts[i]) + throw new Error(`Not identical accounts! Original: ${createdAccounts[i]}, Restored: ${restoredAccounts[i]}`) } } }, diff --git a/app/scripts/lib/setupSentry.js b/app/scripts/lib/setupSentry.js index a6d1bb9b2..b5e4f2bec 100644 --- a/app/scripts/lib/setupSentry.js +++ b/app/scripts/lib/setupSentry.js @@ -3,8 +3,7 @@ import { Dedupe, ExtraErrorData } from '@sentry/integrations' import extractEthjsErrorMessage from './extractEthjsErrorMessage' -const METAMASK_DEBUG = process.env.METAMASK_DEBUG -const METAMASK_ENVIRONMENT = process.env.METAMASK_ENVIRONMENT +const { METAMASK_DEBUG, METAMASK_ENVIRONMENT } = process.env const SENTRY_DSN_DEV = 'https://f59f3dd640d2429d9d0e2445a87ea8e1@sentry.io/273496' // This describes the subset of Redux state attached to errors sent to Sentry @@ -72,7 +71,7 @@ export default function setupSentry ({ release, getState }) { let sentryTarget if (METAMASK_DEBUG) { - return + return undefined } else if (METAMASK_ENVIRONMENT === 'production') { if (!process.env.SENTRY_DSN) { throw new Error(`Missing SENTRY_DSN environment variable in production environment`) @@ -122,13 +121,13 @@ export default function setupSentry ({ release, getState }) { function simplifyErrorMessages (report) { rewriteErrorMessages(report, (errorMessage) => { // simplify ethjs error messages - errorMessage = extractEthjsErrorMessage(errorMessage) + let simplifiedErrorMessage = extractEthjsErrorMessage(errorMessage) // simplify 'Transaction Failed: known transaction' - if (errorMessage.indexOf('Transaction Failed: known transaction') === 0) { + if (simplifiedErrorMessage.indexOf('Transaction Failed: known transaction') === 0) { // cut the hash from the error message - errorMessage = 'Transaction Failed: known transaction' + simplifiedErrorMessage = 'Transaction Failed: known transaction' } - return errorMessage + return simplifiedErrorMessage }) } diff --git a/app/scripts/lib/setupWeb3.js b/app/scripts/lib/setupWeb3.js index 63d0ef67b..493ac2767 100644 --- a/app/scripts/lib/setupWeb3.js +++ b/app/scripts/lib/setupWeb3.js @@ -3,7 +3,7 @@ // TODO:deprecate:2020 // Delete this file -import 'web3/dist/web3.min.js' +import 'web3/dist/web3.min' const shouldLogUsage = !([ 'docs.metamask.io', diff --git a/app/scripts/lib/typed-message-manager.js b/app/scripts/lib/typed-message-manager.js index 3f5da3db1..64ce6427c 100644 --- a/app/scripts/lib/typed-message-manager.js +++ b/app/scripts/lib/typed-message-manager.js @@ -1,12 +1,12 @@ import EventEmitter from 'events' -import ObservableStore from 'obs-store' -import createId from './random-id' import assert from 'assert' +import ObservableStore from 'obs-store' import { ethErrors } from 'eth-json-rpc-errors' import sigUtil from 'eth-sig-util' import { isValidAddress } from 'ethereumjs-util' import log from 'loglevel' import jsonschema from 'jsonschema' +import createId from './random-id' import { MESSAGE_TYPE } from './enums' /** @@ -28,6 +28,7 @@ import { MESSAGE_TYPE } from './enums' */ export default class TypedMessageManager extends EventEmitter { + /** * Controller in charge of managing - storing, adding, removing, updating - TypedMessage. */ @@ -61,7 +62,8 @@ export default class TypedMessageManager extends EventEmitter { getUnapprovedMsgs () { return this.messages.filter((msg) => msg.status === 'unapproved') .reduce((result, msg) => { - result[msg.id] = msg; return result + result[msg.id] = msg + return result }, {}) } @@ -118,8 +120,8 @@ export default class TypedMessageManager extends EventEmitter { const msgId = createId() const msgData = { id: msgId, - msgParams: msgParams, - time: time, + msgParams, + time, status: 'unapproved', type: MESSAGE_TYPE.ETH_SIGN_TYPED_DATA, } @@ -154,7 +156,7 @@ export default class TypedMessageManager extends EventEmitter { }, 'Signing data must be valid EIP-712 typed data.') break case 'V3': - case 'V4': + case 'V4': { assert.equal(typeof params.data, 'string', '"params.data" must be a string.') let data assert.doesNotThrow(() => { @@ -163,10 +165,12 @@ export default class TypedMessageManager extends EventEmitter { const validation = jsonschema.validate(data, sigUtil.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.chainId + const { chainId } = data.domain + // eslint-disable-next-line radix const activeChainId = parseInt(this.networkController.getNetworkState()) chainId && assert.equal(chainId, activeChainId, `Provided chainId "${chainId}" must match the active chainId "${activeChainId}"`) break + } default: assert.fail(`Unknown typed data version "${params.version}"`) } @@ -291,7 +295,7 @@ export default class TypedMessageManager extends EventEmitter { _setMsgStatus (msgId, status) { const msg = this.getMsg(msgId) if (!msg) { - throw new Error('TypedMessageManager - Message not found for id: "${msgId}".') + throw new Error(`TypedMessageManager - Message not found for id: "${msgId}".`) } msg.status = status this._updateMsg(msg) diff --git a/app/scripts/lib/util.js b/app/scripts/lib/util.js index dfd3bc54c..08998d6cc 100644 --- a/app/scripts/lib/util.js +++ b/app/scripts/lib/util.js @@ -1,6 +1,6 @@ +import assert from 'assert' import extension from 'extensionizer' import ethUtil from 'ethereumjs-util' -import assert from 'assert' import BN from 'bn.js' import { memoize } from 'lodash' @@ -27,9 +27,8 @@ const getEnvironmentTypeMemo = memoize((url) => { return ENVIRONMENT_TYPE_FULLSCREEN } else if (parsedUrl.pathname === '/notification.html') { return ENVIRONMENT_TYPE_NOTIFICATION - } else { - return ENVIRONMENT_TYPE_BACKGROUND } + return ENVIRONMENT_TYPE_BACKGROUND }) /** @@ -55,19 +54,19 @@ const getEnvironmentType = (url = window.location.href) => getEnvironmentTypeMem */ const getPlatform = (_) => { const ua = window.navigator.userAgent - if (ua.search('Firefox') !== -1) { - return PLATFORM_FIREFOX - } else { + if (ua.search('Firefox') === -1) { if (window && window.chrome && window.chrome.ipcRenderer) { return PLATFORM_BRAVE - } else if (ua.search('Edge') !== -1) { - return PLATFORM_EDGE - } else if (ua.search('OPR') !== -1) { - return PLATFORM_OPERA - } else { - return PLATFORM_CHROME } + if (ua.search('Edge') !== -1) { + return PLATFORM_EDGE + } + if (ua.search('OPR') !== -1) { + return PLATFORM_OPERA + } + return PLATFORM_CHROME } + return PLATFORM_FIREFOX } /** @@ -135,12 +134,12 @@ function BnMultiplyByFraction (targetBN, numerator, denominator) { /** * Returns an Error if extension.runtime.lastError is present * this is a workaround for the non-standard error object that's used - * @returns {Error} + * @returns {Error|undefined} */ function checkForError () { - const lastError = extension.runtime.lastError + const { lastError } = extension.runtime if (!lastError) { - return + return undefined } // if it quacks like an Error, its an Error if (lastError.stack && lastError.message) { diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index b0866ce08..1c99424bc 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -10,22 +10,35 @@ import pump from 'pump' import Dnode from 'dnode' import extension from 'extensionizer' import ObservableStore from 'obs-store' -import ComposableObservableStore from './lib/ComposableObservableStore' import asStream from 'obs-store/lib/asStream' -import AccountTracker from './lib/account-tracker' import RpcEngine 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 'eth-contract-metadata' +import { + AddressBookController, + CurrencyRateController, + PhishingController, +} from '@metamask/controllers' +import ComposableObservableStore from './lib/ComposableObservableStore' +import AccountTracker from './lib/account-tracker' import createLoggerMiddleware from './lib/createLoggerMiddleware' import createMethodMiddleware from './lib/createMethodMiddleware' import createOriginMiddleware from './lib/createOriginMiddleware' import createTabIdMiddleware from './lib/createTabIdMiddleware' import createOnboardingMiddleware from './lib/createOnboardingMiddleware' -import providerAsMiddleware from 'eth-json-rpc-middleware/providerAsMiddleware' -import { setupMultiplex } from './lib/stream-utils.js' -import KeyringController from 'eth-keyring-controller' +import { setupMultiplex } from './lib/stream-utils' import EnsController from './controllers/ens' import NetworkController from './controllers/network' import PreferencesController from './controllers/preferences' @@ -47,25 +60,8 @@ import { PermissionsController } from './controllers/permissions' import getRestrictedMethods from './controllers/permissions/restrictedMethods' import nodeify from './lib/nodeify' import accountImporter from './account-import-strategies' -import getBuyEthUrl from './lib/buy-eth-url' import selectChainId from './lib/select-chain-id' -import { Mutex } from 'await-semaphore' -import { version } from '../manifest/_base.json' -import ethUtil from 'ethereumjs-util' - import seedPhraseVerifier from './lib/seed-phrase-verifier' -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 'eth-contract-metadata' - -import { - AddressBookController, - CurrencyRateController, - PhishingController, -} from '@metamask/controllers' import backgroundMetaMetricsEvent from './lib/background-metametrics' @@ -82,6 +78,7 @@ export default class MetamaskController extends EventEmitter { this.sendUpdate = debounce(this.privateSendUpdate.bind(this), 200) this.opts = opts + this.platform = opts.platform const initState = opts.initState || {} this.recordFirstTimeInfo(initState) @@ -89,9 +86,6 @@ export default class MetamaskController extends EventEmitter { // the only thing that uses controller connections are open metamask UI instances this.activeControllerConnections = 0 - // platform-specific api - this.platform = opts.platform - this.getRequestAccountTabIds = opts.getRequestAccountTabIds this.getOpenMetamaskTabsIds = opts.getOpenMetamaskTabsIds @@ -222,6 +216,7 @@ export default class MetamaskController extends EventEmitter { preferencesStore: this.preferencesController.store, }) + const version = this.platform.getVersion() this.threeBoxController = new ThreeBoxController({ preferencesController: this.preferencesController, addressBookController: this.addressBookController, @@ -278,7 +273,6 @@ export default class MetamaskController extends EventEmitter { this.encryptionPublicKeyManager = new EncryptionPublicKeyManager() this.typedMessageManager = new TypedMessageManager({ networkController: this.networkController }) - this.store.updateStructure({ AppStateController: this.appStateController.store, TransactionController: this.txController.store, @@ -336,6 +330,7 @@ export default class MetamaskController extends EventEmitter { * Constructor helper: initialize a provider. */ initializeProvider () { + const version = this.platform.getVersion() const providerOpts = { static: { eth_syncing: false, @@ -409,8 +404,8 @@ export default class MetamaskController extends EventEmitter { * @returns {Object} - status */ getState () { - const vault = this.keyringController.store.getState().vault - const isInitialized = !!vault + const { vault } = this.keyringController.store.getState() + const isInitialized = Boolean(vault) return { ...{ isInitialized }, @@ -426,14 +421,16 @@ export default class MetamaskController extends EventEmitter { * @returns {Object} - Object containing API functions. */ getApi () { - const keyringController = this.keyringController - const networkController = this.networkController - const onboardingController = this.onboardingController - const alertController = this.alertController - const permissionsController = this.permissionsController - const preferencesController = this.preferencesController - const threeBoxController = this.threeBoxController - const txController = this.txController + const { + keyringController, + networkController, + onboardingController, + alertController, + permissionsController, + preferencesController, + threeBoxController, + txController, + } = this return { // etc @@ -449,7 +446,6 @@ export default class MetamaskController extends EventEmitter { setCurrentLocale: this.setCurrentLocale.bind(this), markPasswordForgotten: this.markPasswordForgotten.bind(this), unMarkPasswordForgotten: this.unMarkPasswordForgotten.bind(this), - buyEth: this.buyEth.bind(this), safelistPhishingDomain: this.safelistPhishingDomain.bind(this), getRequestAccountTabIds: (cb) => cb(null, this.getRequestAccountTabIds()), getOpenMetamaskTabsIds: (cb) => cb(null, this.getOpenMetamaskTabsIds()), @@ -596,13 +592,11 @@ export default class MetamaskController extends EventEmitter { vault = await this.keyringController.fullUpdate() } else { vault = await this.keyringController.createNewVaultAndKeychain(password) - const accounts = await this.keyringController.getAccounts() - this.preferencesController.setAddresses(accounts) + const addresses = await this.keyringController.getAccounts() + this.preferencesController.setAddresses(addresses) this.selectFirstIdentity() } return vault - } catch (err) { - throw err } finally { releaseLock() } @@ -618,7 +612,7 @@ export default class MetamaskController extends EventEmitter { try { let accounts, lastBalance - const keyringController = this.keyringController + const { keyringController } = this // clear known identities this.preferencesController.setAddresses([]) @@ -658,8 +652,6 @@ export default class MetamaskController extends EventEmitter { this.preferencesController.setAddresses(accounts) this.selectFirstIdentity() return vault - } catch (err) { - throw err } finally { releaseLock() } @@ -714,15 +706,16 @@ export default class MetamaskController extends EventEmitter { Object.keys(accountTokens).forEach((address) => { const checksummedAddress = ethUtil.toChecksumAddress(address) filteredAccountTokens[checksummedAddress] = {} - Object.keys(accountTokens[address]).forEach( - (networkType) => (filteredAccountTokens[checksummedAddress][networkType] = networkType !== 'mainnet' ? - accountTokens[address][networkType] : - accountTokens[address][networkType].filter(({ address }) => { - const tokenAddress = ethUtil.toChecksumAddress(address) - return contractMap[tokenAddress] ? contractMap[tokenAddress].erc20 : true - }) - ), - ) + Object.keys(accountTokens[address]).forEach((networkType) => { + filteredAccountTokens[checksummedAddress][networkType] = networkType === 'mainnet' + ? ( + accountTokens[address][networkType].filter(({ address: tokenAddress }) => { + const checksumAddress = ethUtil.toChecksumAddress(tokenAddress) + return contractMap[checksumAddress] ? contractMap[checksumAddress].erc20 : true + }) + ) + : accountTokens[address][networkType] + }) }) const preferences = { @@ -751,7 +744,7 @@ export default class MetamaskController extends EventEmitter { // transactions - let transactions = this.txController.store.getState().transactions + 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) @@ -934,7 +927,6 @@ export default class MetamaskController extends EventEmitter { return { ...keyState, identities } } - // // Account Management // @@ -949,7 +941,7 @@ export default class MetamaskController extends EventEmitter { if (!primaryKeyring) { throw new Error('MetamaskController - No HD Key Tree found') } - const keyringController = this.keyringController + const { keyringController } = this const oldAccounts = await keyringController.getAccounts() const keyState = await keyringController.addNewAccount(primaryKeyring) const newAccounts = await keyringController.getAccounts() @@ -1034,7 +1026,6 @@ export default class MetamaskController extends EventEmitter { return address } - /** * Imports an account with the specified import strategy. * These are defined in app/scripts/account-import-strategies @@ -1046,7 +1037,7 @@ export default class MetamaskController extends EventEmitter { */ async importAccountWithStrategy (strategy, args) { const privateKey = await accountImporter.importAccount(strategy, args) - const keyring = await this.keyringController.addNewKeyring('Simple Key Pair', [ privateKey ]) + const keyring = await this.keyringController.addNewKeyring('Simple Key Pair', [privateKey]) const accounts = await keyring.getAccounts() // update accounts in preferences controller const allAccounts = await this.keyringController.getAccounts() @@ -1119,12 +1110,12 @@ export default class MetamaskController extends EventEmitter { * @param {string} msgId - The id of the message to cancel. */ cancelMessage (msgId, cb) { - const messageManager = this.messageManager + const { messageManager } = this messageManager.rejectMsg(msgId) - if (cb && typeof cb === 'function') { - cb(null, this.getState()) + if (!cb || typeof cb !== 'function') { return } + cb(null, this.getState()) } // personal_sign methods: @@ -1180,10 +1171,10 @@ export default class MetamaskController extends EventEmitter { cancelPersonalMessage (msgId, cb) { const messageManager = this.personalMessageManager messageManager.rejectMsg(msgId) - if (cb && typeof cb === 'function') { - cb(null, this.getState()) + if (!cb || typeof cb !== 'function') { return } + cb(null, this.getState()) } // eth_decrypt methods @@ -1265,10 +1256,10 @@ export default class MetamaskController extends EventEmitter { cancelDecryptMessage (msgId, cb) { const messageManager = this.decryptMessageManager messageManager.rejectMsg(msgId) - if (cb && typeof cb === 'function') { - cb(null, this.getState()) + if (!cb || typeof cb !== 'function') { return } + cb(null, this.getState()) } // eth_getEncryptionPublicKey methods @@ -1323,10 +1314,10 @@ export default class MetamaskController extends EventEmitter { cancelEncryptionPublicKey (msgId, cb) { const messageManager = this.encryptionPublicKeyManager messageManager.rejectMsg(msgId) - if (cb && typeof cb === 'function') { - cb(null, this.getState()) + if (!cb || typeof cb !== 'function') { return } + cb(null, this.getState()) } // eth_signTypedData methods @@ -1349,12 +1340,12 @@ export default class MetamaskController extends EventEmitter { * Triggers the callback in newUnsignedTypedMessage. * * @param {Object} msgParams - The params passed to eth_signTypedData. - * @returns {Object} - Full state update. + * @returns {Object|undefined} - Full state update. */ async signTypedMessage (msgParams) { log.info('MetaMaskController - eth_signTypedData') const msgId = msgParams.metamaskId - const version = msgParams.version + const { version } = msgParams try { const cleanMsgParams = await this.typedMessageManager.approveMessage(msgParams) @@ -1372,6 +1363,7 @@ export default class MetamaskController extends EventEmitter { } catch (error) { log.info('MetaMaskController - eth_signTypedData failed.', error) this.typedMessageManager.errorMessage(msgId, error) + return undefined } } @@ -1383,10 +1375,10 @@ export default class MetamaskController extends EventEmitter { cancelTypedMessage (msgId, cb) { const messageManager = this.typedMessageManager messageManager.rejectMsg(msgId) - if (cb && typeof cb === 'function') { - cb(null, this.getState()) + if (!cb || typeof cb !== 'function') { return } + cb(null, this.getState()) } //============================================================================= @@ -1401,13 +1393,9 @@ export default class MetamaskController extends EventEmitter { * @returns {Object} - MetaMask state */ async createCancelTransaction (originalTxId, customGasPrice) { - try { - await this.txController.createCancelTransaction(originalTxId, customGasPrice) - const state = await this.getState() - return state - } catch (error) { - throw error - } + await this.txController.createCancelTransaction(originalTxId, customGasPrice) + const state = await this.getState() + return state } async createSpeedUpTransaction (originalTxId, customGasPrice, customGasLimit) { @@ -1470,7 +1458,7 @@ export default class MetamaskController extends EventEmitter { */ setupUntrustedCommunication (connectionStream, sender) { const { usePhishDetect } = this.preferencesController.store.getState() - const hostname = (new URL(sender.url)).hostname + 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) @@ -1526,7 +1514,7 @@ export default class MetamaskController extends EventEmitter { const api = this.getApi() const dnode = Dnode(api) // report new active controller connection - this.activeControllerConnections++ + this.activeControllerConnections += 1 this.emit('controllerConnectionChanged', this.activeControllerConnections) // connect dnode api to remote connection pump( @@ -1535,7 +1523,7 @@ export default class MetamaskController extends EventEmitter { outStream, (err) => { // report new active controller connection - this.activeControllerConnections-- + this.activeControllerConnections -= 1 this.emit('controllerConnectionChanged', this.activeControllerConnections) // report any error if (err) { @@ -1609,8 +1597,7 @@ export default class MetamaskController extends EventEmitter { setupProviderEngine ({ origin, location, extensionId, tabId, isInternal = false }) { // setup json rpc engine stack const engine = new RpcEngine() - const provider = this.provider - const blockTracker = this.blockTracker + const { provider, blockTracker } = this // create filter polyfill middleware const filterMiddleware = createFilterMiddleware({ provider, blockTracker }) @@ -1850,6 +1837,7 @@ export default class MetamaskController extends EventEmitter { customVariables, eventOpts: { action, + category: 'Background', name, }, }, @@ -1880,28 +1868,11 @@ export default class MetamaskController extends EventEmitter { return } catch (err) { cb(err) + // eslint-disable-next-line no-useless-return return } } - /** - * A method for forwarding the user to the easiest way to obtain ether, - * or the network "gas" currency, for the current selected network. - * - * @param {string} address - The address to fund. - * @param {string} amount - The amount of ether desired, as a base 10 string. - */ - buyEth (address, amount) { - if (!amount) { - amount = '5' - } - const network = this.networkController.getNetworkState() - const url = getBuyEthUrl({ network, address, amount }) - if (url) { - this.platform.openTab({ url }) - } - } - // network /** * A method for selecting a custom URL for an ethereum RPC provider and updating it @@ -1918,7 +1889,6 @@ export default class MetamaskController extends EventEmitter { return rpcUrl } - /** * A method for selecting a custom URL for an ethereum RPC provider. * @param {string} rpcTarget - A URL for a valid Ethereum RPC API. @@ -1964,6 +1934,7 @@ export default class MetamaskController extends EventEmitter { return } catch (err) { cb(err) + // eslint-disable-next-line no-useless-return return } } @@ -1980,6 +1951,7 @@ export default class MetamaskController extends EventEmitter { return } catch (err) { cb(err) + // eslint-disable-next-line no-useless-return return } } @@ -1996,6 +1968,7 @@ export default class MetamaskController extends EventEmitter { return } catch (err) { cb(err) + // eslint-disable-next-line no-useless-return return } } @@ -2012,6 +1985,7 @@ export default class MetamaskController extends EventEmitter { return } catch (err) { cb(err) + // eslint-disable-next-line no-useless-return return } } @@ -2028,6 +2002,7 @@ export default class MetamaskController extends EventEmitter { return } catch (err) { cb(err) + // eslint-disable-next-line no-useless-return return } } @@ -2039,6 +2014,7 @@ export default class MetamaskController extends EventEmitter { return } catch (err) { cb(err) + // eslint-disable-next-line no-useless-return return } } @@ -2055,11 +2031,11 @@ export default class MetamaskController extends EventEmitter { return } catch (err) { cb(err) + // eslint-disable-next-line no-useless-return return } } - /** * A method for setting a user's current locale, affecting the language rendered. * @param {string} key - Locale identifier. @@ -2072,6 +2048,7 @@ export default class MetamaskController extends EventEmitter { return } catch (err) { cb(err) + // eslint-disable-next-line no-useless-return return } } @@ -2083,6 +2060,7 @@ export default class MetamaskController extends EventEmitter { */ recordFirstTimeInfo (initState) { if (!('firstTimeInfo' in initState)) { + const version = this.platform.getVersion() initState.firstTimeInfo = { version, date: Date.now(), diff --git a/app/scripts/migrations/002.js b/app/scripts/migrations/002.js index ce172365a..24df7f4de 100644 --- a/app/scripts/migrations/002.js +++ b/app/scripts/migrations/002.js @@ -1,12 +1,11 @@ -const version = 2 - import { cloneDeep } from 'lodash' +const version = 2 export default { version, - migrate: function (originalVersionedData) { + migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version try { @@ -14,7 +13,9 @@ export default { versionedData.data.config.provider.type = 'rpc' versionedData.data.config.provider.rpcTarget = 'https://rpc.metamask.io/' } - } catch (e) {} + } catch (_) { + // empty + } return Promise.resolve(versionedData) }, } diff --git a/app/scripts/migrations/003.js b/app/scripts/migrations/003.js index 15c9b2070..08e4be468 100644 --- a/app/scripts/migrations/003.js +++ b/app/scripts/migrations/003.js @@ -1,20 +1,22 @@ +import { cloneDeep } from 'lodash' + const version = 3 const oldTestRpc = 'https://rawtestrpc.metamask.io/' const newTestRpc = 'https://testrpc.metamask.io/' -import { cloneDeep } from 'lodash' - export default { version, - migrate: function (originalVersionedData) { + migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version try { if (versionedData.data.config.provider.rpcTarget === oldTestRpc) { versionedData.data.config.provider.rpcTarget = newTestRpc } - } catch (e) {} + } catch (_) { + // empty + } return Promise.resolve(versionedData) }, } diff --git a/app/scripts/migrations/004.js b/app/scripts/migrations/004.js index 358cbbea7..48741a267 100644 --- a/app/scripts/migrations/004.js +++ b/app/scripts/migrations/004.js @@ -1,11 +1,11 @@ -const version = 4 - import { cloneDeep } from 'lodash' +const version = 4 + export default { version, - migrate: function (versionedData) { + migrate (versionedData) { const safeVersionedData = cloneDeep(versionedData) safeVersionedData.meta.version = version try { @@ -25,7 +25,9 @@ export default { break // No default } - } catch (_) {} + } catch (_) { + // empty + } return Promise.resolve(safeVersionedData) }, } diff --git a/app/scripts/migrations/005.js b/app/scripts/migrations/005.js index 05587c432..baead6890 100644 --- a/app/scripts/migrations/005.js +++ b/app/scripts/migrations/005.js @@ -1,5 +1,3 @@ -const version = 5 - /* This migration moves state from the flat state trie into KeyringController substate @@ -8,11 +6,12 @@ This migration moves state from the flat state trie into KeyringController subst import { cloneDeep } from 'lodash' +const version = 5 export default { version, - migrate: function (originalVersionedData) { + migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version try { @@ -20,14 +19,14 @@ export default { 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) }, } function selectSubstateForKeyringController (state) { - const config = state.config + const { config } = state const newState = { ...state, KeyringController: { diff --git a/app/scripts/migrations/006.js b/app/scripts/migrations/006.js index b53015315..8d1e72935 100644 --- a/app/scripts/migrations/006.js +++ b/app/scripts/migrations/006.js @@ -1,5 +1,3 @@ -const version = 6 - /* This migration moves KeyringController.selectedAddress to PreferencesController.selectedAddress @@ -8,10 +6,12 @@ This migration moves KeyringController.selectedAddress to PreferencesController. import { cloneDeep } from 'lodash' +const version = 6 + export default { version, - migrate: function (originalVersionedData) { + migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version try { @@ -19,7 +19,7 @@ export default { 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) }, diff --git a/app/scripts/migrations/007.js b/app/scripts/migrations/007.js index bacf005fa..41272ee3b 100644 --- a/app/scripts/migrations/007.js +++ b/app/scripts/migrations/007.js @@ -1,5 +1,3 @@ -const version = 7 - /* This migration breaks out the TransactionManager substate @@ -8,10 +6,12 @@ This migration breaks out the TransactionManager substate import { cloneDeep } from 'lodash' +const version = 7 + export default { version, - migrate: function (originalVersionedData) { + migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version try { @@ -19,7 +19,7 @@ export default { 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) }, diff --git a/app/scripts/migrations/008.js b/app/scripts/migrations/008.js index a4537ae9b..6f25bbcd5 100644 --- a/app/scripts/migrations/008.js +++ b/app/scripts/migrations/008.js @@ -1,5 +1,3 @@ -const version = 8 - /* This migration breaks out the NoticeController substate @@ -8,10 +6,12 @@ This migration breaks out the NoticeController substate import { cloneDeep } from 'lodash' +const version = 8 + export default { version, - migrate: function (originalVersionedData) { + migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version try { @@ -19,7 +19,7 @@ export default { 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) }, diff --git a/app/scripts/migrations/009.js b/app/scripts/migrations/009.js index 3fddf7aa9..f63297836 100644 --- a/app/scripts/migrations/009.js +++ b/app/scripts/migrations/009.js @@ -1,5 +1,3 @@ -const version = 9 - /* This migration breaks out the CurrencyController substate @@ -8,10 +6,12 @@ This migration breaks out the CurrencyController substate import { cloneDeep, merge } from 'lodash' +const version = 9 + export default { version, - migrate: function (originalVersionedData) { + migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version try { @@ -19,7 +19,7 @@ export default { 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) }, diff --git a/app/scripts/migrations/010.js b/app/scripts/migrations/010.js index c8dd42aaf..354b19871 100644 --- a/app/scripts/migrations/010.js +++ b/app/scripts/migrations/010.js @@ -1,5 +1,3 @@ -const version = 10 - /* This migration breaks out the ShapeShiftController substate @@ -8,10 +6,12 @@ This migration breaks out the ShapeShiftController substate import { cloneDeep, merge } from 'lodash' +const version = 10 + export default { version, - migrate: function (originalVersionedData) { + migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version try { @@ -19,7 +19,7 @@ export default { 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) }, diff --git a/app/scripts/migrations/011.js b/app/scripts/migrations/011.js index d465bf5a6..d8f852f9f 100644 --- a/app/scripts/migrations/011.js +++ b/app/scripts/migrations/011.js @@ -1,5 +1,3 @@ -const version = 11 - /* This migration removes the discaimer state from our app, which was integrated into our notices. @@ -8,10 +6,12 @@ This migration removes the discaimer state from our app, which was integrated in import { cloneDeep } from 'lodash' +const version = 11 + export default { version, - migrate: function (originalVersionedData) { + migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version try { @@ -19,7 +19,7 @@ export default { 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) }, diff --git a/app/scripts/migrations/012.js b/app/scripts/migrations/012.js index fc3ddc59c..d01edbc41 100644 --- a/app/scripts/migrations/012.js +++ b/app/scripts/migrations/012.js @@ -1,5 +1,3 @@ -const version = 12 - /* This migration modifies our notices to delete their body after being read. @@ -8,10 +6,12 @@ This migration modifies our notices to delete their body after being read. import { cloneDeep } from 'lodash' +const version = 12 + export default { version, - migrate: function (originalVersionedData) { + migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version try { @@ -19,7 +19,7 @@ export default { 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) }, diff --git a/app/scripts/migrations/013.js b/app/scripts/migrations/013.js index 433face72..530fc687c 100644 --- a/app/scripts/migrations/013.js +++ b/app/scripts/migrations/013.js @@ -1,5 +1,3 @@ -const version = 13 - /* This migration modifies the network config from ambiguous 'testnet' to explicit 'ropsten' @@ -8,10 +6,12 @@ This migration modifies the network config from ambiguous 'testnet' to explicit import { cloneDeep } from 'lodash' +const version = 13 + export default { version, - migrate: function (originalVersionedData) { + migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version try { @@ -19,7 +19,7 @@ export default { 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) }, diff --git a/app/scripts/migrations/014.js b/app/scripts/migrations/014.js index e7a7b8c99..630aa2051 100644 --- a/app/scripts/migrations/014.js +++ b/app/scripts/migrations/014.js @@ -1,5 +1,3 @@ -const version = 14 - /* This migration removes provider from config and moves it too NetworkController. @@ -8,10 +6,12 @@ This migration removes provider from config and moves it too NetworkController. import { cloneDeep } from 'lodash' +const version = 14 + export default { version, - migrate: function (originalVersionedData) { + migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version try { @@ -19,7 +19,7 @@ export default { 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) }, diff --git a/app/scripts/migrations/015.js b/app/scripts/migrations/015.js index 4ea61b7d1..682eb8db7 100644 --- a/app/scripts/migrations/015.js +++ b/app/scripts/migrations/015.js @@ -1,5 +1,3 @@ -const version = 15 - /* This migration sets transactions with the 'Gave up submitting tx.' err message @@ -9,10 +7,12 @@ to a 'failed' stated import { cloneDeep } from 'lodash' +const version = 15 + export default { version, - migrate: function (originalVersionedData) { + migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version try { @@ -20,7 +20,7 @@ export default { 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) }, @@ -30,7 +30,7 @@ function transformState (state) { const newState = state const { TransactionController } = newState if (TransactionController && TransactionController.transactions) { - const transactions = TransactionController.transactions + const { transactions } = TransactionController newState.TransactionController.transactions = transactions.map((txMeta) => { if (!txMeta.err) { return txMeta diff --git a/app/scripts/migrations/016.js b/app/scripts/migrations/016.js index 341658e06..974a1125d 100644 --- a/app/scripts/migrations/016.js +++ b/app/scripts/migrations/016.js @@ -1,5 +1,3 @@ -const version = 16 - /* This migration sets transactions with the 'Gave up submitting tx.' err message @@ -9,10 +7,12 @@ to a 'failed' stated import { cloneDeep } from 'lodash' +const version = 16 + export default { version, - migrate: function (originalVersionedData) { + migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version try { @@ -20,7 +20,7 @@ export default { 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) }, @@ -30,7 +30,7 @@ function transformState (state) { const newState = state const { TransactionController } = newState if (TransactionController && TransactionController.transactions) { - const transactions = newState.TransactionController.transactions + const { transactions } = newState.TransactionController newState.TransactionController.transactions = transactions.map((txMeta) => { if (!txMeta.err) { diff --git a/app/scripts/migrations/017.js b/app/scripts/migrations/017.js index e39d7855d..497cbe33e 100644 --- a/app/scripts/migrations/017.js +++ b/app/scripts/migrations/017.js @@ -1,5 +1,3 @@ -const version = 17 - /* This migration sets transactions who were retried and marked as failed to submitted @@ -8,10 +6,12 @@ This migration sets transactions who were retried and marked as failed to submit import { cloneDeep } from 'lodash' +const version = 17 + export default { version, - migrate: function (originalVersionedData) { + migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version try { @@ -19,7 +19,7 @@ export default { 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) }, @@ -29,7 +29,7 @@ function transformState (state) { const newState = state const { TransactionController } = newState if (TransactionController && TransactionController.transactions) { - const transactions = newState.TransactionController.transactions + const { transactions } = newState.TransactionController newState.TransactionController.transactions = transactions.map((txMeta) => { if (!txMeta.status === 'failed') { return txMeta diff --git a/app/scripts/migrations/018.js b/app/scripts/migrations/018.js index 7a182ab2a..bb57ddf0c 100644 --- a/app/scripts/migrations/018.js +++ b/app/scripts/migrations/018.js @@ -1,5 +1,3 @@ -const version = 18 - /* This migration updates "transaction state history" to diffs style @@ -12,11 +10,12 @@ import { migrateFromSnapshotsToDiffs, } from '../controllers/transactions/lib/tx-state-history-helpers' +const version = 18 export default { version, - migrate: function (originalVersionedData) { + migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version try { @@ -24,7 +23,7 @@ export default { 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) }, @@ -34,7 +33,7 @@ function transformState (state) { const newState = state const { TransactionController } = newState if (TransactionController && TransactionController.transactions) { - const transactions = newState.TransactionController.transactions + const { transactions } = newState.TransactionController newState.TransactionController.transactions = transactions.map((txMeta) => { // no history: initialize if (!txMeta.history || txMeta.history.length === 0) { diff --git a/app/scripts/migrations/019.js b/app/scripts/migrations/019.js index e87bdad62..4c786b7c9 100644 --- a/app/scripts/migrations/019.js +++ b/app/scripts/migrations/019.js @@ -1,6 +1,4 @@ -const version = 19 - /* This migration sets transactions as failed @@ -10,10 +8,12 @@ whos nonce is too high import { cloneDeep } from 'lodash' +const version = 19 + export default { version, - migrate: function (originalVersionedData) { + migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version try { @@ -21,7 +21,7 @@ export default { 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) }, @@ -32,7 +32,7 @@ function transformState (state) { const { TransactionController } = newState if (TransactionController && TransactionController.transactions) { - const transactions = newState.TransactionController.transactions + const { transactions } = newState.TransactionController newState.TransactionController.transactions = transactions.map((txMeta, _, txList) => { if (txMeta.status !== 'submitted') { @@ -66,13 +66,13 @@ function transformState (state) { function getHighestContinuousFrom (txList, startPoint) { const nonces = txList.map((txMeta) => { - const nonce = txMeta.txParams.nonce + const { nonce } = txMeta.txParams return parseInt(nonce, 16) }) let highest = startPoint while (nonces.includes(highest)) { - highest++ + highest += 1 } return highest @@ -80,7 +80,7 @@ function getHighestContinuousFrom (txList, startPoint) { function getHighestNonce (txList) { const nonces = txList.map((txMeta) => { - const nonce = txMeta.txParams.nonce + const { nonce } = txMeta.txParams return parseInt(nonce || '0x0', 16) }) const highestNonce = Math.max.apply(null, nonces) diff --git a/app/scripts/migrations/020.js b/app/scripts/migrations/020.js index eaf6dcbc0..eb8080124 100644 --- a/app/scripts/migrations/020.js +++ b/app/scripts/migrations/020.js @@ -1,5 +1,3 @@ -const version = 20 - /* This migration ensures previous installations @@ -10,10 +8,12 @@ so that we can version notices in the future. import { cloneDeep } from 'lodash' +const version = 20 + export default { version, - migrate: function (originalVersionedData) { + migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version try { @@ -21,7 +21,7 @@ export default { 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) }, diff --git a/app/scripts/migrations/021.js b/app/scripts/migrations/021.js index c57266f08..ac3170131 100644 --- a/app/scripts/migrations/021.js +++ b/app/scripts/migrations/021.js @@ -1,5 +1,3 @@ -const version = 21 - /* This migration removes the BlackListController from disk state @@ -8,10 +6,12 @@ This migration removes the BlackListController from disk state import { cloneDeep } from 'lodash' +const version = 21 + export default { version, - migrate: function (originalVersionedData) { + migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version try { @@ -19,7 +19,7 @@ export default { 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) }, diff --git a/app/scripts/migrations/022.js b/app/scripts/migrations/022.js index b986a94f4..76f96a0ae 100644 --- a/app/scripts/migrations/022.js +++ b/app/scripts/migrations/022.js @@ -1,6 +1,4 @@ -const version = 22 - /* This migration adds submittedTime to the txMeta if it is not their @@ -9,10 +7,12 @@ This migration adds submittedTime to the txMeta if it is not their import { cloneDeep } from 'lodash' +const version = 22 + export default { version, - migrate: function (originalVersionedData) { + migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version try { @@ -20,7 +20,7 @@ export default { 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) }, @@ -30,7 +30,7 @@ function transformState (state) { const newState = state const { TransactionController } = newState if (TransactionController && TransactionController.transactions) { - const transactions = newState.TransactionController.transactions + const { transactions } = newState.TransactionController newState.TransactionController.transactions = transactions.map((txMeta) => { if (txMeta.status !== 'submitted' || txMeta.submittedTime) { diff --git a/app/scripts/migrations/023.js b/app/scripts/migrations/023.js index af4ee8d45..5f0363d53 100644 --- a/app/scripts/migrations/023.js +++ b/app/scripts/migrations/023.js @@ -1,6 +1,4 @@ -const version = 23 - /* This migration removes transactions that are no longer usefull down to 40 total @@ -9,10 +7,12 @@ This migration removes transactions that are no longer usefull down to 40 total import { cloneDeep } from 'lodash' +const version = 23 + export default { version, - migrate: function (originalVersionedData) { + migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version try { @@ -20,7 +20,7 @@ export default { 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) }, @@ -31,7 +31,7 @@ function transformState (state) { const { TransactionController } = newState if (TransactionController && TransactionController.transactions) { - const transactions = newState.TransactionController.transactions + const { transactions } = newState.TransactionController if (transactions.length <= 40) { return newState diff --git a/app/scripts/migrations/024.js b/app/scripts/migrations/024.js index 569c817c2..84a998d12 100644 --- a/app/scripts/migrations/024.js +++ b/app/scripts/migrations/024.js @@ -1,6 +1,4 @@ -const version = 24 - /* This migration ensures that the from address in txParams is to lower case for @@ -10,10 +8,12 @@ all unapproved transactions import { cloneDeep } from 'lodash' +const version = 24 + export default { version, - migrate: async function (originalVersionedData) { + async migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version const state = versionedData.data @@ -28,7 +28,7 @@ function transformState (state) { if (!newState.TransactionController) { return newState } - const transactions = newState.TransactionController.transactions + const { transactions } = newState.TransactionController newState.TransactionController.transactions = transactions.map((txMeta, _) => { if ( txMeta.status === 'unapproved' && diff --git a/app/scripts/migrations/025.js b/app/scripts/migrations/025.js index 1f3721d27..72bcdbf01 100644 --- a/app/scripts/migrations/025.js +++ b/app/scripts/migrations/025.js @@ -1,6 +1,4 @@ // next version number -const version = 25 - /* normalizes txParams on unconfirmed txs @@ -10,10 +8,12 @@ import ethUtil from 'ethereumjs-util' import { cloneDeep } from 'lodash' +const version = 25 + export default { version, - migrate: async function (originalVersionedData) { + async migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version const state = versionedData.data @@ -28,7 +28,7 @@ function transformState (state) { if (newState.TransactionController) { if (newState.TransactionController.transactions) { - const transactions = newState.TransactionController.transactions + const { transactions } = newState.TransactionController newState.TransactionController.transactions = transactions.map((txMeta) => { if (txMeta.status !== 'unapproved') { return txMeta diff --git a/app/scripts/migrations/026.js b/app/scripts/migrations/026.js index 2282455ef..e6cb9db85 100644 --- a/app/scripts/migrations/026.js +++ b/app/scripts/migrations/026.js @@ -1,5 +1,3 @@ -const version = 26 - /* This migration moves the identities stored in the KeyringController @@ -9,6 +7,8 @@ This migration moves the identities stored in the KeyringController import { cloneDeep } from 'lodash' +const version = 26 + export default { version, migrate (originalVersionedData) { @@ -18,7 +18,7 @@ export default { const state = versionedData.data versionedData.data = transformState(state) } catch (err) { - console.warn(`MetaMask Migration #${version}` + err.stack) + console.warn(`MetaMask Migration #${version}${err.stack}`) return Promise.reject(err) } return Promise.resolve(versionedData) diff --git a/app/scripts/migrations/027.js b/app/scripts/migrations/027.js index dc4d0beb7..42e024f56 100644 --- a/app/scripts/migrations/027.js +++ b/app/scripts/migrations/027.js @@ -1,6 +1,4 @@ // next version number -const version = 27 - /* normalizes txParams on unconfirmed txs @@ -8,10 +6,12 @@ normalizes txParams on unconfirmed txs */ import { cloneDeep } from 'lodash' +const version = 27 + export default { version, - migrate: async function (originalVersionedData) { + async migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version const state = versionedData.data @@ -26,7 +26,7 @@ function transformState (state) { if (newState.TransactionController) { if (newState.TransactionController.transactions) { - const transactions = newState.TransactionController.transactions + const { transactions } = newState.TransactionController newState.TransactionController.transactions = transactions.filter((txMeta) => txMeta.status !== 'rejected') } } diff --git a/app/scripts/migrations/028.js b/app/scripts/migrations/028.js index 09fc18f11..fa816ca53 100644 --- a/app/scripts/migrations/028.js +++ b/app/scripts/migrations/028.js @@ -1,6 +1,4 @@ // next version number -const version = 28 - /* normalizes txParams on unconfirmed txs @@ -8,10 +6,12 @@ normalizes txParams on unconfirmed txs */ import { cloneDeep } from 'lodash' +const version = 28 + export default { version, - migrate: async function (originalVersionedData) { + async migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version const state = versionedData.data @@ -26,8 +26,7 @@ function transformState (state) { if (newState.PreferencesController) { if (newState.PreferencesController.tokens && newState.PreferencesController.identities) { - const identities = newState.PreferencesController.identities - const tokens = newState.PreferencesController.tokens + const { identities, tokens } = newState.PreferencesController newState.PreferencesController.accountTokens = {} Object.keys(identities).forEach((identity) => { newState.PreferencesController.accountTokens[identity] = { 'mainnet': tokens } diff --git a/app/scripts/migrations/029.js b/app/scripts/migrations/029.js index 345d1ad92..4773eb466 100644 --- a/app/scripts/migrations/029.js +++ b/app/scripts/migrations/029.js @@ -1,7 +1,8 @@ // next version number -const version = 29 import failTxsThat from './fail-tx' +const version = 29 + // time const seconds = 1000 const minutes = 60 * seconds diff --git a/app/scripts/migrations/030.js b/app/scripts/migrations/030.js index 499f8d664..6f11e27a5 100644 --- a/app/scripts/migrations/030.js +++ b/app/scripts/migrations/030.js @@ -1,6 +1,4 @@ // next version number -const version = 30 - /* removes invalid chaids from preferences and networkController for custom rpcs @@ -9,10 +7,12 @@ removes invalid chaids from preferences and networkController for custom rpcs import { cloneDeep } from 'lodash' +const version = 30 + export default { version, - migrate: async function (originalVersionedData) { + async migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version const state = versionedData.data @@ -25,10 +25,11 @@ export default { function transformState (state) { const newState = state if (state.PreferencesController) { - const frequentRpcListDetail = newState.PreferencesController.frequentRpcListDetail + const { frequentRpcListDetail } = newState.PreferencesController if (frequentRpcListDetail) { frequentRpcListDetail.forEach((rpc, index) => { - if (!!rpc.chainId && Number.isNaN(parseInt(rpc.chainId))) { + // eslint-disable-next-line radix + if (Boolean(rpc.chainId) && Number.isNaN(parseInt(rpc.chainId))) { delete frequentRpcListDetail[index].chainId } }) @@ -36,10 +37,12 @@ function transformState (state) { } } if (state.NetworkController) { + // eslint-disable-next-line radix if (newState.NetworkController.network && Number.isNaN(parseInt(newState.NetworkController.network))) { delete newState.NetworkController.network } + // eslint-disable-next-line radix if (newState.NetworkController.provider && newState.NetworkController.provider.chainId && Number.isNaN(parseInt(newState.NetworkController.provider.chainId))) { delete newState.NetworkController.provider.chainId } diff --git a/app/scripts/migrations/031.js b/app/scripts/migrations/031.js index 14d4a7ef8..59a8dcf15 100644 --- a/app/scripts/migrations/031.js +++ b/app/scripts/migrations/031.js @@ -1,7 +1,8 @@ // next version number -const version = 31 import { cloneDeep } from 'lodash' +const version = 31 + /* * The purpose of this migration is to properly set the completedOnboarding flag based on the state * of the KeyringController. @@ -9,7 +10,7 @@ import { cloneDeep } from 'lodash' export default { version, - migrate: async function (originalVersionedData) { + async migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version const state = versionedData.data diff --git a/app/scripts/migrations/032.js b/app/scripts/migrations/032.js index 4f807617d..fce4d65a6 100644 --- a/app/scripts/migrations/032.js +++ b/app/scripts/migrations/032.js @@ -1,12 +1,13 @@ -const version = 32 import { cloneDeep } from 'lodash' +const version = 32 + /** * The purpose of this migration is to set the {@code completedUiMigration} flag based on the user's UI preferences */ export default { version, - migrate: async function (originalVersionedData) { + async migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version const state = versionedData.data diff --git a/app/scripts/migrations/033.js b/app/scripts/migrations/033.js index 70710e793..e1e0ea3b4 100644 --- a/app/scripts/migrations/033.js +++ b/app/scripts/migrations/033.js @@ -1,6 +1,4 @@ // next version number -const version = 33 - /* Cleans up notices and assocated notice controller code @@ -9,10 +7,12 @@ Cleans up notices and assocated notice controller code import { cloneDeep } from 'lodash' +const version = 33 + export default { version, - migrate: async function (originalVersionedData) { + async migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version const state = versionedData.data diff --git a/app/scripts/migrations/034.js b/app/scripts/migrations/034.js index 92a8d909f..ba61131e4 100644 --- a/app/scripts/migrations/034.js +++ b/app/scripts/migrations/034.js @@ -1,13 +1,14 @@ -const version = 34 import { cloneDeep } from 'lodash' +const version = 34 + /** * The purpose of this migration is to enable the {@code privacyMode} feature flag and set the user as being migrated * if it was {@code false}. */ export default { version, - migrate: async function (originalVersionedData) { + async migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version const state = versionedData.data diff --git a/app/scripts/migrations/035.js b/app/scripts/migrations/035.js index b483c35de..6ea634730 100644 --- a/app/scripts/migrations/035.js +++ b/app/scripts/migrations/035.js @@ -1,6 +1,4 @@ // next version number -const version = 35 - /* Removes the deprecated 'seedWords' state @@ -9,10 +7,12 @@ Removes the deprecated 'seedWords' state import { cloneDeep } from 'lodash' +const version = 35 + export default { version, - migrate: async function (originalVersionedData) { + async migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version versionedData.data = transformState(versionedData.data) diff --git a/app/scripts/migrations/036.js b/app/scripts/migrations/036.js index 0ba0bc035..2b64fc6ea 100644 --- a/app/scripts/migrations/036.js +++ b/app/scripts/migrations/036.js @@ -1,12 +1,13 @@ -const version = 36 import { cloneDeep } from 'lodash' +const version = 36 + /** * The purpose of this migration is to remove the {@code privacyMode} feature flag. */ export default { version, - migrate: async function (originalVersionedData) { + async migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version const state = versionedData.data diff --git a/app/scripts/migrations/037.js b/app/scripts/migrations/037.js index 1d7f13810..e650337d4 100644 --- a/app/scripts/migrations/037.js +++ b/app/scripts/migrations/037.js @@ -1,7 +1,8 @@ -const version = 37 import { cloneDeep } from 'lodash' import { util } from '@metamask/controllers' +const version = 37 + /** * The purpose of this migration is to update the address book state * to the new schema with chainId as a key. @@ -9,7 +10,7 @@ import { util } from '@metamask/controllers' */ export default { version, - migrate: async function (originalVersionedData) { + async migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version const state = versionedData.data diff --git a/app/scripts/migrations/038.js b/app/scripts/migrations/038.js index fdbaa1d3b..b104fe49f 100644 --- a/app/scripts/migrations/038.js +++ b/app/scripts/migrations/038.js @@ -1,12 +1,13 @@ -const version = 38 import { cloneDeep } from 'lodash' +const version = 38 + /** * The purpose of this migration is to assign all users to a test group for the fullScreenVsPopup a/b test */ export default { version, - migrate: async function (originalVersionedData) { + async migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version const state = versionedData.data @@ -19,17 +20,18 @@ function transformState (state) { const { ABTestController: ABTestControllerState = {} } = state const { abTests = {} } = ABTestControllerState - if (!abTests.fullScreenVsPopup) { - state = { - ...state, - ABTestController: { - ...ABTestControllerState, - abTests: { - ...abTests, - fullScreenVsPopup: 'control', - }, - }, - } + if (abTests.fullScreenVsPopup) { + return state + } + + return { + ...state, + ABTestController: { + ...ABTestControllerState, + abTests: { + ...abTests, + fullScreenVsPopup: 'control', + }, + }, } - return state } diff --git a/app/scripts/migrations/039.js b/app/scripts/migrations/039.js index f1f38c0a5..d190b4f9b 100644 --- a/app/scripts/migrations/039.js +++ b/app/scripts/migrations/039.js @@ -1,7 +1,8 @@ -const version = 39 import { cloneDeep } from 'lodash' import ethUtil from 'ethereumjs-util' +const version = 39 + const DAI_V1_CONTRACT_ADDRESS = '0x89d24A6b4CcB1B6fAA2625fE562bDD9a23260359' const DAI_V1_TOKEN_SYMBOL = 'DAI' const SAI_TOKEN_SYMBOL = 'SAI' @@ -21,7 +22,7 @@ function isOldDai (token = {}) { */ export default { version, - migrate: async function (originalVersionedData) { + async migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version const state = versionedData.data diff --git a/app/scripts/migrations/040.js b/app/scripts/migrations/040.js index ca243e4aa..93b0e72be 100644 --- a/app/scripts/migrations/040.js +++ b/app/scripts/migrations/040.js @@ -1,6 +1,7 @@ -const version = 40 import { cloneDeep } from 'lodash' +const version = 40 + /** * Site connections are now managed by the PermissionsController, and the * ProviderApprovalController is removed. This migration deletes all @@ -8,7 +9,7 @@ import { cloneDeep } from 'lodash' */ export default { version, - migrate: async function (originalVersionedData) { + async migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version const state = versionedData.data diff --git a/app/scripts/migrations/041.js b/app/scripts/migrations/041.js index 83028ed1b..9e81312c3 100644 --- a/app/scripts/migrations/041.js +++ b/app/scripts/migrations/041.js @@ -1,12 +1,13 @@ -const version = 41 import { cloneDeep } from 'lodash' +const version = 41 + /** * PreferencesController.autoLogoutTimeLimit -> autoLockTimeLimit */ export default { version, - migrate: async function (originalVersionedData) { + async migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version const state = versionedData.data diff --git a/app/scripts/migrations/042.js b/app/scripts/migrations/042.js index 4c1fb510a..ed8b9f7cc 100644 --- a/app/scripts/migrations/042.js +++ b/app/scripts/migrations/042.js @@ -1,13 +1,14 @@ -const version = 42 import { cloneDeep } from 'lodash' +const version = 42 + /** * Initialize `connectedStatusPopoverHasBeenShown` to `false` if it hasn't yet been set, * so that existing users are introduced to the new connected status indicator */ export default { version, - migrate: async function (originalVersionedData) { + async migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version const state = versionedData.data diff --git a/app/scripts/migrations/043.js b/app/scripts/migrations/043.js index c024b7949..ad2dddde5 100644 --- a/app/scripts/migrations/043.js +++ b/app/scripts/migrations/043.js @@ -1,12 +1,13 @@ -const version = 43 import { cloneDeep } from 'lodash' +const version = 43 + /** * Remove unused 'currentAccountTab' state */ export default { version, - migrate: async function (originalVersionedData) { + async migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version const state = versionedData.data diff --git a/app/scripts/migrations/044.js b/app/scripts/migrations/044.js index 39c9b546f..00a23c012 100644 --- a/app/scripts/migrations/044.js +++ b/app/scripts/migrations/044.js @@ -1,12 +1,13 @@ -const version = 44 import { cloneDeep } from 'lodash' +const version = 44 + /** * Remove unused 'mkrMigrationReminderTimestamp' state from the `AppStateController` */ export default { version, - migrate: async function (originalVersionedData) { + async migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version const state = versionedData.data diff --git a/app/scripts/migrations/045.js b/app/scripts/migrations/045.js index 9ff7ded55..d8024a0f9 100644 --- a/app/scripts/migrations/045.js +++ b/app/scripts/migrations/045.js @@ -1,12 +1,13 @@ -const version = 45 import { cloneDeep } from 'lodash' +const version = 45 + /** * Replaces {@code PreferencesController.ipfsGateway} with 'dweb.link' if set */ export default { version, - migrate: async function (originalVersionedData) { + async migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version const state = versionedData.data diff --git a/app/scripts/migrations/046.js b/app/scripts/migrations/046.js index 4f7d36db1..6b1ebdae0 100644 --- a/app/scripts/migrations/046.js +++ b/app/scripts/migrations/046.js @@ -1,12 +1,13 @@ -const version = 46 import { cloneDeep } from 'lodash' +const version = 46 + /** * Delete {@code ABTestController} state */ export default { version, - migrate: async function (originalVersionedData) { + async migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version const state = versionedData.data diff --git a/app/scripts/migrations/047.js b/app/scripts/migrations/047.js index 255971ec3..371bf2135 100644 --- a/app/scripts/migrations/047.js +++ b/app/scripts/migrations/047.js @@ -1,12 +1,13 @@ -const version = 47 import { cloneDeep } from 'lodash' +const version = 47 + /** * Stringify the `metamaskNetworkId` property of all transactions */ export default { version, - migrate: async function (originalVersionedData) { + async migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version const state = versionedData.data diff --git a/app/scripts/migrations/fail-tx.js b/app/scripts/migrations/fail-tx.js index e5a349033..e6236ec4e 100644 --- a/app/scripts/migrations/fail-tx.js +++ b/app/scripts/migrations/fail-tx.js @@ -9,7 +9,7 @@ export default function failTxsThat (version, reason, condition) { 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) @@ -20,7 +20,7 @@ function transformState (state, condition, reason) { const newState = state const { TransactionController } = newState if (TransactionController && TransactionController.transactions) { - const transactions = TransactionController.transactions + const { transactions } = TransactionController newState.TransactionController.transactions = transactions.map((txMeta) => { if (!condition(txMeta)) { diff --git a/app/scripts/migrations/template.js b/app/scripts/migrations/template.js index c9e3b795b..6427d49f4 100644 --- a/app/scripts/migrations/template.js +++ b/app/scripts/migrations/template.js @@ -1,6 +1,4 @@ // next version number -const version = 0 - /* description of migration and what it does @@ -9,10 +7,12 @@ description of migration and what it does import { cloneDeep } from 'lodash' +const version = 0 + export default { version, - migrate: async function (originalVersionedData) { + async migrate (originalVersionedData) { const versionedData = cloneDeep(originalVersionedData) versionedData.meta.version = version const state = versionedData.data diff --git a/app/scripts/phishing-detect.js b/app/scripts/phishing-detect.js index f0ab55d00..6311b7004 100644 --- a/app/scripts/phishing-detect.js +++ b/app/scripts/phishing-detect.js @@ -1,9 +1,9 @@ import querystring from 'querystring' -import dnode from 'dnode' import { EventEmitter } from 'events' +import dnode from 'dnode' import PortStream from 'extension-port-stream' import extension from 'extensionizer' -import { setupMultiplex } from './lib/stream-utils.js' +import { setupMultiplex } from './lib/stream-utils' import { getEnvironmentType } from './lib/util' import ExtensionPlatform from './platforms/extension' diff --git a/app/scripts/platforms/extension.js b/app/scripts/platforms/extension.js index 11340c8cc..c891ae97c 100644 --- a/app/scripts/platforms/extension.js +++ b/app/scripts/platforms/extension.js @@ -105,6 +105,7 @@ export default class ExtensionPlatform { }) } catch (e) { cb(e) + // eslint-disable-next-line no-useless-return return } } @@ -189,7 +190,7 @@ export default class ExtensionPlatform { this._subscribeToNotificationClicked() - const url = explorerLink(txMeta.hash, parseInt(txMeta.metamaskNetworkId)) + const url = explorerLink(txMeta.hash, txMeta.metamaskNetworkId) const nonce = parseInt(txMeta.txParams.nonce, 16) const title = 'Confirmed transaction' @@ -210,10 +211,11 @@ export default class ExtensionPlatform { url, { 'type': 'basic', - 'title': title, + title, 'iconUrl': extension.extension.getURL('../../images/icon-64.png'), - 'message': message, - }) + message, + }, + ) } _subscribeToNotificationClicked () { diff --git a/app/scripts/ui.js b/app/scripts/ui.js index 3a76a5f4e..a77c0d6a3 100644 --- a/app/scripts/ui.js +++ b/app/scripts/ui.js @@ -6,26 +6,25 @@ import './lib/freezeGlobals' import 'abortcontroller-polyfill/dist/polyfill-patch-fetch' import '@formatjs/intl-relativetimeformat/polyfill' +import { EventEmitter } from 'events' import PortStream from 'extension-port-stream' -import { getEnvironmentType } from './lib/util' +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 { setupMultiplex } from './lib/stream-utils' +import setupSentry from './lib/setupSentry' +import ExtensionPlatform from './platforms/extension' import { ENVIRONMENT_TYPE_FULLSCREEN, ENVIRONMENT_TYPE_POPUP, } from './lib/enums' - -import extension from 'extensionizer' -import ExtensionPlatform from './platforms/extension' - -import setupSentry from './lib/setupSentry' -import { EventEmitter } from 'events' -import Dnode from 'dnode' -import Eth from 'ethjs' -import EthQuery from 'eth-query' -import launchMetaMaskUi from '../../ui' -import StreamProvider from 'web3-stream-provider' -import { setupMultiplex } from './lib/stream-utils.js' -import log from 'loglevel' +import { getEnvironmentType } from './lib/util' start().catch(log.error) @@ -62,7 +61,8 @@ async function start () { const container = document.getElementById('app-content') initializeUi(tab, container, connectionStream, (err, store) => { if (err) { - return displayCriticalError(container, err) + displayCriticalError(container, err) + return } const state = store.getState() @@ -102,7 +102,8 @@ async function queryCurrentActiveTab (windowType) { function initializeUi (activeTab, container, connectionStream, cb) { connectToAccountManager(connectionStream, (err, backgroundConnection) => { if (err) { - return cb(err) + cb(err) + return } launchMetaMaskUi({ @@ -149,7 +150,7 @@ function setupWeb3Connection (connectionStream) { function setupControllerConnection (connectionStream, cb) { const eventEmitter = new EventEmitter() const backgroundDnode = Dnode({ - sendUpdate: function (state) { + sendUpdate (state) { eventEmitter.emit('update', state) }, }) diff --git a/development/build/display.js b/development/build/display.js index 90ca4e7ba..e5556dd09 100644 --- a/development/build/display.js +++ b/development/build/display.js @@ -123,9 +123,8 @@ function getSymbolNormal (value) { return SYMBOLS.ThreeQuarters } else if (rounded === 7 / 8) { return SYMBOLS.SevenEighths - } else { - return SYMBOLS.Full } + return SYMBOLS.Full } // get partial block char for value (right-adjusted) @@ -144,7 +143,6 @@ function getSymbolNormalRight (value) { return SYMBOLS.RightEighth } else if (rounded === 1) { return SYMBOLS.Space - } else { - 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 0dbce1255..92af2e338 100644 --- a/development/build/etc.js +++ b/development/build/etc.js @@ -1,7 +1,7 @@ +const { promises: fs } = require('fs') const gulp = require('gulp') const gulpZip = require('gulp-zip') const del = require('del') -const { promises: fs } = require('fs') const pify = require('pify') const pump = pify(require('pump')) const baseManifest = require('../../app/manifest/_base.json') @@ -9,7 +9,6 @@ const { createTask, composeParallel } = require('./task') module.exports = createEtcTasks - function createEtcTasks ({ browserPlatforms, livereload }) { const clean = createTask('clean', async function clean () { diff --git a/development/build/index.js b/development/build/index.js index a665410b2..0a9f519f8 100755 --- a/development/build/index.js +++ b/development/build/index.js @@ -31,7 +31,8 @@ function defineAllTasks () { const { clean, reload, zip } = createEtcTasks({ livereload, browserPlatforms }) // build for development (livereload) - createTask('dev', + createTask( + 'dev', composeSeries( clean, styleTasks.dev, @@ -45,7 +46,8 @@ function defineAllTasks () { ) // build for test development (livereload) - createTask('testDev', + createTask( + 'testDev', composeSeries( clean, styleTasks.dev, @@ -59,7 +61,8 @@ function defineAllTasks () { ) // build for prod release - createTask('prod', + createTask( + 'prod', composeSeries( clean, styleTasks.prod, @@ -73,7 +76,8 @@ function defineAllTasks () { ) // build for CI testing - createTask('test', + createTask( + 'test', composeSeries( clean, styleTasks.prod, diff --git a/development/build/manifest.js b/development/build/manifest.js index 71d335be0..1ea9e5ad5 100644 --- a/development/build/manifest.js +++ b/development/build/manifest.js @@ -7,7 +7,6 @@ const { createTask, composeSeries } = require('./task') module.exports = createManifestTasks - const scriptsToExcludeFromBackgroundDevBuild = { 'bg-libs.js': true, } diff --git a/development/build/scripts.js b/development/build/scripts.js index 6f206ee57..c6e3e4173 100644 --- a/development/build/scripts.js +++ b/development/build/scripts.js @@ -17,15 +17,14 @@ const { makeStringTransform } = require('browserify-transform-tools') const conf = require('rc')('metamask', {}) -const { createTask, composeParallel, composeSeries, runInChildProcess } = require('./task') const packageJSON = require('../../package.json') +const { createTask, composeParallel, composeSeries, runInChildProcess } = require('./task') module.exports = createScriptTasks - const dependencies = Object.keys((packageJSON && packageJSON.dependencies) || {}) const materialUIDependencies = ['@material-ui/core'] -const reactDepenendencies = dependencies.filter((dep) => dep.match(/react/)) +const reactDepenendencies = dependencies.filter((dep) => dep.match(/react/u)) const d3Dependencies = ['c3', 'd3'] const externalDependenciesMap = { @@ -62,8 +61,7 @@ function createScriptTasks ({ browserPlatforms, livereload }) { core.prod, ) - const dev = core.dev - const testDev = core.testDev + const { dev, testDev } = core const test = composeParallel( deps.background, @@ -73,7 +71,6 @@ function createScriptTasks ({ browserPlatforms, livereload }) { return { prod, dev, testDev, test } - function createTasksForBuildJsDeps ({ key, filename }) { return createTask(`scripts:deps:${key}`, bundleTask({ label: filename, @@ -84,7 +81,6 @@ function createScriptTasks ({ browserPlatforms, livereload }) { })) } - function createTasksForBuildJsExtension ({ taskPrefix, devMode, testing }) { const standardBundles = [ 'background', @@ -94,14 +90,12 @@ function createScriptTasks ({ browserPlatforms, livereload }) { const standardSubtasks = standardBundles.map((filename) => { return createTask(`${taskPrefix}:${filename}`, - createBundleTaskForBuildJsExtensionNormal({ filename, devMode, testing }), - ) + createBundleTaskForBuildJsExtensionNormal({ filename, devMode, testing })) }) // inpage must be built before contentscript // because inpage bundle result is included inside contentscript const contentscriptSubtask = createTask(`${taskPrefix}:contentscript`, - createTaskForBuildJsExtensionContentscript({ devMode, testing }), - ) + createTaskForBuildJsExtensionContentscript({ devMode, testing })) // task for initiating livereload const initiateLiveReload = async () => { @@ -160,7 +154,6 @@ function createScriptTasks ({ browserPlatforms, livereload }) { ) } - function bundleTask (opts) { let bundler @@ -204,7 +197,7 @@ function createScriptTasks ({ browserPlatforms, livereload }) { buildStream = buildStream .pipe(terser({ mangle: { - reserved: [ 'MetamaskInpageProvider' ], + reserved: ['MetamaskInpageProvider'], }, sourceMap: { content: true, @@ -288,9 +281,9 @@ function createScriptTasks ({ browserPlatforms, livereload }) { if (!opts.buildLib) { if (opts.devMode && opts.filename === 'ui.js') { - browserifyOpts['entries'] = ['./development/require-react-devtools.js', opts.filepath] + browserifyOpts.entries = ['./development/require-react-devtools.js', opts.filepath] } else { - browserifyOpts['entries'] = [opts.filepath] + browserifyOpts.entries = [opts.filepath] } } @@ -349,10 +342,8 @@ function createScriptTasks ({ browserPlatforms, livereload }) { return bundler } - } - function beep () { process.stdout.write('\x07') } @@ -365,13 +356,12 @@ function getEnvironment ({ devMode, test }) { return 'testing' } else if (process.env.CIRCLE_BRANCH === 'master') { return 'production' - } else if (/^Version-v(\d+)[.](\d+)[.](\d+)/.test(process.env.CIRCLE_BRANCH)) { + } else if ((/^Version-v(\d+)[.](\d+)[.](\d+)/u).test(process.env.CIRCLE_BRANCH)) { return 'release-candidate' } else if (process.env.CIRCLE_BRANCH === 'develop') { return 'staging' } else if (process.env.CIRCLE_PULL_REQUEST) { return 'pull-request' - } else { - return 'other' } + return 'other' } diff --git a/development/build/static.js b/development/build/static.js index 62dbeaa62..3d4c74394 100644 --- a/development/build/static.js +++ b/development/build/static.js @@ -1,5 +1,5 @@ -const fs = require('fs-extra') const path = require('path') +const fs = require('fs-extra') const watch = require('gulp-watch') const glob = require('fast-glob') @@ -9,7 +9,6 @@ const { createTask, composeSeries } = require('./task') module.exports = createStaticAssetTasks - const copyTargets = [ { src: `./app/_locales/`, diff --git a/development/build/styles.js b/development/build/styles.js index 4667100c8..d6f3a7855 100644 --- a/development/build/styles.js +++ b/development/build/styles.js @@ -11,11 +11,9 @@ const rename = require('gulp-rename') const pump = pify(require('pump')) const { createTask } = require('./task') - // scss compilation and autoprefixing tasks module.exports = createStyleTasks - function createStyleTasks ({ livereload }) { const prod = createTask('styles:prod', createScssBuildTask({ @@ -44,19 +42,18 @@ function createStyleTasks ({ livereload }) { return { prod, dev, lint } - function createScssBuildTask ({ src, dest, devMode, pattern }) { return async function () { if (devMode) { watch(pattern, async (event) => { - await buildScss(devMode) + await buildScss() livereload.changed(event.path) }) } await buildScss(devMode) } - async function buildScss (devMode) { + async function buildScss () { await pump(...[ // pre-process gulp.src(src), @@ -75,5 +72,4 @@ function createStyleTasks ({ livereload }) { } } - } diff --git a/development/build/task.js b/development/build/task.js index 4a0a9d437..879ab1c97 100644 --- a/development/build/task.js +++ b/development/build/task.js @@ -8,7 +8,6 @@ module.exports = { detectAndRunEntryTask, tasks, taskEvents, createTask, runTask const { setupTaskDisplay } = require('./display') - function detectAndRunEntryTask () { // get requested task name and execute const taskName = process.argv[2] diff --git a/development/metamaskbot-build-announce.js b/development/metamaskbot-build-announce.js index 788929fb3..51d9617a2 100755 --- a/development/metamaskbot-build-announce.js +++ b/development/metamaskbot-build-announce.js @@ -12,12 +12,11 @@ function capitalizeFirstLetter (string) { async function start () { - const GITHUB_COMMENT_TOKEN = process.env.GITHUB_COMMENT_TOKEN - const CIRCLE_PULL_REQUEST = process.env.CIRCLE_PULL_REQUEST + const { GITHUB_COMMENT_TOKEN, CIRCLE_PULL_REQUEST } = process.env console.log('CIRCLE_PULL_REQUEST', CIRCLE_PULL_REQUEST) - const CIRCLE_SHA1 = process.env.CIRCLE_SHA1 + const { CIRCLE_SHA1 } = process.env console.log('CIRCLE_SHA1', CIRCLE_SHA1) - const CIRCLE_BUILD_NUM = process.env.CIRCLE_BUILD_NUM + const { CIRCLE_BUILD_NUM } = process.env console.log('CIRCLE_BUILD_NUM', CIRCLE_BUILD_NUM) if (!CIRCLE_PULL_REQUEST) { @@ -58,7 +57,7 @@ async function start () { `dep viz: ${depVizLink}`, `all artifacts`, ] - const hiddenContent = `` + const hiddenContent = `` const exposedContent = `Builds ready [${SHORT_SHA1}]` const artifactsBody = `
${exposedContent}${hiddenContent}
` @@ -81,10 +80,7 @@ async function start () { const summaryPlatform = 'chrome' const summaryPage = 'home' let commentBody - if (!benchmarkResults[summaryPlatform]) { - console.log(`No results for ${summaryPlatform} found; skipping benchmark`) - commentBody = artifactsBody - } else { + if (benchmarkResults[summaryPlatform]) { try { const summaryPageLoad = Math.round(parseFloat(benchmarkResults[summaryPlatform][summaryPage].average.load)) const summaryPageLoadMarginOfError = Math.round(parseFloat(benchmarkResults[summaryPlatform][summaryPage].marginOfError.load)) @@ -147,6 +143,9 @@ async function start () { console.error(`Error constructing benchmark results: '${error}'`) commentBody = artifactsBody } + } else { + console.log(`No results for ${summaryPlatform} found; skipping benchmark`) + commentBody = artifactsBody } const JSON_PAYLOAD = JSON.stringify({ body: commentBody }) diff --git a/development/mock-3box.js b/development/mock-3box.js index 89cf20ab1..e4260c610 100644 --- a/development/mock-3box.js +++ b/development/mock-3box.js @@ -3,7 +3,7 @@ function delay (time) { } async function loadFromMock3Box (key) { - const res = await window.fetch('http://localhost:8889?key=' + key) + const res = await window.fetch(`http://localhost:8889?key=${key}`) const text = await res.text() return text.length ? JSON.parse(text) : null } @@ -50,7 +50,7 @@ class Mock3Box { }, } }, - logout: () => {}, + logout: () => undefined, }) } diff --git a/development/sentry-publish.js b/development/sentry-publish.js index 81034374e..80c373608 100644 --- a/development/sentry-publish.js +++ b/development/sentry-publish.js @@ -1,6 +1,8 @@ #!/usr/bin/env node +const childProcess = require('child_process') const pify = require('pify') -const exec = pify(require('child_process').exec, { multiArgs: true }) + +const exec = pify(childProcess.exec, { multiArgs: true }) const VERSION = require('../dist/chrome/manifest.json').version // eslint-disable-line import/no-unresolved start().catch(console.error) @@ -25,12 +27,14 @@ async function start () { // check if version has artifacts or not const versionHasArtifacts = versionAlreadyExists && await checkIfVersionHasArtifacts() - if (!versionHasArtifacts) { - // upload sentry source and sourcemaps - await exec(`./development/sentry-upload-artifacts.sh --release ${VERSION}`) - } else { + if (versionHasArtifacts) { console.log(`Version "${VERSION}" already has artifacts on Sentry, skipping sourcemap upload`) + return } + + // upload sentry source and sourcemaps + await exec(`./development/sentry-upload-artifacts.sh --release ${VERSION}`) + } async function checkIfAuthWorks () { diff --git a/development/sourcemap-validator.js b/development/sourcemap-validator.js index 7be473110..cb5f6f6c8 100644 --- a/development/sourcemap-validator.js +++ b/development/sourcemap-validator.js @@ -1,6 +1,6 @@ const fs = require('fs') -const { SourceMapConsumer } = require('source-map') const path = require('path') +const { SourceMapConsumer } = require('source-map') const pify = require('pify') const fsAsync = pify(fs) @@ -18,7 +18,6 @@ start().catch((error) => { process.exit(1) }) - async function start () { const targetFiles = [ `background.js`, @@ -49,7 +48,9 @@ async function validateSourcemapForFile ({ buildName }) { try { const filePath = path.join(__dirname, `/../dist/${platform}/`, `${buildName}`) rawBuild = await fsAsync.readFile(filePath, 'utf8') - } catch (err) {} + } catch (_) { + // empty + } if (!rawBuild) { throw new Error(`SourcemapValidator - failed to load source file for "${buildName}"`) } @@ -58,12 +59,16 @@ async function validateSourcemapForFile ({ buildName }) { try { const filePath = path.join(__dirname, `/../dist/sourcemaps/`, `${buildName}.map`) rawSourceMap = await fsAsync.readFile(filePath, 'utf8') - } catch (err) {} + } catch (_) { + // empty + } // attempt to load in dev mode try { const filePath = path.join(__dirname, `/../dist/${platform}/`, `${buildName}.map`) rawSourceMap = await fsAsync.readFile(filePath, 'utf8') - } catch (err) {} + } catch (_) { + // empty + } if (!rawSourceMap) { throw new Error(`SourcemapValidator - failed to load sourcemaps for "${buildName}"`) } @@ -85,7 +90,7 @@ async function validateSourcemapForFile ({ buildName }) { const matchesPerLine = buildLines.map((line) => indicesOf(targetString, line)) matchesPerLine.forEach((matchIndices, lineIndex) => { matchIndices.forEach((matchColumn) => { - sampleCount++ + sampleCount += 1 const position = { line: lineIndex + 1, column: matchColumn } const result = consumer.originalPositionFor(position) // warn if source content is missing diff --git a/development/static-server.js b/development/static-server.js index fff4103c4..a20908878 100644 --- a/development/static-server.js +++ b/development/static-server.js @@ -61,7 +61,7 @@ const main = async () => { } while (args.length) { - if (/^(--port|-p)$/i.test(args[0])) { + if ((/^(--port|-p)$/u).test(args[0])) { if (args[1] === undefined) { throw new Error('Missing port argument') } diff --git a/development/verify-locale-strings.js b/development/verify-locale-strings.js index 990ed95f4..1d4c6e3a7 100644 --- a/development/verify-locale-strings.js +++ b/development/verify-locale-strings.js @@ -46,19 +46,19 @@ for (const arg of process.argv.slice(2)) { } } -main(specifiedLocale, fix) +main() .catch((error) => { log.error(error) process.exit(1) }) -async function main (specifiedLocale, fix) { +async function main () { if (specifiedLocale) { log.info(`Verifying selected locale "${specifiedLocale}":\n`) const locale = localeIndex.find((localeMeta) => localeMeta.code === specifiedLocale) const failed = locale.code === 'en' ? - await verifyEnglishLocale(fix) : - await verifyLocale(locale, fix) + await verifyEnglishLocale() : + await verifyLocale(locale) if (failed) { process.exit(1) } @@ -97,13 +97,14 @@ async function getLocale (code) { log.error(`Error opening your locale ("${code}") file: `, e) } process.exit(1) + return undefined } } async function writeLocale (code, locale) { try { const localeFilePath = getLocalePath(code) - return writeFile(localeFilePath, JSON.stringify(locale, null, 2) + '\n', 'utf8') + return writeFile(localeFilePath, `${JSON.stringify(locale, null, 2)}\n`, 'utf8') } catch (e) { if (e.code === 'ENOENT') { log.error('Locale file not found') @@ -111,10 +112,11 @@ async function writeLocale (code, locale) { log.error(`Error writing your locale ("${code}") file: `, e) } process.exit(1) + return undefined } } -async function verifyLocale (code, fix = false) { +async function verifyLocale (code) { const englishLocale = await getLocale('en') const targetLocale = await getLocale(code) @@ -148,7 +150,7 @@ async function verifyLocale (code, fix = false) { if (extraItems.length > 0) { if (fix) { - const newLocale = Object.assign({}, targetLocale) + const newLocale = { ...targetLocale } for (const item of extraItems) { delete newLocale[item] } @@ -156,20 +158,22 @@ async function verifyLocale (code, fix = false) { } return true } + + return false } -async function verifyEnglishLocale (fix = false) { +async function verifyEnglishLocale () { const englishLocale = await getLocale('en') const javascriptFiles = await findJavascriptFiles(path.resolve(__dirname, '..', 'ui')) // match "t(`...`)" because constructing message keys from template strings // prevents this script from finding the messages, and then inappropriately // deletes them - const templateStringRegex = /\bt\(`.*`\)/g + const templateStringRegex = /\bt\(`.*`\)/ug const templateUsage = [] // match the keys from the locale file - const keyRegex = /'(\w+)'|"(\w+)"/g + const keyRegex = /'(\w+)'|"(\w+)"/ug const usedMessages = new Set() for await (const fileContents of getFileContents(javascriptFiles)) { for (const match of matchAll.call(fileContents, keyRegex)) { @@ -211,7 +215,7 @@ async function verifyEnglishLocale (fix = false) { } if (unusedMessages.length > 0 && fix) { - const newLocale = Object.assign({}, englishLocale) + const newLocale = { ...englishLocale } for (const key of unusedMessages) { delete newLocale[key] } @@ -240,7 +244,6 @@ async function * getFileContents (filenames) { } } - function compareLocalesForMissingItems ({ base, subject }) { return Object.keys(base).filter((key) => !subject[key]) } diff --git a/package.json b/package.json index 18dfb5bd4..fc470803d 100644 --- a/package.json +++ b/package.json @@ -179,7 +179,7 @@ "@babel/preset-env": "^7.5.5", "@babel/preset-react": "^7.0.0", "@babel/register": "^7.5.5", - "@metamask/eslint-config": "^1.1.0", + "@metamask/eslint-config": "^3.1.0", "@metamask/forwarder": "^1.1.0", "@metamask/test-dapp": "^3.1.0", "@sentry/cli": "^1.49.0", @@ -202,7 +202,7 @@ "chalk": "^3.0.0", "chromedriver": "^79.0.0", "concurrently": "^5.2.0", - "copy-webpack-plugin": "^5.1.1", + "copy-webpack-plugin": "^6.0.3", "coveralls": "^3.0.0", "css-loader": "^2.1.1", "del": "^3.0.0", diff --git a/test/e2e/.eslintrc.js b/test/e2e/.eslintrc.js deleted file mode 100644 index d84a4b2fb..000000000 --- a/test/e2e/.eslintrc.js +++ /dev/null @@ -1,5 +0,0 @@ -module.exports = { - rules: { - 'mocha/no-hooks-for-single-case': 'off', - }, -} diff --git a/test/e2e/address-book.spec.js b/test/e2e/address-book.spec.js index f9fc7d5be..85cef65de 100644 --- a/test/e2e/address-book.spec.js +++ b/test/e2e/address-book.spec.js @@ -1,6 +1,7 @@ const assert = require('assert') const { By, until } = require('selenium-webdriver') +const enLocaleMessages = require('../../app/_locales/en/messages.json') const { tinyDelayMs, regularDelayMs, @@ -8,7 +9,6 @@ const { } = require('./helpers') const { buildWebDriver } = require('./webdriver') const Ganache = require('./ganache') -const enLocaleMessages = require('../../app/_locales/en/messages.json') const ganacheServer = new Ganache() @@ -152,7 +152,7 @@ describe('MetaMask', function () { 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/)) + await driver.wait(until.elementTextMatches(balance, /25\s*ETH/u)) await driver.delay(regularDelayMs) }) }) @@ -202,7 +202,7 @@ describe('MetaMask', function () { }, 10000) const txValues = await driver.findElement(By.css('.transaction-list-item__primary-currency')) - await driver.wait(until.elementTextMatches(txValues, /-1\s*ETH/), 10000) + await driver.wait(until.elementTextMatches(txValues, /-1\s*ETH/u), 10000) }) }) @@ -239,7 +239,7 @@ describe('MetaMask', function () { }, 10000) const txValues = await driver.findElement(By.css('.transaction-list-item__primary-currency')) - await driver.wait(until.elementTextMatches(txValues, /-2\s*ETH/), 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 52008bb40..d8b79a9eb 100644 --- a/test/e2e/benchmark.js +++ b/test/e2e/benchmark.js @@ -62,10 +62,10 @@ async function profilePageLoad (pages, numSamples) { } const result = { - firstPaint: runResults.map((result) => result.paint['first-paint']), - domContentLoaded: runResults.map((result) => result.navigation[0] && result.navigation[0].domContentLoaded), - load: runResults.map((result) => result.navigation[0] && result.navigation[0].load), - domInteractive: runResults.map((result) => result.navigation[0] && result.navigation[0].domInteractive), + firstPaint: runResults.map((metrics) => metrics.paint['first-paint']), + domContentLoaded: runResults.map((metrics) => metrics.navigation[0] && metrics.navigation[0].domContentLoaded), + load: runResults.map((metrics) => metrics.navigation[0] && metrics.navigation[0].load), + domInteractive: runResults.map((metrics) => metrics.navigation[0] && metrics.navigation[0].domInteractive), } results[pageName] = { @@ -92,17 +92,18 @@ async function isWritable (directory) { } async function getFirstParentDirectoryThatExists (directory) { - while (true) { + let nextDirectory = directory + for (;;) { try { - await fs.access(directory, fsConstants.F_OK) - return directory + await fs.access(nextDirectory, fsConstants.F_OK) + return nextDirectory } catch (error) { if (error.code !== 'ENOENT') { throw error - } else if (directory === path.dirname(directory)) { + } else if (nextDirectory === path.dirname(nextDirectory)) { throw new Error('Failed to find parent directory that exists') } - directory = path.dirname(directory) + nextDirectory = path.dirname(nextDirectory) } } } @@ -117,7 +118,7 @@ async function main () { let existingParentDirectory while (args.length) { - if (/^(--pages|-p)$/i.test(args[0])) { + if ((/^(--pages|-p)$/u).test(args[0])) { if (args[1] === undefined) { throw new Error('Missing pages argument') } @@ -128,7 +129,7 @@ async function main () { } } args.splice(0, 2) - } else if (/^(--samples|-s)$/i.test(args[0])) { + } else if ((/^(--samples|-s)$/u).test(args[0])) { if (args[1] === undefined) { throw new Error('Missing number of samples') } @@ -137,7 +138,7 @@ async function main () { throw new Error(`Invalid 'samples' argument given: '${args[1]}'`) } args.splice(0, 2) - } else if (/^(--out|-o)$/i.test(args[0])) { + } else if ((/^(--out|-o)$/u).test(args[0])) { if (args[1] === undefined) { throw new Error('Missing output filename') } diff --git a/test/e2e/ethereum-on.spec.js b/test/e2e/ethereum-on.spec.js index e7412ac68..5dd15d5fd 100644 --- a/test/e2e/ethereum-on.spec.js +++ b/test/e2e/ethereum-on.spec.js @@ -2,13 +2,13 @@ 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 enLocaleMessages = require('../../app/_locales/en/messages.json') const ganacheServer = new Ganache() @@ -89,11 +89,11 @@ describe('MetaMask', function () { }) it('gets the current accounts address', async function () { - const addressInput = await driver.findElement(By.css('.qr-ellip-address')) + const addressInput = await driver.findElement(By.css('.readonly-input__input')) 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) diff --git a/test/e2e/fixture-server.js b/test/e2e/fixture-server.js index 608955f76..b96ba8e9a 100644 --- a/test/e2e/fixture-server.js +++ b/test/e2e/fixture-server.js @@ -1,6 +1,6 @@ const { promises: fs } = require('fs') -const Koa = require('koa') const path = require('path') +const Koa = require('koa') const CURRENT_STATE_KEY = '__CURRENT__' const DEFAULT_STATE_KEY = '__DEFAULT__' @@ -44,7 +44,7 @@ class FixtureServer { return } - return new Promise((resolve, reject) => { + await new Promise((resolve, reject) => { this._server.close() this._server.once('error', reject) this._server.once('close', resolve) diff --git a/test/e2e/from-import-ui.spec.js b/test/e2e/from-import-ui.spec.js index 7a112c722..d9b93bcad 100644 --- a/test/e2e/from-import-ui.spec.js +++ b/test/e2e/from-import-ui.spec.js @@ -2,13 +2,13 @@ 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 enLocaleMessages = require('../../app/_locales/en/messages.json') const ganacheServer = new Ganache() @@ -99,24 +99,24 @@ describe('Using MetaMask with an existing account', 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-wrapper')) + await driver.findVisibleElement(By.css('.qr-code__wrapper')) await driver.delay(regularDelayMs) - const [address] = await driver.findElements(By.css('input.qr-ellip-address')) + const [address] = await driver.findElements(By.css('.readonly-input__input')) assert.equal(await address.getAttribute('value'), testAddress) - await driver.clickElement(By.css('.account-modal-close')) + 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-wrapper')) + 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.clickElement(By.css('.account-modal__close')) await driver.wait(until.stalenessOf(detailModal)) await driver.delay(regularDelayMs) }) @@ -223,7 +223,7 @@ describe('Using MetaMask with an existing account', function () { const txValues = await driver.findElements(By.css('.transaction-list-item__primary-currency')) assert.equal(txValues.length, 1) - assert.ok(/-1\s*ETH/.test(await txValues[0].getText())) + assert.ok((/-1\s*ETH/u).test(await txValues[0].getText())) }) }) diff --git a/test/e2e/ganache.js b/test/e2e/ganache.js index cd15990c8..edce5b15e 100644 --- a/test/e2e/ganache.js +++ b/test/e2e/ganache.js @@ -1,5 +1,5 @@ -const ganache = require('ganache-core') const { promisify } = require('util') +const ganache = require('ganache-core') const defaultOptions = { blockTime: 2, @@ -10,10 +10,9 @@ const defaultOptions = { } class Ganache { - async start (options) { - options = Object.assign({}, defaultOptions, options) - - const port = options.port + async start (opts) { + const options = { ...defaultOptions, ...opts } + const { port } = options this._server = ganache.server(options) const listen = promisify(this._server.listen).bind(this._server) diff --git a/test/e2e/helpers.js b/test/e2e/helpers.js index 1611e66da..b06efb3ec 100644 --- a/test/e2e/helpers.js +++ b/test/e2e/helpers.js @@ -1,8 +1,8 @@ const path = require('path') +const createStaticServer = require('../../development/create-static-server') const Ganache = require('./ganache') const FixtureServer = require('./fixture-server') const { buildWebDriver } = require('./webdriver') -const createStaticServer = require('../../development/create-static-server') const tinyDelayMs = 200 const regularDelayMs = tinyDelayMs * 2 diff --git a/test/e2e/incremental-security.spec.js b/test/e2e/incremental-security.spec.js index 82e3fc0e0..6b76bae12 100644 --- a/test/e2e/incremental-security.spec.js +++ b/test/e2e/incremental-security.spec.js @@ -2,6 +2,7 @@ const assert = require('assert') const webdriver = require('selenium-webdriver') const { By, until } = webdriver +const enLocaleMessages = require('../../app/_locales/en/messages.json') const { tinyDelayMs, regularDelayMs, @@ -9,7 +10,6 @@ const { } = require('./helpers') const { buildWebDriver } = require('./webdriver') const Ganache = require('./ganache') -const enLocaleMessages = require('../../app/_locales/en/messages.json') const ganacheServer = new Ganache() @@ -95,12 +95,12 @@ describe('MetaMask', function () { }) it('gets the current accounts address', async function () { - const addressInput = await driver.findElement(By.css('.qr-ellip-address')) + const addressInput = await driver.findElement(By.css('.readonly-input__input')) 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) @@ -127,7 +127,7 @@ describe('MetaMask', function () { await driver.clickElement(By.css('#send')) const txStatus = await driver.findElement(By.css('#success')) - await driver.wait(until.elementTextMatches(txStatus, /Success/), 15000) + await driver.wait(until.elementTextMatches(txStatus, /Success/u), 15000) }) it('switches back to MetaMask', async function () { @@ -136,7 +136,7 @@ describe('MetaMask', function () { 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/), 15000) + await driver.wait(until.elementTextMatches(balances[0], /1/u), 15000) const balance = await balances[0].getText() assert.equal(balance, '1') @@ -193,7 +193,7 @@ describe('MetaMask', function () { 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/), 15000) + await driver.wait(until.elementTextMatches(balances[0], /1/u), 15000) const balance = await balances[0].getText() assert.equal(balance, '1') diff --git a/test/e2e/metamask-responsive-ui.spec.js b/test/e2e/metamask-responsive-ui.spec.js index 0b7e8b4d4..b776299d4 100644 --- a/test/e2e/metamask-responsive-ui.spec.js +++ b/test/e2e/metamask-responsive-ui.spec.js @@ -2,6 +2,7 @@ const assert = require('assert') const webdriver = require('selenium-webdriver') const { By, until } = webdriver +const enLocaleMessages = require('../../app/_locales/en/messages.json') const { tinyDelayMs, regularDelayMs, @@ -9,7 +10,6 @@ const { } = require('./helpers') const { buildWebDriver } = require('./webdriver') const Ganache = require('./ganache') -const enLocaleMessages = require('../../app/_locales/en/messages.json') const ganacheServer = new Ganache() @@ -167,7 +167,7 @@ describe('MetaMask', function () { 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/)) + await driver.wait(until.elementTextMatches(balance, /100\s*ETH/u)) await driver.delay(regularDelayMs) }) }) @@ -218,7 +218,7 @@ describe('MetaMask', function () { }, 10000) const txValues = await driver.findElement(By.css('.transaction-list-item__primary-currency')) - await driver.wait(until.elementTextMatches(txValues, /-1\s*ETH/), 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 15d0198cd..f8c21d131 100644 --- a/test/e2e/metamask-ui.spec.js +++ b/test/e2e/metamask-ui.spec.js @@ -2,6 +2,7 @@ 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, @@ -9,7 +10,6 @@ const { } = require('./helpers') const { buildWebDriver } = require('./webdriver') const Ganache = require('./ganache') -const enLocaleMessages = require('../../app/_locales/en/messages.json') const ganacheServer = new Ganache() @@ -121,11 +121,11 @@ describe('MetaMask', 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-wrapper')) + 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')) + await driver.clickElement(By.css('.account-modal__close')) await driver.wait(until.stalenessOf(accountModal)) await driver.delay(regularDelayMs) @@ -208,7 +208,7 @@ describe('MetaMask', function () { 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/)) + await driver.wait(until.elementTextMatches(balance, /100\s*ETH/u)) await driver.delay(regularDelayMs) }) }) @@ -273,7 +273,7 @@ describe('MetaMask', function () { }, 10000) const txValues = await driver.findElement(By.css('.transaction-list-item__primary-currency')) - await driver.wait(until.elementTextMatches(txValues, /-1\s*ETH/), 10000) + await driver.wait(until.elementTextMatches(txValues, /-1\s*ETH/u), 10000) }) }) @@ -312,7 +312,7 @@ describe('MetaMask', function () { }, 10000) const txValues = await driver.findElement(By.css('.transaction-list-item__primary-currency')) - await driver.wait(until.elementTextMatches(txValues, /-1\s*ETH/), 10000) + await driver.wait(until.elementTextMatches(txValues, /-1\s*ETH/u), 10000) }) }) @@ -360,7 +360,7 @@ describe('MetaMask', function () { }, 10000) const txValues = await driver.findElement(By.css('.transaction-list-item__primary-currency')) - await driver.wait(until.elementTextMatches(txValues, /-1\s*ETH/), 10000) + await driver.wait(until.elementTextMatches(txValues, /-1\s*ETH/u), 10000) }) }) @@ -463,7 +463,7 @@ describe('MetaMask', function () { }, 10000) const txValue = await driver.findClickableElement(By.css('.transaction-list-item__primary-currency')) - await driver.wait(until.elementTextMatches(txValue, /-3\s*ETH/), 10000) + await driver.wait(until.elementTextMatches(txValue, /-3\s*ETH/u), 10000) }) it('the transaction has the expected gas price', async function () { @@ -471,7 +471,7 @@ describe('MetaMask', function () { 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$/), 10000) + await driver.wait(until.elementTextMatches(txGasPrice, /^10$/u), 10000) await popoverCloseButton.click() }) }) @@ -654,7 +654,7 @@ describe('MetaMask', function () { }, 10000) const txAction = await driver.findElements(By.css('.list-item__heading')) - await driver.wait(until.elementTextMatches(txAction[0], /Contract\sDeployment/), 10000) + await driver.wait(until.elementTextMatches(txAction[0], /Contract\sDeployment/u), 10000) await driver.delay(regularDelayMs) }) @@ -663,20 +663,20 @@ describe('MetaMask', function () { await driver.delay(regularDelayMs) let contractStatus = await driver.findElement(By.css('#contractStatus')) - await driver.wait(until.elementTextMatches(contractStatus, /Deployed/), 15000) + await driver.wait(until.elementTextMatches(contractStatus, /Deployed/u), 15000) await driver.clickElement(By.css('#depositButton')) await driver.delay(largeDelayMs) contractStatus = await driver.findElement(By.css('#contractStatus')) - await driver.wait(until.elementTextMatches(contractStatus, /Deposit\sinitiated/), 10000) + await driver.wait(until.elementTextMatches(contractStatus, /Deposit\sinitiated/u), 10000) await driver.switchToWindow(extension) await driver.delay(largeDelayMs * 2) await driver.findElements(By.css('.transaction-list-item')) const txListValue = await driver.findClickableElement(By.css('.transaction-list-item__primary-currency')) - await driver.wait(until.elementTextMatches(txListValue, /-4\s*ETH/), 10000) + await driver.wait(until.elementTextMatches(txListValue, /-4\s*ETH/u), 10000) await txListValue.click() await driver.delay(regularDelayMs) @@ -718,7 +718,7 @@ describe('MetaMask', function () { }, 10000) const txValues = await driver.findElements(By.css('.transaction-list-item__primary-currency')) - await driver.wait(until.elementTextMatches(txValues[0], /-4\s*ETH/), 10000) + 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 () { @@ -743,7 +743,7 @@ describe('MetaMask', function () { }, 10000) const txValues = await driver.findElement(By.css('.transaction-list-item__primary-currency')) - await driver.wait(until.elementTextMatches(txValues, /-0\s*ETH/), 10000) + await driver.wait(until.elementTextMatches(txValues, /-0\s*ETH/u), 10000) await driver.closeAllWindowHandlesExcept([extension, dapp]) await driver.switchToWindow(extension) @@ -752,9 +752,9 @@ describe('MetaMask', function () { 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.wait(until.elementTextMatches(balance, /^87.*\s*ETH.*$/), 10000) + await driver.wait(until.elementTextMatches(balance, /^87.*\s*ETH.*$/u), 10000) const tokenAmount = await balance.getText() - assert.ok(/^87.*\s*ETH.*$/.test(tokenAmount)) + assert.ok((/^87.*\s*ETH.*$/u).test(tokenAmount)) await driver.delay(regularDelayMs) }) }) @@ -797,7 +797,7 @@ describe('MetaMask', function () { await driver.delay(tinyDelayMs) const tokenContractAddress = await driver.findElement(By.css('#tokenAddress')) - await driver.wait(until.elementTextMatches(tokenContractAddress, /0x/)) + await driver.wait(until.elementTextMatches(tokenContractAddress, /0x/u)) tokenAddress = await tokenContractAddress.getText() await driver.delay(regularDelayMs) @@ -830,9 +830,9 @@ describe('MetaMask', function () { 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*$/)) + await driver.wait(until.elementTextMatches(balance, /^10\s*TST\s*$/u)) const tokenAmount = await balance.getText() - assert.ok(/^10\s*TST\s*$/.test(tokenAmount)) + assert.ok((/^10\s*TST\s*$/u).test(tokenAmount)) await driver.delay(regularDelayMs) }) }) @@ -887,7 +887,7 @@ describe('MetaMask', function () { const confirmDataText = await confirmDataDiv.getText() await driver.delay(regularDelayMs) - assert(confirmDataText.match(/0xa9059cbb0000000000000000000000002f318c334780961fb129d2a6c30d0763d9a5c97/)) + assert(confirmDataText.match(/0xa9059cbb0000000000000000000000002f318c334780961fb129d2a6c30d0763d9a5c97/u)) await driver.clickElement(By.xpath(`//li[contains(text(), 'Details')]`)) await driver.delay(regularDelayMs) @@ -906,10 +906,10 @@ describe('MetaMask', function () { const txValues = await driver.findElements(By.css('.transaction-list-item__primary-currency')) assert.equal(txValues.length, 1) - await driver.wait(until.elementTextMatches(txValues[0], /-1\s*TST/), 10000) + 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/i), 10000) + await driver.wait(until.elementTextMatches(txStatuses[0], /Send\sTST/u), 10000) }) }) @@ -931,7 +931,7 @@ describe('MetaMask', function () { 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/), 10000) + await driver.wait(until.elementTextMatches(txListValue, /-1.5\s*TST/u), 10000) await txListValue.click() await driver.delay(regularDelayMs) @@ -987,12 +987,12 @@ describe('MetaMask', function () { }, 10000) const txValues = await driver.findElements(By.css('.transaction-list-item__primary-currency')) - await driver.wait(until.elementTextMatches(txValues[0], /-1.5\s*TST/)) + 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/), 10000) + 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/), 10000) + await driver.wait(until.elementTextMatches(tokenBalanceAmount[0], /7.5\s*TST/u), 10000) }) }) @@ -1019,7 +1019,7 @@ describe('MetaMask', function () { }, 10000) const [txtListHeading] = await driver.findElements(By.css('.transaction-list-item .list-item__heading')) - await driver.wait(until.elementTextMatches(txtListHeading, /Approve TST spend limit/)) + await driver.wait(until.elementTextMatches(txtListHeading, /Approve TST spend limit/u)) await driver.clickElement(By.css('.transaction-list-item')) await driver.delay(regularDelayMs) }) @@ -1034,7 +1034,7 @@ describe('MetaMask', function () { const confirmDataDiv = await driver.findElement(By.css('.confirm-approve-content__data__data-block')) const confirmDataText = await confirmDataDiv.getText() - assert(confirmDataText.match(/0x095ea7b30000000000000000000000009bc5baf874d2da8d216ae9f137804184ee5afef4/)) + assert(confirmDataText.match(/0x095ea7b30000000000000000000000009bc5baf874d2da8d216ae9f137804184ee5afef4/u)) }) it('opens the gas edit modal', async function () { @@ -1105,7 +1105,7 @@ describe('MetaMask', function () { }, 10000) const txStatuses = await driver.findElements(By.css('.list-item__heading')) - await driver.wait(until.elementTextMatches(txStatuses[0], /Approve TST spend limit/)) + await driver.wait(until.elementTextMatches(txStatuses[0], /Approve TST spend limit/u)) }) }) @@ -1130,7 +1130,7 @@ describe('MetaMask', function () { }, 10000) const [txListValue] = await driver.findElements(By.css('.transaction-list-item__primary-currency')) - await driver.wait(until.elementTextMatches(txListValue, /-1.5\s*TST/)) + await driver.wait(until.elementTextMatches(txListValue, /-1.5\s*TST/u)) await driver.clickElement(By.css('.transaction-list-item')) await driver.delay(regularDelayMs) }) @@ -1148,9 +1148,9 @@ describe('MetaMask', function () { }, 10000) const txValues = await driver.findElements(By.css('.transaction-list-item__primary-currency')) - await driver.wait(until.elementTextMatches(txValues[0], /-1.5\s*TST/)) + 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/)) + await driver.wait(until.elementTextMatches(txStatuses[0], /Send TST/u)) }) }) @@ -1176,7 +1176,7 @@ describe('MetaMask', function () { }, 10000) const [txtListHeading] = await driver.findElements(By.css('.transaction-list-item .list-item__heading')) - await driver.wait(until.elementTextMatches(txtListHeading, /Approve TST spend limit/)) + await driver.wait(until.elementTextMatches(txtListHeading, /Approve TST spend limit/u)) await driver.clickElement(By.css('.transaction-list-item')) await driver.delay(regularDelayMs) }) @@ -1203,7 +1203,7 @@ describe('MetaMask', function () { }, 10000) const txStatuses = await driver.findElements(By.css('.list-item__heading')) - await driver.wait(until.elementTextMatches(txStatuses[0], /Approve TST spend limit/)) + await driver.wait(until.elementTextMatches(txStatuses[0], /Approve TST spend limit/u)) }) }) @@ -1244,7 +1244,7 @@ describe('MetaMask', function () { 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/)) + await driver.wait(until.elementTextMatches(balance, /0\s*BAT/u)) await driver.delay(regularDelayMs) }) }) diff --git a/test/e2e/mock-3box/server.js b/test/e2e/mock-3box/server.js index 9d6bc7372..1ac8a758c 100644 --- a/test/e2e/mock-3box/server.js +++ b/test/e2e/mock-3box/server.js @@ -32,6 +32,7 @@ const server = http.createServer(requestHandler) server.listen(port, (err) => { if (err) { - return 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 8ec86b3cb..87c439c0c 100644 --- a/test/e2e/permissions.spec.js +++ b/test/e2e/permissions.spec.js @@ -2,13 +2,13 @@ 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 enLocaleMessages = require('../../app/_locales/en/messages.json') const ganacheServer = new Ganache() @@ -90,11 +90,11 @@ describe('MetaMask', function () { }) it('gets the current accounts address', async function () { - const addressInput = await driver.findElement(By.css('.qr-ellip-address')) + const addressInput = await driver.findElement(By.css('.readonly-input__input')) 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) diff --git a/test/e2e/send-edit.spec.js b/test/e2e/send-edit.spec.js index c3e60f1c2..aa0fc6645 100644 --- a/test/e2e/send-edit.spec.js +++ b/test/e2e/send-edit.spec.js @@ -2,6 +2,7 @@ const assert = require('assert') const webdriver = require('selenium-webdriver') const { By, until } = webdriver +const enLocaleMessages = require('../../app/_locales/en/messages.json') const { tinyDelayMs, regularDelayMs, @@ -9,7 +10,6 @@ const { } = require('./helpers') const { buildWebDriver } = require('./webdriver') const Ganache = require('./ganache') -const enLocaleMessages = require('../../app/_locales/en/messages.json') const ganacheServer = new Ganache() @@ -205,7 +205,7 @@ describe('Using MetaMask with an existing account', function () { const txValues = await driver.findElements(By.css('.transaction-list-item__primary-currency')) assert.equal(txValues.length, 1) - assert.ok(/-2.2\s*ETH/.test(await txValues[0].getText())) + 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 6e2a558ec..9e83cc25e 100644 --- a/test/e2e/signature-request.spec.js +++ b/test/e2e/signature-request.spec.js @@ -74,7 +74,7 @@ describe('MetaMask', function () { await driver.delay(regularDelayMs) await driver.waitUntilXWindowHandles(3) - const windowHandles = await driver.getAllWindowHandles() + windowHandles = await driver.getAllWindowHandles() extension = windowHandles[0] dapp = await driver.switchToWindowWithTitle('E2E Test Dapp', windowHandles) @@ -108,7 +108,7 @@ describe('MetaMask', function () { 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)) + assert.equal(await address.getText(), `${publicAddress.slice(0, 8)}...${publicAddress.slice(publicAddress.length - 8)}`) }) it('signs the transaction', async function () { @@ -124,11 +124,11 @@ describe('MetaMask', function () { await driver.clickElement(By.css('[data-testid="account-options-menu__account-details"]')) await driver.delay(regularDelayMs) - const addressInput = await driver.findElement(By.css('.qr-ellip-address')) + 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')) - 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) diff --git a/test/e2e/tests/localization.spec.js b/test/e2e/tests/localization.spec.js index e3d4520ca..127d432bd 100644 --- a/test/e2e/tests/localization.spec.js +++ b/test/e2e/tests/localization.spec.js @@ -20,7 +20,7 @@ describe('Localization', function () { 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+/) + const [fiatAmount, fiatUnit] = secondaryBalanceText.trim().split(/\s+/u) assert.ok(fiatAmount.startsWith('₱')) assert.equal(fiatUnit, 'PHP') }, diff --git a/test/e2e/threebox.spec.js b/test/e2e/threebox.spec.js index e7affbfeb..3ba7c060e 100644 --- a/test/e2e/threebox.spec.js +++ b/test/e2e/threebox.spec.js @@ -3,6 +3,7 @@ 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, @@ -10,7 +11,6 @@ const { } = require('./helpers') const { buildWebDriver } = require('./webdriver') const Ganache = require('./ganache') -const enLocaleMessages = require('../../app/_locales/en/messages.json') const ganacheServer = new Ganache() @@ -97,7 +97,7 @@ describe('MetaMask', function () { 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/)) + await driver.wait(until.elementTextMatches(balance, /25\s*ETH/u)) await driver.delay(regularDelayMs) }) }) @@ -203,7 +203,7 @@ describe('MetaMask', function () { 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/)) + await driver2.wait(until.elementTextMatches(balance, /25\s*ETH/u)) await driver2.delay(regularDelayMs) }) }) diff --git a/test/e2e/webdriver/driver.js b/test/e2e/webdriver/driver.js index daf3a1acc..dcd516e41 100644 --- a/test/e2e/webdriver/driver.js +++ b/test/e2e/webdriver/driver.js @@ -1,8 +1,9 @@ const { promises: fs } = require('fs') -const { until, error: webdriverError } = require('selenium-webdriver') const { strict: assert } = require('assert') +const { until, error: webdriverError } = require('selenium-webdriver') class Driver { + /** * @param {!ThenableWebDriver} driver - A {@code WebDriver} instance * @param {string} browser - The type of browser this driver is controlling @@ -61,8 +62,7 @@ class Driver { this.driver.wait(until.elementIsEnabled(element), this.timeout), ) return acc - }, []), - ) + }, [])) return elements } @@ -136,9 +136,8 @@ class Driver { } async switchToWindowWithTitle (title, windowHandles) { - if (!windowHandles) { - windowHandles = await this.driver.getAllWindowHandles() - } + // eslint-disable-next-line no-param-reassign + windowHandles = windowHandles || await this.driver.getAllWindowHandles() for (const handle of windowHandles) { await this.driver.switchTo().window(handle) @@ -148,7 +147,7 @@ class Driver { } } - throw new Error('No window with title: ' + title) + throw new Error(`No window with title: ${title}`) } /** @@ -158,6 +157,7 @@ class Driver { * @returns {Promise} */ async closeAllWindowHandlesExcept (exceptions, windowHandles) { + // eslint-disable-next-line no-param-reassign windowHandles = windowHandles || await this.driver.getAllWindowHandles() for (const handle of windowHandles) { @@ -180,7 +180,9 @@ class Driver { await fs.writeFile(`${filepathBase}-screenshot.png`, screenshot, { encoding: 'base64' }) const htmlSource = await this.driver.getPageSource() await fs.writeFile(`${filepathBase}-dom.html`, htmlSource) - const uiState = await this.driver.executeScript(() => window.getCleanAppState()) + const uiState = await this.driver.executeScript( + () => window.getCleanAppState && window.getCleanAppState(), + ) await fs.writeFile(`${filepathBase}-state.json`, JSON.stringify(uiState, null, 2)) } diff --git a/test/e2e/webdriver/firefox.js b/test/e2e/webdriver/firefox.js index aff7227a4..f5c8426ae 100644 --- a/test/e2e/webdriver/firefox.js +++ b/test/e2e/webdriver/firefox.js @@ -20,6 +20,7 @@ const GeckoDriverCommand = { * A wrapper around a {@code WebDriver} instance exposing Firefox-specific functionality */ class FirefoxDriver { + /** * Builds a {@link FirefoxDriver} instance * @param {{extensionPath: string}} options - the options for the build diff --git a/test/e2e/webdriver/index.js b/test/e2e/webdriver/index.js index 652e27283..23e5acd5a 100644 --- a/test/e2e/webdriver/index.js +++ b/test/e2e/webdriver/index.js @@ -1,8 +1,8 @@ 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 fetchMockResponses = require('../../data/fetch-mocks.json') async function buildWebDriver ({ responsive, port } = {}) { const browser = process.env.SELENIUM_BROWSER @@ -37,16 +37,16 @@ async function buildBrowserWebDriver (browser, webDriverOptions) { async function setupFetchMocking (driver) { // define fetchMocking script, to be evaluated in the browser - function fetchMocking (fetchMockResponses) { + function fetchMocking (mockResponses) { window.origFetch = window.fetch.bind(window) window.fetch = async (...args) => { const url = args[0] if (url.match(/^http(s)?:\/\/ethgasstation\.info\/json\/ethgasAPI.*/u)) { - return { json: async () => clone(fetchMockResponses.ethGasBasic) } + return { json: async () => clone(mockResponses.ethGasBasic) } } else if (url.match(/http(s?):\/\/ethgasstation\.info\/json\/predictTable.*/u)) { - return { json: async () => clone(fetchMockResponses.ethGasPredictTable) } - } else if (url.match(/chromeextensionmm/)) { - return { json: async () => clone(fetchMockResponses.metametrics) } + return { json: async () => clone(mockResponses.ethGasPredictTable) } + } else if (url.match(/chromeextensionmm/u)) { + return { json: async () => clone(mockResponses.metametrics) } } return window.origFetch(...args) } diff --git a/test/helper.js b/test/helper.js index ea44bee48..d1b79335b 100644 --- a/test/helper.js +++ b/test/helper.js @@ -5,7 +5,6 @@ import Adapter from 'enzyme-adapter-react-16' import log from 'loglevel' import { JSDOM } from 'jsdom' - nock.disableNetConnect() nock.enableNetConnect('localhost') @@ -80,7 +79,7 @@ require('abortcontroller-polyfill/dist/polyfill-patch-fetch') window.localStorage = {} // override metamask-logo -window.requestAnimationFrame = () => {} +window.requestAnimationFrame = () => undefined // crypto.getRandomValues if (!window.crypto) { diff --git a/test/lib/createTxMeta.js b/test/lib/createTxMeta.js index 78f38bade..4dde18f62 100644 --- a/test/lib/createTxMeta.js +++ b/test/lib/createTxMeta.js @@ -1,10 +1,11 @@ import { snapshotFromTxMeta } from '../../app/scripts/controllers/transactions/lib/tx-state-history-helpers' export default function createTxMeta (partialMeta) { - const txMeta = Object.assign({ + const txMeta = { status: 'unapproved', txParams: {}, - }, partialMeta) + ...partialMeta, + } // initialize history txMeta.history = [] // capture initial snapshot of txMeta for history diff --git a/test/lib/render-helpers.js b/test/lib/render-helpers.js index 3671ad129..c0ac849ea 100644 --- a/test/lib/render-helpers.js +++ b/test/lib/render-helpers.js @@ -17,7 +17,7 @@ export function mountWithRouter (component, store = {}, pathname = '/') { history: new MemoryRouter().history, route: { location: { - pathname: pathname, + pathname, }, match: {}, }, @@ -27,7 +27,7 @@ export function mountWithRouter (component, store = {}, pathname = '/') { context: { router, t: (str) => str, - metricsEvent: () => {}, + metricsEvent: () => undefined, store, }, childContextTypes: { diff --git a/test/unit-global/frozenPromise.js b/test/unit-global/frozenPromise.js index 05f1defe7..594c1350a 100644 --- a/test/unit-global/frozenPromise.js +++ b/test/unit-global/frozenPromise.js @@ -1,7 +1,3 @@ - -/* eslint-disable no-native-reassign */ - -// this is what we're testing import '../../app/scripts/lib/freezeGlobals' import assert from 'assert' @@ -10,6 +6,7 @@ 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') } catch (err) { @@ -28,7 +25,7 @@ describe('Promise global is immutable', function () { it('throws when mutating existing Promise property', function () { try { - Promise.all = () => {} + Promise.all = () => undefined assert.fail('did not throw error') } catch (err) { assert.ok(err, 'did throw error') diff --git a/test/unit/app/ComposableObservableStore.js b/test/unit/app/ComposableObservableStore.js index 4eb5f0299..961be1dc0 100644 --- a/test/unit/app/ComposableObservableStore.js +++ b/test/unit/app/ComposableObservableStore.js @@ -1,6 +1,6 @@ import assert from 'assert' -import ComposableObservableStore from '../../../app/scripts/lib/ComposableObservableStore' import ObservableStore from 'obs-store' +import ComposableObservableStore from '../../../app/scripts/lib/ComposableObservableStore' describe('ComposableObservableStore', function () { it('should register initial state', function () { diff --git a/test/unit/app/account-import-strategies.spec.js b/test/unit/app/account-import-strategies.spec.js index fa43826d6..3c6b6fbef 100644 --- a/test/unit/app/account-import-strategies.spec.js +++ b/test/unit/app/account-import-strategies.spec.js @@ -1,6 +1,6 @@ import assert from 'assert' import ethUtil from 'ethereumjs-util' -import accountImporter from '../../../app/scripts/account-import-strategies/index' +import accountImporter from '../../../app/scripts/account-import-strategies' describe('Account Import Strategies', function () { const privkey = '0x4cfd3e90fc78b0f86bf7524722150bb8da9c60cd532564d7ff43f5716514f553' @@ -8,19 +8,19 @@ describe('Account Import Strategies', function () { describe('private key import', function () { it('imports a private key and strips 0x prefix', async function () { - const importPrivKey = await accountImporter.importAccount('Private Key', [ privkey ]) + const importPrivKey = await accountImporter.importAccount('Private Key', [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 () => { @@ -30,7 +30,7 @@ describe('Account Import Strategies', function () { 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']) }) }) }) @@ -40,7 +40,7 @@ describe('Account Import Strategies', function () { 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') } @@ -48,7 +48,7 @@ describe('Account Import Strategies', function () { it('imports json string and password to return a private key', async function () { const fileContentsPassword = 'password1' - const importJson = await accountImporter.importAccount('JSON File', [ json, fileContentsPassword]) + const importJson = await accountImporter.importAccount('JSON File', [json, fileContentsPassword]) assert.equal(importJson, '0x5733876abe94146069ce8bcbabbde2677f2e35fa33e875e92041ed2ac87e5bc7') }) }) diff --git a/test/unit/app/controllers/cached-balances-test.js b/test/unit/app/controllers/cached-balances-test.js index 272334dc5..f954da63f 100644 --- a/test/unit/app/controllers/cached-balances-test.js +++ b/test/unit/app/controllers/cached-balances-test.js @@ -9,7 +9,7 @@ describe('CachedBalancesController', function () { getNetwork: () => Promise.resolve(17), accountTracker: { store: { - subscribe: () => {}, + subscribe: () => undefined, }, }, initState: { @@ -32,7 +32,7 @@ describe('CachedBalancesController', function () { const controller = new CachedBalancesController({ accountTracker: { store: { - subscribe: () => {}, + subscribe: () => undefined, }, }, initState: { @@ -75,7 +75,7 @@ describe('CachedBalancesController', function () { const controller = new CachedBalancesController({ accountTracker: { store: { - subscribe: () => {}, + subscribe: () => undefined, }, }, initState: { diff --git a/test/unit/app/controllers/detect-tokens-test.js b/test/unit/app/controllers/detect-tokens-test.js index ee2418856..0b65e9258 100644 --- a/test/unit/app/controllers/detect-tokens-test.js +++ b/test/unit/app/controllers/detect-tokens-test.js @@ -14,7 +14,7 @@ describe('DetectTokensController', function () { const sandbox = sinon.createSandbox() let keyringMemStore, network, preferences - const noop = () => {} + const noop = () => undefined const networkControllerProviderConfig = { getAccounts: noop, @@ -22,9 +22,8 @@ describe('DetectTokensController', function () { beforeEach(async function () { - nock('https://api.infura.io') - .get(/.*/) + .get(/.*/u) .reply(200) keyringMemStore = new ObservableStore({ isUnlocked: false }) diff --git a/test/unit/app/controllers/ens-controller-test.js b/test/unit/app/controllers/ens-controller-test.js index 1176b8b42..cf57bdf1f 100644 --- a/test/unit/app/controllers/ens-controller-test.js +++ b/test/unit/app/controllers/ens-controller-test.js @@ -1,7 +1,6 @@ import assert from 'assert' import sinon from 'sinon' import ObservableStore from 'obs-store' -import HttpProvider from 'ethjs-provider-http' import EnsController from '../../../../app/scripts/controllers/ens' const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000' @@ -10,11 +9,10 @@ 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 provider = new HttpProvider('https://ropsten.infura.io') const currentNetworkId = '3' const networkStore = new ObservableStore(currentNetworkId) const ens = new EnsController({ - provider, + provider: { }, networkStore, }) diff --git a/test/unit/app/controllers/incoming-transactions-test.js b/test/unit/app/controllers/incoming-transactions-test.js index 7947a7102..727c394fa 100644 --- a/test/unit/app/controllers/incoming-transactions-test.js +++ b/test/unit/app/controllers/incoming-transactions-test.js @@ -2,12 +2,12 @@ import assert from 'assert' import sinon from 'sinon' import proxyquire from 'proxyquire' +import { ROPSTEN, RINKEBY, KOVAN, GOERLI, MAINNET } from '../../../../app/scripts/controllers/network/enums' + const IncomingTransactionsController = proxyquire('../../../../app/scripts/controllers/incoming-transactions', { '../lib/random-id': { default: () => 54321 }, }).default -import { ROPSTEN, RINKEBY, KOVAN, GOERLI, MAINNET } from '../../../../app/scripts/controllers/network/enums' - describe('IncomingTransactionsController', function () { const EMPTY_INIT_STATE = { incomingTransactions: {}, diff --git a/test/unit/app/controllers/metamask-controller-test.js b/test/unit/app/controllers/metamask-controller-test.js index 746b098d3..3bd1b3689 100644 --- a/test/unit/app/controllers/metamask-controller-test.js +++ b/test/unit/app/controllers/metamask-controller-test.js @@ -4,9 +4,10 @@ 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 EthQuery from 'eth-query' const threeBoxSpies = { init: sinon.stub(), @@ -14,12 +15,11 @@ const threeBoxSpies = { turnThreeBoxSyncingOn: sinon.stub(), _registerUpdates: sinon.spy(), } -import proxyquire from 'proxyquire' class ThreeBoxControllerMock { constructor () { this.store = { - subscribe: () => {}, + subscribe: () => undefined, getState: () => ({}), } this.init = threeBoxSpies.init @@ -78,7 +78,7 @@ const CUSTOM_RPC_URL = 'http://localhost:8545' describe('MetaMaskController', function () { let metamaskController const sandbox = sinon.createSandbox() - const noop = () => {} + const noop = () => undefined beforeEach(function () { @@ -92,28 +92,28 @@ describe('MetaMaskController', function () { nock('https://api.infura.io') .persist() - .get(/.*/) + .get(/.*/u) .reply(200) nock('https://min-api.cryptocompare.com') .persist() - .get(/.*/) + .get(/.*/u) .reply(200, '{"JPY":12415.9}') metamaskController = new MetaMaskController({ showUnapprovedTx: noop, showUnconfirmedMessage: noop, encryptor: { - encrypt: function (_, object) { + encrypt (_, object) { this.object = object return Promise.resolve('mock-encrypted') }, - decrypt: function () { + decrypt () { return Promise.resolve(this.object) }, }, initState: cloneDeep(firstTimeState), - platform: { showTransactionNotification: () => {} }, + platform: { showTransactionNotification: () => undefined, getVersion: () => 'foo' }, }) // disable diagnostics metamaskController.diagnostics = null @@ -146,7 +146,7 @@ describe('MetaMaskController', function () { beforeEach(async function () { const password = 'a-fake-password' await metamaskController.createNewVaultAndRestore(password, TEST_SEED) - await metamaskController.importAccountWithStrategy('Private Key', [ importPrivkey ]) + await metamaskController.importAccountWithStrategy('Private Key', [importPrivkey]) }) it('adds private key to keyrings in KeyringController', async function () { @@ -306,9 +306,9 @@ describe('MetaMaskController', function () { it('should return the balance known by accountTracker', async function () { const accounts = {} const balance = '0x14ced5122ce0a000' - accounts[TEST_ADDRESS] = { balance: balance } + accounts[TEST_ADDRESS] = { balance } - metamaskController.accountTracker.store.putState({ accounts: accounts }) + metamaskController.accountTracker.store.putState({ accounts }) const gotten = await metamaskController.getBalance(TEST_ADDRESS) @@ -323,7 +323,7 @@ describe('MetaMaskController', function () { callback(undefined, balance) }) - metamaskController.accountTracker.store.putState({ accounts: accounts }) + metamaskController.accountTracker.store.putState({ accounts }) const gotten = await metamaskController.getBalance(TEST_ADDRESS, ethQuery) @@ -367,7 +367,7 @@ describe('MetaMaskController', function () { address = '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc' identities = { '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc': { - 'address': address, + address, 'name': 'Account 1', }, '0xc42edfcc21ed14dda456aa0756c153f7985d8813': { @@ -503,7 +503,6 @@ describe('MetaMaskController', function () { assert.equal(keyrings[0].unlockedAccount, accountToUnlock) }) - it('should call keyringController.addNewAccount', async function () { assert(metamaskController.keyringController.addNewAccount.calledOnce) }) @@ -524,7 +523,6 @@ describe('MetaMaskController', function () { assert(metamaskController.preferencesController.setAccountLabel.calledOnce) }) - }) describe('#setCustomRpc', function () { @@ -684,7 +682,7 @@ describe('MetaMaskController', function () { msgParams = { 'from': address, - 'data': data, + data, } const promise = metamaskController.newUnsignedMessage(msgParams) @@ -694,7 +692,7 @@ describe('MetaMaskController', function () { metamaskMsgs = metamaskController.messageManager.getUnapprovedMsgs() messages = metamaskController.messageManager.messages msgId = Object.keys(metamaskMsgs)[0] - messages[0].msgParams.metamaskId = parseInt(msgId) + messages[0].msgParams.metamaskId = parseInt(msgId, 10) }) it('persists address from msg params', function () { @@ -714,7 +712,7 @@ describe('MetaMaskController', function () { }) it('rejects the message', function () { - const msgIdInt = parseInt(msgId) + const msgIdInt = parseInt(msgId, 10) metamaskController.cancelMessage(msgIdInt, noop) assert.equal(messages[0].status, 'rejected') }) @@ -744,7 +742,7 @@ describe('MetaMaskController', function () { msgParams = { 'from': address, - 'data': data, + data, } const promise = metamaskController.newUnsignedPersonalMessage(msgParams) @@ -754,15 +752,14 @@ describe('MetaMaskController', function () { metamaskPersonalMsgs = metamaskController.personalMessageManager.getUnapprovedMsgs() personalMessages = metamaskController.personalMessageManager.messages msgId = Object.keys(metamaskPersonalMsgs)[0] - personalMessages[0].msgParams.metamaskId = parseInt(msgId) + personalMessages[0].msgParams.metamaskId = parseInt(msgId, 10) }) it('errors with no from in msgParams', async function () { - const msgParams = { - 'data': data, - } try { - await metamaskController.newUnsignedPersonalMessage(msgParams) + await metamaskController.newUnsignedPersonalMessage({ + data, + }) assert.fail('should have thrown') } catch (error) { assert.equal(error.message, 'MetaMask Message Signature: from field is required.') @@ -786,7 +783,7 @@ describe('MetaMaskController', function () { }) it('rejects the message', function () { - const msgIdInt = parseInt(msgId) + const msgIdInt = parseInt(msgId, 10) metamaskController.cancelPersonalMessage(msgIdInt, noop) assert.equal(personalMessages[0].status, 'rejected') }) @@ -819,7 +816,8 @@ describe('MetaMaskController', function () { const { promise, resolve } = deferredPromise() const streamTest = createThoughStream((chunk, _, cb) => { if (chunk.name !== 'phishing') { - return cb() + cb() + return } assert.equal(chunk.data.hostname, (new URL(phishingMessageSender.url)).hostname) resolve() diff --git a/test/unit/app/controllers/network/network-controller-test.js b/test/unit/app/controllers/network/network-controller-test.js index 08164d99d..161df6170 100644 --- a/test/unit/app/controllers/network/network-controller-test.js +++ b/test/unit/app/controllers/network/network-controller-test.js @@ -6,7 +6,7 @@ import { getNetworkDisplayName } from '../../../../../app/scripts/controllers/ne describe('NetworkController', function () { describe('controller', function () { let networkController - const noop = () => {} + const noop = () => undefined const networkControllerProviderConfig = { getAccounts: noop, } @@ -53,7 +53,7 @@ describe('NetworkController', function () { it('should update provider.type', function () { networkController.initializeProvider(networkControllerProviderConfig) networkController.setProviderType('mainnet') - const type = networkController.getProviderConfig().type + const { type } = networkController.getProviderConfig() assert.equal(type, 'mainnet', 'provider type is updated') }) it('should set the network to loading', function () { diff --git a/test/unit/app/controllers/permissions/helpers.js b/test/unit/app/controllers/permissions/helpers.js index 0378dc089..e920b851d 100644 --- a/test/unit/app/controllers/permissions/helpers.js +++ b/test/unit/app/controllers/permissions/helpers.js @@ -26,6 +26,7 @@ export function grantPermissions (permController, origin, permissions) { * @return {Function} A convenient wrapper for the requestUserApproval function. */ export function getRequestUserApprovalHelper (permController) { + /** * Returns a request object that can be passed to requestUserApproval. * diff --git a/test/unit/app/controllers/permissions/mocks.js b/test/unit/app/controllers/permissions/mocks.js index 5302d9f61..578b39911 100644 --- a/test/unit/app/controllers/permissions/mocks.js +++ b/test/unit/app/controllers/permissions/mocks.js @@ -20,7 +20,7 @@ import { * - Immutable mock values like Ethereum accounts and expected states */ -export const noop = () => {} +export const noop = () => undefined /** * Mock Permissions Controller and Middleware @@ -33,7 +33,7 @@ const keyringAccounts = deepFreeze([ '0xcc74c7a59194e5d9268476955650d1e285be703c', ]) -const getKeyringAccounts = async () => [ ...keyringAccounts ] +const getKeyringAccounts = async () => [...keyringAccounts] const getIdentities = () => { return keyringAccounts.reduce( @@ -108,6 +108,7 @@ export function getPermissionsMiddleware (permController, origin, extensionId) { return (req, res = {}, next = noop, end) => { return new Promise((resolve, reject) => { + // eslint-disable-next-line no-param-reassign end = end || _end middleware(req, res, next, end) @@ -260,7 +261,8 @@ const PERMS = { return { eth_accounts: { caveats: CAVEATS.eth_accounts(accounts), - } } + }, + } }, /** @@ -573,7 +575,7 @@ export const getters = deepFreeze({ return { origin, method: 'wallet_requestPermissions', - params: [ PERMS.requests[permissionName]() ], + params: [PERMS.requests[permissionName]()], } }, @@ -589,7 +591,7 @@ export const getters = deepFreeze({ return { origin, method: 'wallet_requestPermissions', - params: [ permissions ], + params: [permissions], } }, diff --git a/test/unit/app/controllers/permissions/permissions-controller-test.js b/test/unit/app/controllers/permissions/permissions-controller-test.js index 1b4f315a3..f51ed0800 100644 --- a/test/unit/app/controllers/permissions/permissions-controller-test.js +++ b/test/unit/app/controllers/permissions/permissions-controller-test.js @@ -170,7 +170,6 @@ describe('permissions controller', function () { 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', @@ -189,7 +188,7 @@ describe('permissions controller', function () { Object.keys(notifications).forEach((origin) => { assert.deepEqual( notifications[origin], - [ NOTIFICATIONS.removedAccounts() ], + [NOTIFICATIONS.removedAccounts()], 'origin should have single wallet_accountsChanged:[] notification', ) }) @@ -447,12 +446,12 @@ describe('permissions controller', function () { ) await assert.doesNotThrow( - () => permController.validatePermittedAccounts([ keyringAccounts[0] ]), + () => permController.validatePermittedAccounts([keyringAccounts[0]]), 'should not throw on single keyring account', ) await assert.doesNotThrow( - () => permController.validatePermittedAccounts([ keyringAccounts[1] ]), + () => permController.validatePermittedAccounts([keyringAccounts[1]]), 'should not throw on single keyring account', ) }) @@ -655,7 +654,6 @@ describe('permissions controller', function () { }) }) - describe('removeAllAccountPermissions', function () { let permController, notifications @@ -823,9 +821,9 @@ describe('permissions controller', function () { beforeEach(function () { identities = ALL_ACCOUNTS.reduce( - (identities, account) => { - identities[account] = {} - return identities + (identitiesAcc, account) => { + identitiesAcc[account] = {} + return identitiesAcc }, {}, ) @@ -1284,7 +1282,7 @@ describe('permissions controller', function () { assert.deepEqual( notifications[DOMAINS.a.origin], - [ NOTIFICATIONS.newAccounts(ACCOUNTS.a.permitted) ], + [NOTIFICATIONS.newAccounts(ACCOUNTS.a.permitted)], 'origin should have correct notification', ) }) 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 d6e3482c6..6f9fc104b 100644 --- a/test/unit/app/controllers/permissions/permissions-log-controller-test.js +++ b/test/unit/app/controllers/permissions/permissions-log-controller-test.js @@ -310,7 +310,7 @@ describe('permissions log', function () { ) // 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() @@ -356,7 +356,7 @@ describe('permissions log', function () { 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) @@ -384,7 +384,7 @@ describe('permissions log', function () { DOMAINS.a.origin, PERM_NAMES.test_method, ) delete req.params - const res = { result: [ PERMS.granted.test_method() ] } + const res = { result: [PERMS.granted.test_method()] } // no params => no response logMiddleware({ ...req }, { ...res }) @@ -400,7 +400,7 @@ describe('permissions log', function () { DOMAINS.a.origin, PERM_NAMES.eth_accounts, ) const res = { - result: [ PERMS.granted.eth_accounts(ACCOUNTS.a.permitted) ], + result: [PERMS.granted.eth_accounts(ACCOUNTS.a.permitted)], } logMiddleware({ ...req }, { ...res }) @@ -419,7 +419,7 @@ describe('permissions log', function () { 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 }) @@ -438,7 +438,7 @@ describe('permissions log', function () { DOMAINS.a.origin, PERM_NAMES.eth_accounts, ) const res = { - result: [ PERMS.granted.eth_accounts(ACCOUNTS.a.permitted) ], + result: [PERMS.granted.eth_accounts(ACCOUNTS.a.permitted)], } delete res.result[0].caveats @@ -458,7 +458,7 @@ describe('permissions log', function () { DOMAINS.a.origin, PERM_NAMES.eth_accounts, ) const res = { - result: [ PERMS.granted.eth_accounts(ACCOUNTS.a.permitted) ], + result: [PERMS.granted.eth_accounts(ACCOUNTS.a.permitted)], } res.result[0].caveats.push({ foo: 'bar' }) @@ -558,7 +558,7 @@ describe('permissions log', function () { DOMAINS.a.origin, PERM_NAMES.test_method, ), res: { - result: [ PERMS.granted.test_method() ], + result: [PERMS.granted.test_method()], }, }) @@ -568,7 +568,7 @@ describe('permissions log', function () { DOMAINS.b.origin, PERM_NAMES.eth_accounts, ), res: { - result: [ PERMS.granted.eth_accounts(ACCOUNTS.b.permitted) ], + result: [PERMS.granted.eth_accounts(ACCOUNTS.b.permitted)], }, }) @@ -616,7 +616,7 @@ describe('permissions log', function () { DOMAINS.a.origin, PERM_NAMES.test_method, ), res: { - result: [ PERMS.granted.test_method() ], + result: [PERMS.granted.test_method()], }, }) diff --git a/test/unit/app/controllers/preferences-controller-test.js b/test/unit/app/controllers/preferences-controller-test.js index 5d711f1c8..3484dd210 100644 --- a/test/unit/app/controllers/preferences-controller-test.js +++ b/test/unit/app/controllers/preferences-controller-test.js @@ -1,8 +1,8 @@ import assert from 'assert' import ObservableStore from 'obs-store' +import sinon from 'sinon' import PreferencesController from '../../../../app/scripts/controllers/preferences' import { addInternalMethodPrefix } from '../../../../app/scripts/controllers/permissions' -import sinon from 'sinon' describe('preferences controller', function () { let preferencesController @@ -39,7 +39,7 @@ describe('preferences controller', function () { '0x7e57e2', ]) - const accountTokens = preferencesController.store.getState().accountTokens + const { accountTokens } = preferencesController.store.getState() assert.deepEqual(accountTokens, { '0xda22le': {}, @@ -119,7 +119,6 @@ describe('preferences controller', function () { address: '0xda22le', }) - preferencesController.setAccountLabel('0xda22le', 'Dazzle') assert.deepEqual(preferencesController.store.getState().identities['0xda22le'], { name: 'Dazzle', @@ -130,7 +129,7 @@ describe('preferences controller', function () { describe('getTokens', function () { it('should return an empty list initially', async function () { - preferencesController.setAddresses([ '0x7e57e2' ]) + preferencesController.setAddresses(['0x7e57e2']) await preferencesController.setSelectedAddress('0x7e57e2') const tokens = preferencesController.getTokens() @@ -144,7 +143,7 @@ describe('preferences controller', function () { const symbol = 'ABBR' const decimals = 5 - preferencesController.setAddresses([ '0x7e57e2' ]) + preferencesController.setAddresses(['0x7e57e2']) await preferencesController.setSelectedAddress('0x7e57e2') await preferencesController.addToken(address, symbol, decimals) @@ -162,7 +161,7 @@ describe('preferences controller', function () { const symbol = 'ABBR' const decimals = 5 - preferencesController.setAddresses([ '0x7e57e2' ]) + preferencesController.setAddresses(['0x7e57e2']) await preferencesController.setSelectedAddress('0x7e57e2') await preferencesController.addToken(address, symbol, decimals) @@ -241,7 +240,7 @@ describe('preferences controller', function () { describe('removeToken', function () { it('should remove the only token from its state', async function () { - preferencesController.setAddresses([ '0x7e57e2' ]) + preferencesController.setAddresses(['0x7e57e2']) await preferencesController.setSelectedAddress('0x7e57e2') await preferencesController.addToken('0xa', 'A', 5) await preferencesController.removeToken('0xa') @@ -251,7 +250,7 @@ describe('preferences controller', function () { }) it('should remove a token from its state', async function () { - preferencesController.setAddresses([ '0x7e57e2' ]) + preferencesController.setAddresses(['0x7e57e2']) await preferencesController.setSelectedAddress('0x7e57e2') await preferencesController.addToken('0xa', 'A', 4) await preferencesController.addToken('0xb', 'B', 5) @@ -366,15 +365,13 @@ describe('preferences controller', function () { }) describe('on watchAsset', function () { - let stubNext, stubEnd, stubHandleWatchAssetERC20, asy, req, res + let stubHandleWatchAssetERC20, asy, req, res const sandbox = sinon.createSandbox() beforeEach(function () { req = { params: {} } res = {} - asy = { next: () => {}, end: () => {} } - stubNext = sandbox.stub(asy, 'next') - stubEnd = sandbox.stub(asy, 'end').returns(0) + asy = { next: sandbox.spy(), end: sandbox.spy() } stubHandleWatchAssetERC20 = sandbox.stub(preferencesController, '_handleWatchAssetERC20') }) after(function () { @@ -382,40 +379,33 @@ describe('preferences controller', function () { }) it('shouldn not do anything if method not corresponds', async function () { - const asy = { next: () => {}, end: () => {} } - const stubNext = sandbox.stub(asy, 'next') - const stubEnd = sandbox.stub(asy, 'end').returns(0) req.method = 'metamask' await preferencesController.requestWatchAsset(req, res, asy.next, asy.end) - sandbox.assert.notCalled(stubEnd) - sandbox.assert.called(stubNext) + sandbox.assert.notCalled(asy.end) + sandbox.assert.called(asy.next) }) it('should do something if method is supported', async function () { - const asy = { next: () => {}, end: () => {} } - const stubNext = sandbox.stub(asy, 'next') - const stubEnd = sandbox.stub(asy, 'end').returns(0) req.method = 'metamask_watchAsset' req.params.type = 'someasset' await preferencesController.requestWatchAsset(req, res, asy.next, asy.end) - sandbox.assert.called(stubEnd) - sandbox.assert.notCalled(stubNext) + sandbox.assert.called(asy.end) + sandbox.assert.notCalled(asy.next) req.method = addInternalMethodPrefix('watchAsset') req.params.type = 'someasset' await preferencesController.requestWatchAsset(req, res, asy.next, asy.end) - sandbox.assert.calledTwice(stubEnd) - sandbox.assert.notCalled(stubNext) + sandbox.assert.calledTwice(asy.end) + sandbox.assert.notCalled(asy.next) }) it('should through error if method is supported but asset type is not', async function () { req.method = 'metamask_watchAsset' req.params.type = 'someasset' await preferencesController.requestWatchAsset(req, res, asy.next, asy.end) - sandbox.assert.called(stubEnd) + sandbox.assert.called(asy.end) sandbox.assert.notCalled(stubHandleWatchAssetERC20) - sandbox.assert.notCalled(stubNext) + sandbox.assert.notCalled(asy.next) assert.deepEqual(res, {}) }) it('should trigger handle add asset if type supported', async function () { - const asy = { next: () => {}, end: () => {} } req.method = 'metamask_watchAsset' req.params.type = 'ERC20' await preferencesController.requestWatchAsset(req, res, asy.next, asy.end) @@ -442,7 +432,7 @@ describe('preferences controller', function () { req.params.options = { address, symbol, decimals, image } sandbox.stub(preferencesController, '_validateERC20AssetParams').returns(true) - preferencesController.openPopup = async () => {} + preferencesController.openPopup = async () => undefined await preferencesController._handleWatchAssetERC20(req.params.options) const suggested = preferencesController.getSuggestedTokens() @@ -478,46 +468,16 @@ describe('preferences controller', function () { assert.ok(assetImages[address], `set image correctly`) }) it('should validate ERC20 asset correctly', async function () { - const validateSpy = sandbox.spy(preferencesController._validateERC20AssetParams) - try { - validateSpy({ rawAddress: '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07', symbol: 'ABC', decimals: 0 }) - } catch (e) {} - assert.equal(validateSpy.threw(), false, 'correct options object') - const validateSpyAddress = sandbox.spy(preferencesController._validateERC20AssetParams) - try { - validateSpyAddress({ symbol: 'ABC', decimals: 0 }) - } catch (e) {} - assert.equal(validateSpyAddress.threw(), true, 'options object with no address') - const validateSpySymbol = sandbox.spy(preferencesController._validateERC20AssetParams) - try { - validateSpySymbol({ rawAddress: '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07', decimals: 0 }) - } catch (e) {} - assert.equal(validateSpySymbol.threw(), true, 'options object with no symbol') - const validateSpyDecimals = sandbox.spy(preferencesController._validateERC20AssetParams) - try { - validateSpyDecimals({ rawAddress: '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07', symbol: 'ABC' }) - } catch (e) {} - assert.equal(validateSpyDecimals.threw(), true, 'options object with no decimals') - const validateSpyInvalidSymbol = sandbox.spy(preferencesController._validateERC20AssetParams) - try { - validateSpyInvalidSymbol({ rawAddress: '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07', symbol: 'ABCDEFGHI', decimals: 0 }) - } catch (e) {} - assert.equal(validateSpyInvalidSymbol.threw(), true, 'options object with invalid symbol') - const validateSpyInvalidDecimals1 = sandbox.spy(preferencesController._validateERC20AssetParams) - try { - validateSpyInvalidDecimals1({ rawAddress: '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07', symbol: 'ABCDEFGHI', decimals: -1 }) - } catch (e) {} - assert.equal(validateSpyInvalidDecimals1.threw(), true, 'options object with decimals less than zero') - const validateSpyInvalidDecimals2 = sandbox.spy(preferencesController._validateERC20AssetParams) - try { - validateSpyInvalidDecimals2({ rawAddress: '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07', symbol: 'ABCDEFGHI', decimals: 38 }) - } catch (e) {} - assert.equal(validateSpyInvalidDecimals2.threw(), true, 'options object with decimals more than 36') - const validateSpyInvalidAddress = sandbox.spy(preferencesController._validateERC20AssetParams) - try { - validateSpyInvalidAddress({ rawAddress: '0x123', symbol: 'ABC', decimals: 0 }) - } catch (e) {} - assert.equal(validateSpyInvalidAddress.threw(), true, 'options object with address invalid') + const validate = preferencesController._validateERC20AssetParams + + assert.doesNotThrow(() => validate({ rawAddress: '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07', symbol: 'ABC', decimals: 0 })) + assert.throws(() => validate({ symbol: 'ABC', decimals: 0 }), 'missing address should fail') + assert.throws(() => validate({ rawAddress: '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07', decimals: 0 }), 'missing symbol should fail') + assert.throws(() => validate({ rawAddress: '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07', symbol: 'ABC' }), 'missing decimals should fail') + assert.throws(() => validate({ rawAddress: '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07', symbol: 'ABCDEFGHI', decimals: 0 }), 'invalid symbol should fail') + assert.throws(() => validate({ rawAddress: '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07', symbol: 'ABC', decimals: -1 }), 'decimals < 0 should fail') + assert.throws(() => validate({ rawAddress: '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07', symbol: 'ABC', decimals: 38 }), 'decimals > 36 should fail') + assert.throws(() => validate({ rawAddress: '0x123', symbol: 'ABC', decimals: 0 }), 'invalid address should fail') }) }) diff --git a/test/unit/app/controllers/token-rates-controller.js b/test/unit/app/controllers/token-rates-controller.js index 2bc341d22..1f342abe5 100644 --- a/test/unit/app/controllers/token-rates-controller.js +++ b/test/unit/app/controllers/token-rates-controller.js @@ -1,7 +1,7 @@ import assert from 'assert' import sinon from 'sinon' -import TokenRatesController from '../../../../app/scripts/controllers/token-rates' import ObservableStore from 'obs-store' +import TokenRatesController from '../../../../app/scripts/controllers/token-rates' describe('TokenRatesController', function () { it('should listen for preferences store updates', function () { 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 facc0bb12..bbdc72551 100644 --- a/test/unit/app/controllers/transactions/pending-tx-tracker-test.js +++ b/test/unit/app/controllers/transactions/pending-tx-tracker-test.js @@ -1,5 +1,5 @@ -import sinon from 'sinon' 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' @@ -147,15 +147,15 @@ describe('PendingTransactionTracker', function () { }, nonceTracker: { getGlobalLock: async () => { - return { releaseLock: () => {} } + return { releaseLock: () => undefined } }, }, getPendingTransactions: () => txList, getCompletedTransactions: () => { return [] }, - publishTransaction: () => {}, - confirmTransaction: () => {}, + publishTransaction: () => undefined, + confirmTransaction: () => undefined, }) const checkPendingTxStub = sinon.stub(pendingTxTracker, '_checkPendingTx').resolves() diff --git a/test/unit/app/controllers/transactions/tx-controller-test.js b/test/unit/app/controllers/transactions/tx-controller-test.js index e9d229aba..c9b5364c7 100644 --- a/test/unit/app/controllers/transactions/tx-controller-test.js +++ b/test/unit/app/controllers/transactions/tx-controller-test.js @@ -13,7 +13,7 @@ import { SEND_ETHER_ACTION_KEY, DEPLOY_CONTRACT_ACTION_KEY, CONTRACT_INTERACTION_KEY, -} from '../../../../../ui/app/helpers/constants/transactions.js' +} from '../../../../../ui/app/helpers/constants/transactions' import { createTestProviderTools, getTestAccounts } from '../../../../stub/provider' @@ -37,7 +37,7 @@ describe('Transaction Controller', function () { blockTrackerStub.getLatestBlock = noop txController = new TransactionController({ provider, - getGasPrice: function () { + getGasPrice () { return '0xee6b2800' }, networkStore: new ObservableStore(currentNetworkId), @@ -47,7 +47,7 @@ describe('Transaction Controller', function () { ethTx.sign(fromAccount.key) resolve() }), - getPermittedAccounts: () => {}, + getPermittedAccounts: () => undefined, }) txController.nonceTracker.getNonceLock = () => Promise.resolve({ nextNonce: 0, releaseLock: noop }) }) @@ -108,7 +108,6 @@ describe('Transaction Controller', function () { }) }) - describe('#newUnapprovedTransaction', function () { let stub, txMeta, txParams beforeEach(function () { @@ -307,7 +306,7 @@ describe('Transaction Controller', function () { txController.addTx({ id: '1', status: 'unapproved', metamaskNetworkId: currentNetworkId, txParams: {} }, noop) const rawTx = await txController.signTransaction('1') const ethTx = new EthTx(ethUtil.toBuffer(rawTx)) - assert.equal(ethTx.getChainId(), parseInt(currentNetworkId)) + assert.equal(ethTx.getChainId(), 42) }) }) @@ -387,7 +386,7 @@ describe('Transaction Controller', function () { { id: 1, status: 'submitted', metamaskNetworkId: currentNetworkId, txParams, history: [{}] }, ]) - expectedTxParams = Object.assign({}, txParams, { gasPrice: '0xb' }) + expectedTxParams = { ...txParams, gasPrice: '0xb' } }) afterEach(function () { @@ -453,7 +452,7 @@ describe('Transaction Controller', function () { }) it('should ignore the error "Transaction Failed: known transaction" and be as usual', async function () { - providerResultStub['eth_sendRawTransaction'] = async (_, __, ___, end) => { + providerResultStub.eth_sendRawTransaction = async (_, __, ___, end) => { end('Transaction Failed: known transaction') } const rawTx = '0xf86204831e848082520894f231d46dd78806e1dd93442cf33c7671f853874880802ca05f973e540f2d3c2f06d3725a626b75247593cb36477187ae07ecfe0a4db3cf57a00259b52ee8c58baaa385fb05c3f96116e58de89bcc165cb3bfdfc708672fed8a' @@ -547,7 +546,7 @@ describe('Transaction Controller', function () { _blockTrackerStub.getLatestBlock = noop const _txController = new TransactionController({ provider: _provider, - getGasPrice: function () { + getGasPrice () { return '0xee6b2800' }, networkStore: new ObservableStore(currentNetworkId), @@ -579,7 +578,7 @@ describe('Transaction Controller', function () { _blockTrackerStub.getLatestBlock = noop const _txController = new TransactionController({ provider: _provider, - getGasPrice: function () { + getGasPrice () { return '0xee6b2800' }, networkStore: new ObservableStore(currentNetworkId), 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 615a25527..21ba62746 100644 --- a/test/unit/app/controllers/transactions/tx-gas-util-test.js +++ b/test/unit/app/controllers/transactions/tx-gas-util-test.js @@ -9,7 +9,7 @@ describe('txUtils', function () { before(function () { txUtils = new TxUtils(new Proxy({}, { get: () => { - return () => {} + return () => undefined }, })) }) 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 abd7a7098..915e36362 100644 --- a/test/unit/app/controllers/transactions/tx-state-manager-test.js +++ b/test/unit/app/controllers/transactions/tx-state-manager-test.js @@ -34,15 +34,15 @@ describe('TransactionStateManager', function () { it('should emit a signed event to signal the execution of callback', function () { const tx = { id: 1, status: 'unapproved', metamaskNetworkId: currentNetworkId, txParams: {} } const clock = sinon.useFakeTimers() - const noop = sinon.spy() + const onSigned = sinon.spy() txStateManager.addTx(tx) - txStateManager.on('1:signed', noop) + txStateManager.on('1:signed', onSigned) txStateManager.setTxStatusSigned(1) clock.runAll() clock.restore() - assert.ok(noop.calledOnce) + assert.ok(onSigned.calledOnce) }) }) @@ -59,15 +59,15 @@ describe('TransactionStateManager', function () { it('should emit a rejected event to signal the execution of callback', function () { const tx = { id: 1, status: 'unapproved', metamaskNetworkId: currentNetworkId, txParams: {} } const clock = sinon.useFakeTimers() - const noop = sinon.spy() + const onSigned = sinon.spy() txStateManager.addTx(tx) - txStateManager.on('1:rejected', noop) + txStateManager.on('1:rejected', onSigned) txStateManager.setTxStatusRejected(1) clock.runAll() clock.restore() - assert.ok(noop.calledOnce) + assert.ok(onSigned.calledOnce) }) }) @@ -587,13 +587,13 @@ describe('TransactionStateManager', function () { describe('#_removeTx', function () { it('should remove the transaction from the storage', function () { - txStateManager._saveTxList([ { id: 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._saveTxList([{ id: 1 }, { id: 2 }]) txStateManager._removeTx(1) assert.equal(txStateManager.getFullTxList()[0].id, 2, 'txList should have a id of 2') }) diff --git a/test/unit/app/controllers/transactions/tx-utils-test.js b/test/unit/app/controllers/transactions/tx-utils-test.js index 461a49d51..6923d53d5 100644 --- a/test/unit/app/controllers/transactions/tx-utils-test.js +++ b/test/unit/app/controllers/transactions/tx-utils-test.js @@ -70,7 +70,6 @@ describe('txUtils', function () { }) }) - describe('#validateFrom', function () { it('should error when from is not a hex string', function () { diff --git a/test/unit/app/message-manager-test.js b/test/unit/app/message-manager-test.js index 8c499c97d..66eef7b10 100644 --- a/test/unit/app/message-manager-test.js +++ b/test/unit/app/message-manager-test.js @@ -14,9 +14,6 @@ describe('Message Manager', function () { assert.ok(Array.isArray(result)) assert.equal(result.length, 0) }) - it('should also return transactions from local storage if any', function () { - - }) }) describe('#addMsg', function () { diff --git a/test/unit/app/nodeify-test.js b/test/unit/app/nodeify-test.js index a70446ef0..f6e9a3207 100644 --- a/test/unit/app/nodeify-test.js +++ b/test/unit/app/nodeify-test.js @@ -4,7 +4,7 @@ import nodeify from '../../../app/scripts/lib/nodeify' describe('nodeify', function () { const obj = { foo: 'bar', - promiseFunc: function (a) { + promiseFunc (a) { const solution = this.foo + a return Promise.resolve(solution) }, @@ -16,9 +16,10 @@ describe('nodeify', function () { if (!err) { assert.equal(res, 'barbaz') done() - } else { - done(new Error(err.toString())) + return } + + done(new Error(err.toString())) }) }) @@ -37,7 +38,8 @@ describe('nodeify', function () { try { nodified((err, result) => { if (err) { - return done(new Error(`should not have thrown any error: ${err.message}`)) + done(new Error(`should not have thrown any error: ${err.message}`)) + return } assert.equal(42, result, 'got expected result') }) @@ -54,7 +56,8 @@ describe('nodeify', function () { try { nodified((err, result) => { if (result) { - return done(new Error('should not have returned any result')) + 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') diff --git a/test/unit/app/personal-message-manager-test.js b/test/unit/app/personal-message-manager-test.js index 9e5aaaba1..d95ca5e14 100644 --- a/test/unit/app/personal-message-manager-test.js +++ b/test/unit/app/personal-message-manager-test.js @@ -14,9 +14,6 @@ describe('Personal Message Manager', function () { assert.ok(Array.isArray(result)) assert.equal(result.length, 0) }) - it('should also return transactions from local storage if any', function () { - - }) }) describe('#addMsg', function () { diff --git a/test/unit/app/typed-message-manager.spec.js b/test/unit/app/typed-message-manager.spec.js index c69e407a3..5ab7258ad 100644 --- a/test/unit/app/typed-message-manager.spec.js +++ b/test/unit/app/typed-message-manager.spec.js @@ -1,6 +1,6 @@ import assert from 'assert' import sinon from 'sinon' -import NetworkController from '../../../app/scripts/controllers/network/index' +import NetworkController from '../../../app/scripts/controllers/network' import TypedMessageManager from '../../../app/scripts/lib/typed-message-manager' describe('Typed Message Manager', function () { @@ -68,8 +68,8 @@ describe('Typed Message Manager', function () { typedMsgs = typedMessageManager.getUnapprovedMsgs() messages = typedMessageManager.messages msgId = Object.keys(typedMsgs)[0] - messages[0].msgParams.metamaskId = parseInt(msgId) - numberMsgId = parseInt(msgId) + messages[0].msgParams.metamaskId = parseInt(msgId, 10) + numberMsgId = parseInt(msgId, 10) }) it('supports version 1 of signedTypedData', function () { diff --git a/test/unit/lib/account-link.test.js b/test/unit/lib/account-link.test.js index a37bdfcb5..8ba9404e4 100644 --- a/test/unit/lib/account-link.test.js +++ b/test/unit/lib/account-link.test.js @@ -1,5 +1,5 @@ -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 () { diff --git a/test/unit/migrations/023-test.js b/test/unit/migrations/023-test.js index 821057bf8..49f40b033 100644 --- a/test/unit/migrations/023-test.js +++ b/test/unit/migrations/023-test.js @@ -38,8 +38,10 @@ let nonDeletableCount = 0 let status while (transactions.length <= 100) { 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++ + nonDeletableCount += 1 } transactions.push({ status }) } @@ -54,7 +56,6 @@ while (transactions20.length < 20) { transactions20.push({ status }) } - storage.data.TransactionController.transactions = transactions describe('storage is migrated successfully and the proper transactions are remove from state', function () { @@ -65,7 +66,7 @@ describe('storage is migrated successfully and the proper transactions are remov const migratedTransactions = migratedData.data.TransactionController.transactions migratedTransactions.forEach((tx) => { if (!deletableTxStates.find((s) => s === tx.status)) { - leftoverNonDeletableTxCount++ + leftoverNonDeletableTxCount += 1 } }) assert.equal(leftoverNonDeletableTxCount, nonDeletableCount, "migration shouldn't delete transactions we want to keep") diff --git a/test/unit/migrations/024-test.js b/test/unit/migrations/024-test.js index 1aa050b73..446f85f07 100644 --- a/test/unit/migrations/024-test.js +++ b/test/unit/migrations/024-test.js @@ -18,13 +18,11 @@ const storage = { const transactions = [] - while (transactions.length <= 10) { transactions.push({ txParams: { from: '0x8aCce2391c0d510a6c5E5d8f819a678f79b7e675' }, status: 'unapproved' }) transactions.push({ txParams: { from: '0x8aCce2391c0d510a6c5E5d8f819a678f79b7e675' }, status: 'confirmed' }) } - storage.data.TransactionController.transactions = transactions describe('storage is migrated successfully and the txParams.from are lowercase', function () { diff --git a/test/unit/migrations/025-test.js b/test/unit/migrations/025-test.js index 6224eef5a..2cd3381ca 100644 --- a/test/unit/migrations/025-test.js +++ b/test/unit/migrations/025-test.js @@ -19,13 +19,11 @@ const storage = { const transactions = [] - while (transactions.length <= 10) { transactions.push({ txParams: { from: '0x8aCce2391c0d510a6c5E5d8f819a678f79b7e675', random: 'stuff', chainId: 2 }, status: 'unapproved' }) transactions.push({ txParams: { from: '0x8aCce2391c0d510a6c5E5d8f819a678f79b7e675' }, status: 'confirmed' }) } - storage.data.TransactionController.transactions = transactions describe('storage is migrated successfully and the txParams.from are lowercase', function () { diff --git a/test/unit/migrations/026-test.js b/test/unit/migrations/026-test.js index 83858c1c9..3227e3394 100644 --- a/test/unit/migrations/026-test.js +++ b/test/unit/migrations/026-test.js @@ -19,7 +19,7 @@ describe('migration #26', function () { it('should move the identities from KeyringController', function (done) { migration26.migrate(oldStorage) .then((newStorage) => { - const identities = newStorage.data.PreferencesController.identities + const { identities } = newStorage.data.PreferencesController assert.deepEqual(identities, { '0x1e77e2': { name: 'Test Account 1', address: '0x1e77e2' }, '0x7e57e2': { name: 'Test Account 2', address: '0x7e57e2' }, diff --git a/test/unit/migrations/027-test.js b/test/unit/migrations/027-test.js index 126a3b620..959f30374 100644 --- a/test/unit/migrations/027-test.js +++ b/test/unit/migrations/027-test.js @@ -14,14 +14,12 @@ const oldStorage = { const transactions = [] - while (transactions.length < 9) { transactions.push({ status: 'rejected' }) transactions.push({ status: 'unapproved' }) transactions.push({ status: 'approved' }) } - oldStorage.data.TransactionController.transactions = transactions describe('migration #27', function () { diff --git a/test/unit/migrations/028-test.js b/test/unit/migrations/028-test.js index dd58b8a42..b352f0a29 100644 --- a/test/unit/migrations/028-test.js +++ b/test/unit/migrations/028-test.js @@ -24,11 +24,11 @@ describe('migration #28', function () { 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(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') + 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() }) .catch(done) diff --git a/test/unit/migrations/029-test.js b/test/unit/migrations/029-test.js index b47bd1b6c..ccde6b4cb 100644 --- a/test/unit/migrations/029-test.js +++ b/test/unit/migrations/029-test.js @@ -22,7 +22,7 @@ describe('storage is migrated successfully where transactions that are submitted migration29.migrate(storage) .then((migratedData) => { const txs = migratedData.data.TransactionController.transactions - const [ txMeta1 ] = txs + const [txMeta1] = txs assert.equal(migratedData.meta.version, 29) assert.equal(txMeta1.status, 'failed', 'old tx is auto failed') diff --git a/test/unit/migrations/030-test.js b/test/unit/migrations/030-test.js index f575e4bcb..6d0271f0d 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.js' +import migrationTemplate from '../../../app/scripts/migrations/030' const storage = { meta: {}, diff --git a/test/unit/migrations/migrator-test.js b/test/unit/migrations/migrator-test.js index c54866ec0..87468d917 100644 --- a/test/unit/migrations/migrator-test.js +++ b/test/unit/migrations/migrator-test.js @@ -3,29 +3,30 @@ 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: (data) => { + migrate: (state) => { // clone the data just like we do in migrations - const clonedData = cloneDeep(data) + const clonedData = cloneDeep(state) clonedData.meta.version = 1 return Promise.resolve(clonedData) }, }, { version: 2, - migrate: (data) => { - const clonedData = cloneDeep(data) + migrate: (state) => { + const clonedData = cloneDeep(state) clonedData.meta.version = 2 return Promise.resolve(clonedData) }, }, { version: 3, - migrate: (data) => { - const clonedData = cloneDeep(data) + migrate: (state) => { + const clonedData = cloneDeep(state) clonedData.meta.version = 3 return Promise.resolve(clonedData) }, @@ -33,8 +34,6 @@ const stubMigrations = [ ] const versionedData = { meta: { version: 0 }, data: { hello: 'world' } } -import data from '../../../app/scripts/first-time-state' - const firstTimeState = { meta: { version: 0 }, data, @@ -50,12 +49,12 @@ describe('migrations', function () { migrationNumbers = fileNames .reduce((acc, filename) => { const name = filename.split('.')[0] - if (/^\d+$/.test(name)) { + if ((/^\d+$/u).test(name)) { acc.push(name) } return acc }, []) - .map((num) => parseInt(num)) + .map((num) => parseInt(num, 10)) }) it('should include all migrations', function () { @@ -70,12 +69,12 @@ describe('migrations', function () { const testNumbers = fileNames .reduce((acc, filename) => { const name = filename.split('-test.')[0] - if (/^\d+$/.test(name)) { + if ((/^\d+$/u).test(name)) { acc.push(name) } return acc }, []) - .map((num) => parseInt(num)) + .map((num) => parseInt(num, 10)) migrationNumbers.forEach((num) => { if (num >= 33) { @@ -86,8 +85,8 @@ describe('migrations', function () { }) describe('Migrator', function () { - const migrator = new Migrator({ migrations: stubMigrations }) 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) }) diff --git a/test/unit/responsive/components/dropdown-test.js b/test/unit/responsive/components/dropdown-test.js index 76258277f..754879aee 100644 --- a/test/unit/responsive/components/dropdown-test.js +++ b/test/unit/responsive/components/dropdown-test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import configureMockStore from 'redux-mock-store' import thunk from 'redux-thunk' import sinon from 'sinon' diff --git a/test/unit/ui/app/actions.spec.js b/test/unit/ui/app/actions.spec.js index 6eb2e6007..8f2dc0bbf 100644 --- a/test/unit/ui/app/actions.spec.js +++ b/test/unit/ui/app/actions.spec.js @@ -12,14 +12,14 @@ import * as actions from '../../../../ui/app/store/actions' import MetaMaskController from '../../../../app/scripts/metamask-controller' import firstTimeState from '../../localhostState' -const provider = createTestProviderTools({ scaffold: {} }).provider +const { provider } = createTestProviderTools({ scaffold: {} }) const middleware = [thunk] const defaultState = { metamask: {} } const mockStore = (state = defaultState) => configureStore(middleware)(state) describe('Actions', function () { - const noop = () => {} + const noop = () => undefined const currentNetworkId = '42' @@ -32,16 +32,17 @@ describe('Actions', function () { beforeEach(async function () { metamaskController = new MetaMaskController({ + platform: { getVersion: () => 'foo' }, provider, keyringController: new KeyringController({}), showUnapprovedTx: noop, showUnconfirmedMessage: noop, encryptor: { - encrypt: function (_, object) { + encrypt (_, object) { this.object = object return Promise.resolve('mock-encrypted') }, - decrypt: function () { + decrypt () { return Promise.resolve(this.object) }, }, @@ -55,7 +56,7 @@ describe('Actions', function () { await metamaskController.createNewVaultAndRestore(password, TEST_SEED) - await metamaskController.importAccountWithStrategy('Private Key', [ importPrivkey ]) + await metamaskController.importAccountWithStrategy('Private Key', [importPrivkey]) background = metamaskController.getApi() @@ -96,7 +97,6 @@ describe('Actions', function () { { type: 'HIDE_LOADING_INDICATION' }, ] - submitPasswordSpy = sinon.stub(background, 'submitPassword') submitPasswordSpy.callsFake((_, callback) => { @@ -113,8 +113,8 @@ describe('Actions', function () { it('displays warning error and unlock failed when verifySeed fails', async function () { const store = mockStore() - 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' }] verifySeedPhraseSpy = sinon.stub(background, 'verifySeedPhrase') verifySeedPhraseSpy.callsFake((callback) => { @@ -337,9 +337,9 @@ describe('Actions', function () { importAccountWithStrategySpy = sinon.spy(background, 'importAccountWithStrategy') - const importPrivkey = 'c87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3' - - await store.dispatch(actions.importNewAccount('Private Key', [ importPrivkey ])) + await store.dispatch(actions.importNewAccount('Private Key', [ + 'c87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3', + ])) assert(importAccountWithStrategySpy.calledOnce) }) @@ -572,7 +572,7 @@ describe('Actions', function () { metamaskMsgs = metamaskController.messageManager.getUnapprovedMsgs() messages = metamaskController.messageManager.messages msgId = Object.keys(metamaskMsgs)[0] - messages[0].msgParams.metamaskId = parseInt(msgId) + messages[0].msgParams.metamaskId = parseInt(msgId, 10) }) afterEach(function () { @@ -625,7 +625,7 @@ describe('Actions', function () { metamaskMsgs = metamaskController.personalMessageManager.getUnapprovedMsgs() personalMessages = metamaskController.personalMessageManager.messages msgId = Object.keys(metamaskMsgs)[0] - personalMessages[0].msgParams.metamaskId = parseInt(msgId) + personalMessages[0].msgParams.metamaskId = parseInt(msgId, 10) }) afterEach(function () { @@ -713,7 +713,7 @@ describe('Actions', function () { messages = metamaskController.typedMessageManager.getUnapprovedMsgs() typedMessages = metamaskController.typedMessageManager.messages msgId = Object.keys(messages)[0] - typedMessages[0].msgParams.metamaskId = parseInt(msgId) + typedMessages[0].msgParams.metamaskId = parseInt(msgId, 10) }) afterEach(function () { @@ -860,7 +860,7 @@ describe('Actions', function () { 'value': '0x0', } - const txData = { id: '1', status: 'unapproved', metamaskNetworkId: currentNetworkId, txParams: txParams } + const txData = { id: '1', status: 'unapproved', metamaskNetworkId: currentNetworkId, txParams } beforeEach(async function () { await metamaskController.txController.txStateManager.addTx(txData) diff --git a/test/unit/ui/app/reducers/app.spec.js b/test/unit/ui/app/reducers/app.spec.js index cd135d220..7ba811cc3 100644 --- a/test/unit/ui/app/reducers/app.spec.js +++ b/test/unit/ui/app/reducers/app.spec.js @@ -122,7 +122,6 @@ describe('App State', function () { type: actions.MODAL_CLOSE, }) - assert.equal(newState.modal.open, false) assert.equal(newState.modal.modalState.name, null) }) @@ -167,6 +166,23 @@ describe('App State', function () { }) + it('clears account details', function () { + const exportPrivKeyModal = { + accountDetail: { + subview: 'export', + accountExport: 'completed', + privateKey: 'a-priv-key', + }, + } + + const state = { ...metamaskState, appState: { ...exportPrivKeyModal } } + const newState = reduceApp(state, { + type: actions.CLEAR_ACCOUNT_DETAILS, + }) + + assert.deepStrictEqual(newState.accountDetail, {}) + }) + it('shoes account page', function () { const state = reduceApp(metamaskState, { type: actions.SHOW_ACCOUNTS_PAGE, diff --git a/test/unit/ui/app/reducers/metamask.spec.js b/test/unit/ui/app/reducers/metamask.spec.js index 3b232c0f6..1a872b14e 100644 --- a/test/unit/ui/app/reducers/metamask.spec.js +++ b/test/unit/ui/app/reducers/metamask.spec.js @@ -209,7 +209,8 @@ describe('MetaMask Reducers', function () { it('clears send', function () { const initStateSend = { send: - { gasLimit: null, + { + gasLimit: null, gasPrice: null, gasTotal: null, tokenBalance: null, @@ -220,7 +221,8 @@ describe('MetaMask Reducers', function () { errors: {}, maxModeOn: false, editingTransactionId: null, - toNickname: '' }, + toNickname: '', + }, } const sendState = { @@ -240,7 +242,6 @@ describe('MetaMask Reducers', function () { }, } - const state = reduceMetamask(sendState, { type: actionConstants.CLEAR_SEND, }) 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 new file mode 100644 index 000000000..7e001f7d6 --- /dev/null +++ b/ui/app/components/app/account-list-item/account-list-item.js @@ -0,0 +1,51 @@ +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, + className, + displayAddress = false, + handleClick, + icon = null, +}) { + const { name, address, balance } = account || {} + + return ( +
handleClick && handleClick({ name, address, balance })} + > + +
+ + +
{ name || address }
+ + {icon &&
{ icon }
} + + +
+ + {displayAddress && name && ( +
+ { checksumAddress(address) } +
+ )} +
+ ) +} + +AccountListItem.propTypes = { + account: PropTypes.object, + className: PropTypes.string, + 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 new file mode 100644 index 000000000..1759f6597 --- /dev/null +++ b/ui/app/components/app/account-list-item/index.js @@ -0,0 +1 @@ +export { default } from './account-list-item' diff --git a/ui/app/components/app/account-list-item/index.scss b/ui/app/components/app/account-list-item/index.scss new file mode 100644 index 000000000..dcc08d9b5 --- /dev/null +++ b/ui/app/components/app/account-list-item/index.scss @@ -0,0 +1,26 @@ +.account-list-item { + &__top-row { + display: flex; + margin-top: 10px; + margin-left: 8px; + position: relative; + } + + &__account-name { + font-size: 16px; + margin-left: 8px; + } + + &__icon { + position: absolute; + right: 12px; + top: 1px; + } + + &__account-address { + margin-left: 35px; + width: 80%; + overflow: hidden; + text-overflow: ellipsis; + } +} diff --git a/ui/app/pages/send/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 similarity index 74% rename from ui/app/pages/send/account-list-item/tests/account-list-item-component.test.js rename to ui/app/components/app/account-list-item/tests/account-list-item-component.test.js index a2949511a..d42bd7bc9 100644 --- a/ui/app/pages/send/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,11 +1,10 @@ -import React from 'react' 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 '../../../../components/ui/identicon' -import UserPreferencedCurrencyDisplay from '../../../../components/app/user-preferenced-currency-display' -import AccountListItem from '../account-list-item.component' +import Identicon from '../../../ui/identicon' +import AccountListItem from '../account-list-item' describe('AccountListItem Component', function () { let wrapper, propsMethodSpies, checksumAddressStub @@ -22,15 +21,11 @@ describe('AccountListItem Component', function () { } /> - ), { context: { t: (str) => str + '_t' } }) + ), { context: { t: (str) => `${str}_t` } }) }) afterEach(function () { @@ -113,36 +108,5 @@ describe('AccountListItem Component', function () { wrapper.setProps({ account: { address: 'someAddressButNoName' } }) assert.equal(wrapper.find('.account-list-item__account-address').length, 0) }) - - it('should render a CurrencyDisplay with the correct props if displayBalance is true', function () { - wrapper.setProps({ displayBalance: true }) - assert.equal(wrapper.find(UserPreferencedCurrencyDisplay).length, 2) - assert.deepEqual( - wrapper.find(UserPreferencedCurrencyDisplay).at(0).props(), - { - type: 'PRIMARY', - value: 'mockBalance', - hideTitle: true, - }, - ) - }) - - it('should only render one CurrencyDisplay if showFiat is false', function () { - wrapper.setProps({ showFiat: false, displayBalance: true }) - assert.equal(wrapper.find(UserPreferencedCurrencyDisplay).length, 1) - assert.deepEqual( - wrapper.find(UserPreferencedCurrencyDisplay).at(0).props(), - { - type: 'PRIMARY', - value: 'mockBalance', - hideTitle: true, - }, - ) - }) - - it('should not render a CurrencyDisplay if displayBalance is false', function () { - wrapper.setProps({ displayBalance: false }) - assert.equal(wrapper.find(UserPreferencedCurrencyDisplay).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 6409a9cd6..ec3f3f7a9 100644 --- a/ui/app/components/app/account-menu/account-menu.component.js +++ b/ui/app/components/app/account-menu/account-menu.component.js @@ -3,8 +3,7 @@ import PropTypes from 'prop-types' import { debounce } from 'lodash' import Fuse from 'fuse.js' import InputAdornment from '@material-ui/core/InputAdornment' - -import { Menu, Item, Divider, CloseArea } from '../dropdowns/components/menu' +import classnames from 'classnames' import { ENVIRONMENT_TYPE_POPUP } from '../../../../../app/scripts/lib/enums' import { getEnvironmentType } from '../../../../../app/scripts/lib/util' import Identicon from '../../ui/identicon' @@ -22,6 +21,42 @@ import { 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 itemClassName = classnames('account-menu__item', className, { + 'account-menu__item--clickable': Boolean(onClick), + }) + return children + ?
{children}
+ : ( +
+ {icon ?
{icon}
: null} + {text ?
{text}
: null} + {subText ?
{subText}
: null} +
+ ) +} + +AccountMenuItem.propTypes = { + icon: PropTypes.node, + children: PropTypes.node, + text: PropTypes.node, + subText: PropTypes.node, + onClick: PropTypes.func, + className: PropTypes.string, +} + export default class AccountMenu extends Component { static contextTypes = { t: PropTypes.func, @@ -106,7 +141,7 @@ export default class AccountMenu extends Component { fullWidth theme="material-white-padded" />, - , +
, ] } @@ -277,13 +312,16 @@ export default class AccountMenu extends Component { history, } = this.props + if (!isAccountMenuOpen) { + return null + } + return ( - - - +
+ { t('myAccounts') } - - + +
{shouldShowAccountsSearch ? this.renderAccountsSearch() : null}
{ this.renderScrollButton() }
- - + { toggleAccountMenu() metricsEvent({ @@ -330,7 +368,7 @@ export default class AccountMenu extends Component { )} text={t('createAccount')} /> - { toggleAccountMenu() metricsEvent({ @@ -350,7 +388,7 @@ export default class AccountMenu extends Component { )} text={t('importAccount')} /> - { toggleAccountMenu() metricsEvent({ @@ -374,8 +412,8 @@ export default class AccountMenu extends Component { )} text={t('connectHardwareWallet')} /> - - + { toggleAccountMenu() history.push(ABOUT_US_ROUTE) @@ -385,7 +423,7 @@ export default class AccountMenu extends Component { } text={t('infoHelp')} /> - { toggleAccountMenu() history.push(SETTINGS_ROUTE) @@ -405,7 +443,7 @@ export default class AccountMenu extends Component { )} text={t('settings')} /> -
+
) } } diff --git a/ui/app/components/app/account-menu/account-menu.container.js b/ui/app/components/app/account-menu/account-menu.container.js index a9739dccc..c08537264 100644 --- a/ui/app/components/app/account-menu/account-menu.container.js +++ b/ui/app/components/app/account-menu/account-menu.container.js @@ -32,7 +32,7 @@ function mapStateToProps (state) { isAccountMenuOpen, addressConnectedDomainMap: getAddressConnectedDomainMap(state), originOfCurrentTab: origin, - selectedAddress: selectedAddress, + selectedAddress, keyrings: getMetaMaskKeyrings(state), accounts, shouldShowAccountsSearch: accounts.length >= SHOW_SEARCH_ACCOUNTS_MIN_COUNT, diff --git a/ui/app/components/app/account-menu/index.scss b/ui/app/components/app/account-menu/index.scss index 8a2a34bc3..94fb24abe 100644 --- a/ui/app/components/app/account-menu/index.scss +++ b/ui/app/components/app/account-menu/index.scss @@ -3,6 +3,11 @@ z-index: 100; top: 58px; width: 320px; + border-radius: 4px; + background: rgba($black, 0.8); + box-shadow: rgba($black, 0.15) 0 2px 2px 2px; + min-width: 150px; + color: $white; @media screen and (max-width: 575px) { right: calc(((100vw - 100%) / 2) + 8px); @@ -20,6 +25,62 @@ right: calc((100vw - 65vw) / 2); } + &__item { + padding: 18px; + display: flex; + flex-flow: row wrap; + align-items: center; + position: relative; + z-index: 201; + + @media screen and (max-width: 575px) { + padding: 14px; + } + + &--clickable { + cursor: pointer; + + &:hover { + background-color: rgba($white, 0.05); + } + + &:active { + background-color: rgba($white, 0.1); + } + } + + &__icon { + height: 16px; + width: 16px; + margin-right: 14px; + } + + &__text { + font-size: 16px; + line-height: 21px; + } + + &__subtext { + font-size: 12px; + padding: 5px 0 0 30px; + } + } + + &__divider { + background-color: $scorpion; + width: 100%; + height: 1px; + } + + &__close-area { + position: fixed; + width: 100%; + height: 100%; + top: 0; + left: 0; + z-index: 100; + } + &__icon { margin-left: 1rem; cursor: pointer; diff --git a/ui/app/components/app/account-menu/tests/account-menu.test.js b/ui/app/components/app/account-menu/tests/account-menu.test.js index f4e5e1062..e0166dd08 100644 --- a/ui/app/components/app/account-menu/tests/account-menu.test.js +++ b/ui/app/components/app/account-menu/tests/account-menu.test.js @@ -1,10 +1,10 @@ -import React from 'react' 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 AccountMenu from '../index' import { Provider } from 'react-redux' +import { mountWithRouter } from '../../../../../../test/lib/render-helpers' +import AccountMenu from '..' describe('Account Menu', function () { diff --git a/ui/app/components/app/account-panel.js b/ui/app/components/app/account-panel.js deleted file mode 100644 index 36517f474..000000000 --- a/ui/app/components/app/account-panel.js +++ /dev/null @@ -1,63 +0,0 @@ -import PropTypes from 'prop-types' -import React, { Component } from 'react' -import Identicon from '../ui/identicon' -import { addressSummary, formatBalance } from '../../helpers/utils/util' - -export default class AccountPanel extends Component { - static propTypes = { - identity: PropTypes.object, - account: PropTypes.object, - isFauceting: PropTypes.bool, - } - - static defaultProps = { - identity: {}, - account: {}, - isFauceting: false, - } - - render () { - const { identity, account, isFauceting } = this.props - - const panelState = { - key: `accountPanel${identity.address}`, - identiconKey: identity.address, - identiconLabel: identity.name || '', - attributes: [ - { - key: 'ADDRESS', - value: addressSummary(identity.address), - }, - balanceOrFaucetingIndication(account, isFauceting), - ], - } - - return ( -
-
- - {panelState.identiconLabel.substring(0, 7) + '...'} -
-
- {panelState.attributes.map((attr, index) => ( -
- - {attr.value} -
- ))} -
-
- ) - } -} - -function balanceOrFaucetingIndication (account) { - return { - key: 'BALANCE', - value: formatBalance(account.balance), - } -} diff --git a/ui/app/components/app/add-token-button/add-token-button.component.js b/ui/app/components/app/add-token-button/add-token-button.component.js index e1a40d563..1ddf2b1ff 100644 --- a/ui/app/components/app/add-token-button/add-token-button.component.js +++ b/ui/app/components/app/add-token-button/add-token-button.component.js @@ -1,11 +1,10 @@ import React from 'react' +import { useHistory } from 'react-router-dom' import { useMetricEvent } from '../../../hooks/useMetricEvent' import { useI18nContext } from '../../../hooks/useI18nContext' -import { useHistory } from 'react-router-dom' import { ADD_TOKEN_ROUTE } from '../../../helpers/constants/routes' import Button from '../../ui/button' - export default function AddTokenButton () { const addTokenEvent = useMetricEvent({ eventOpts: { diff --git a/ui/app/components/app/alerts/alerts.js b/ui/app/components/app/alerts/alerts.js index 5d376494c..72bb4910a 100644 --- a/ui/app/components/app/alerts/alerts.js +++ b/ui/app/components/app/alerts/alerts.js @@ -1,8 +1,8 @@ import React from 'react' import { useSelector } from 'react-redux' -import UnconnectedAccountAlert from './unconnected-account-alert' import { alertIsOpen as unconnectedAccountAlertIsOpen } from '../../../ducks/alerts/unconnected-account' +import UnconnectedAccountAlert from './unconnected-account-alert' const Alerts = () => { const _unconnectedAccountAlertIsOpen = useSelector(unconnectedAccountAlertIsOpen) 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 9d8483648..b56408a48 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 @@ -19,7 +19,7 @@ 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-v2' +import Tooltip from '../../../ui/tooltip' import ConnectedAccountsList from '../../connected-accounts-list' import { useI18nContext } from '../../../../hooks/useI18nContext' diff --git a/ui/app/components/app/index.scss b/ui/app/components/app/app-components.scss similarity index 55% rename from ui/app/components/app/index.scss rename to ui/app/components/app/app-components.scss index 00724f3e2..07eac6ce1 100644 --- a/ui/app/components/app/index.scss +++ b/ui/app/components/app/app-components.scss @@ -1,59 +1,38 @@ +/** Please import your files in alphabetical order **/ +@import 'account-list-item/index'; @import 'account-menu/index'; @import 'add-token-button/index'; @import 'alerts/alerts'; @import 'app-header/index'; @import 'asset-list-item/asset-list-item'; -@import '../ui/breadcrumbs/index'; -@import '../ui/button-group/index'; -@import '../ui/card/index'; @import 'confirm-page-container/index'; -@import '../ui/currency-input/index'; -@import '../ui/currency-display/index'; -@import '../ui/error-message/index'; -@import '../ui/export-text-container/index'; -@import '../ui/identicon/index'; -@import '../ui/menu/menu'; +@import 'connected-accounts-list/index'; +@import 'connected-accounts-permissions/index'; +@import 'connected-sites-list/index'; +@import 'connected-status-indicator/index'; +@import 'gas-customization/gas-modal-page-container/index'; +@import 'gas-customization/gas-price-button-group/index'; +@import 'gas-customization/index'; +@import 'home-notification/index'; @import 'info-box/index'; @import 'menu-bar/index'; @import 'modal/index'; @import 'modals/index'; +@import 'multiple-notifications/index'; @import 'network-display/index'; -@import '../ui/page-container/index'; -@import '../../pages/index'; @import 'permission-page-container/index'; +@import 'permissions-connect-footer/index'; +@import 'permissions-connect-header/index'; @import 'selected-account/index'; -@import '../ui/sender-to-recipient/index'; -@import '../ui/tabs/index'; -@import '../ui/token-balance/index'; +@import 'sidebars/index'; +@import 'signature-request/index'; +@import 'signature-request-original/index'; +@import 'tab-bar/index'; @import 'token-cell/token-cell'; @import 'transaction-activity-log/index'; @import 'transaction-breakdown/index'; -@import 'transaction-list/index'; -@import 'transaction-list-item/index'; @import 'transaction-list-item-details/index'; +@import 'transaction-list-item/index'; +@import 'transaction-list/index'; @import 'transaction-status/index'; -@import 'sidebars/index'; -@import '../ui/unit-input/index'; -@import 'gas-customization/gas-modal-page-container/index'; -@import 'gas-customization/index'; -@import 'gas-customization/gas-price-button-group/index'; -@import '../ui/toggle-button/index'; -@import 'home-notification/index'; -@import 'multiple-notifications/index'; -@import 'signature-request/index'; -@import 'connected-sites-list/index'; -@import 'connected-accounts-list/index'; -@import 'connected-accounts-permissions/index'; -@import '../ui/icon/index'; -@import '../ui/icon-with-fallback/icon-with-fallback'; -@import '../ui/icon-with-label/index'; -@import '../ui/circle-icon/index'; -@import '../ui/alert-circle-icon/index'; -@import './connected-status-indicator/index'; -@import '../ui/check-box/index'; -@import '../ui/dropdown/dropdown'; -@import 'permissions-connect-header/index'; -@import 'permissions-connect-footer/index'; @import 'wallet-overview/index'; -@import '../ui/account-mismatch-warning/index'; -@import '../ui/icon-border/icon-border'; 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 78c425436..955f2f320 100644 --- a/ui/app/components/app/app-header/app-header.container.js +++ b/ui/app/components/app/app-header/app-header.container.js @@ -2,8 +2,8 @@ import { connect } from 'react-redux' import { withRouter } from 'react-router-dom' import { compose } from 'redux' -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 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 0ada978da..76ece07a7 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,9 +1,9 @@ -import React from 'react' 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 '../index' +import AppHeader from '..' describe('App Header', function () { let wrapper @@ -30,7 +30,7 @@ describe('App Header', function () { , { context: { t: (str) => str, - metricsEvent: () => {}, + metricsEvent: () => undefined, }, }, ) @@ -54,8 +54,8 @@ describe('App Header', function () { const network = wrapper.find({ network: 'test' }) network.simulate('click', { - preventDefault: () => {}, - stopPropagation: () => {}, + preventDefault: () => undefined, + stopPropagation: () => undefined, }) assert(props.showNetworkDropdown.calledOnce) @@ -66,8 +66,8 @@ describe('App Header', function () { const network = wrapper.find({ network: 'test' }) network.simulate('click', { - preventDefault: () => {}, - stopPropagation: () => {}, + preventDefault: () => undefined, + stopPropagation: () => undefined, }) assert(props.hideNetworkDropdown.calledOnce) 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 bacae2d3a..e5ff8212f 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,19 +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-v2' +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 { useDispatch } from 'react-redux' import { updateSendToken } from '../../../store/actions' -import { useHistory } from 'react-router-dom' import { SEND_ROUTE } from '../../../helpers/constants/routes' - const AssetListItem = ({ className, 'data-testid': dataTestId, @@ -60,7 +59,7 @@ const AssetListItem = ({ : null const sendTokenButton = useMemo(() => { - if (tokenAddress == null) { + if (tokenAddress === null || tokenAddress === undefined) { return null } return ( diff --git a/ui/app/components/app/asset-list-item/asset-list-item.scss b/ui/app/components/app/asset-list-item/asset-list-item.scss index 9167f7b09..ddc6fd562 100644 --- a/ui/app/components/app/asset-list-item/asset-list-item.scss +++ b/ui/app/components/app/asset-list-item/asset-list-item.scss @@ -17,7 +17,7 @@ margin-left: 8px; } - &__send-token-button { + & &__send-token-button { display: none; text-transform: uppercase; width: fit-content; @@ -33,7 +33,7 @@ display: flex; } - &__send-token-button { + & &__send-token-button { display: inline-block; } diff --git a/ui/app/components/app/asset-list/index.js b/ui/app/components/app/asset-list/index.js index 49abc01fd..47ee5ce9f 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.js' +export { default } from './asset-list' 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 3c8c28612..d431033c3 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,8 +1,8 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import { shallow } from 'enzyme' -import ConfirmDetailRow from '../confirm-detail-row.component.js' import sinon from 'sinon' +import ConfirmDetailRow from '../confirm-detail-row.component' const propsMethodSpies = { onHeaderClick: sinon.spy(), 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 0143df6d1..bf226df7e 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 @@ -2,10 +2,9 @@ import React, { Component } from 'react' import PropTypes from 'prop-types' import classnames from 'classnames' import { Tabs, Tab } from '../../../ui/tabs' -import { ConfirmPageContainerSummary, ConfirmPageContainerWarning } from '.' import ErrorMessage from '../../../ui/error-message' import { PageContainerFooter } from '../../../ui/page-container' - +import { ConfirmPageContainerSummary, ConfirmPageContainerWarning } from '.' export default class ConfirmPageContainerContent extends Component { static propTypes = { @@ -40,9 +39,9 @@ export default class ConfirmPageContainerContent extends Component { if (detailsComponent && dataComponent) { return this.renderTabs() - } else { - return detailsComponent || dataComponent } + return detailsComponent || dataComponent + } renderTabs () { 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 f1f10a797..f2e2c0f2b 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 @@ -11,7 +11,6 @@ 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, showEdit, @@ -30,8 +29,22 @@ export default function ConfirmPageContainerHeader ({ return (
- { !showAccountInHeader + { showAccountInHeader ? ( +
+
+ +
+
+ { shortenAddress(accountAddress) } +
+ +
+ ) + : (
) - : null - } - { showAccountInHeader - ? ( -
-
- -
-
- { shortenAddress(accountAddress) } -
- -
- ) - : null } { !isFullScreen && }
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 898af901e..1208b1f12 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,8 +1,8 @@ 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 { MenuItem } from '../../ui/menu' export default class ConnectedAccountsList extends PureComponent { static contextTypes = { @@ -32,11 +32,12 @@ export default class ConnectedAccountsList extends PureComponent { return new Error( `Warning: Failed prop type: '${propName}' of component '${componentName}' must be a boolean. Received: ${typeof props[propName]}`, ) - } else if (props[propName] && !props['removePermittedAccount']) { + } else if (props[propName] && !props.removePermittedAccount) { return new Error( `Warning: Failed prop type: '${propName}' of component '${componentName}' requires prop 'removePermittedAccount'.`, ) } + return undefined }, } @@ -148,9 +149,9 @@ export default class ConnectedAccountsList extends PureComponent { : null } action={ - address !== selectedAddress - ? this.renderListItemAction(address) - : null + address === selectedAddress + ? null + : this.renderListItemAction(address) } /> ) 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 index 5954565b5..d000aaf7a 100644 --- 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 @@ -13,7 +13,7 @@ export default class ConnectedStatusIndicator extends Component { } static propTypes = { - status: PropTypes.oneOf([ STATUS_CONNECTED, STATUS_CONNECTED_TO_ANOTHER_ACCOUNT, STATUS_NOT_CONNECTED ]), + status: PropTypes.oneOf([STATUS_CONNECTED, STATUS_CONNECTED_TO_ANOTHER_ACCOUNT, STATUS_NOT_CONNECTED]), onClick: PropTypes.func, } 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 index 9cdaea0fa..17034f32d 100644 --- 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 @@ -1,6 +1,5 @@ import { findKey } from 'lodash' import { connect } from 'react-redux' -import ConnectedStatusIndicator from './connected-status-indicator.component' import { STATUS_CONNECTED, STATUS_CONNECTED_TO_ANOTHER_ACCOUNT, @@ -11,7 +10,7 @@ import { getOriginOfCurrentTab, getSelectedAddress, } from '../../../selectors' - +import ConnectedStatusIndicator from './connected-status-indicator.component' const mapStateToProps = (state) => { const selectedAddress = getSelectedAddress(state) 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 b41bfe1c1..0e151d23d 100644 --- a/ui/app/components/app/contact-list/contact-list.component.js +++ b/ui/app/components/app/contact-list/contact-list.component.js @@ -1,5 +1,6 @@ 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 { @@ -37,12 +38,13 @@ export default class ContactList extends PureComponent { /> { showLoadMore && ( -
this.setState({ isShowingAllRecent: true })} > {t('loadMore')} -
+ ) }
@@ -67,9 +69,8 @@ export default class ContactList extends PureComponent { return 1 } else if (letter1 === letter2) { return 0 - } else { - return -1 } + return -1 }) .map(([letter, groupItems]) => ( {children} diff --git a/ui/app/components/app/dropdowns/components/menu.js b/ui/app/components/app/dropdowns/components/menu.js deleted file mode 100644 index 7861ba534..000000000 --- a/ui/app/components/app/dropdowns/components/menu.js +++ /dev/null @@ -1,83 +0,0 @@ -import PropTypes from 'prop-types' -import React from 'react' -import classnames from 'classnames' - -/** - * Menu component - * @returns {Component|null} - */ -export function Menu (props) { - const { className, children, isShowing } = props - return isShowing - ?
{children}
- : null -} - -Menu.defaultProps = { - className: '', - isShowing: false, - children: null, -} - -Menu.propTypes = { - className: PropTypes.string, - children: PropTypes.node, - isShowing: PropTypes.bool, -} - -export function Item (props) { - const { - icon, - children, - text, - subText, - className, - onClick, - } = props - - const itemClassName = classnames('menu__item', className, { - 'menu__item--clickable': Boolean(onClick), - }) - return children - ?
{children}
- : ( -
- {icon ?
{icon}
: null} - {text ?
{text}
: null} - {subText ?
{subText}
: null} -
- ) -} - -Item.defaultProps = { - children: null, - icon: null, - text: null, - subText: null, - className: '', - onClick: null, -} - -Item.propTypes = { - icon: PropTypes.node, - children: PropTypes.node, - text: PropTypes.node, - subText: PropTypes.node, - className: PropTypes.string, - onClick: PropTypes.func, -} - -export function Divider () { - return
-} - -export function CloseArea ({ onClick }) { - return
-} - -CloseArea.propTypes = { - onClick: PropTypes.func.isRequired, -} diff --git a/ui/app/components/app/dropdowns/network-dropdown.js b/ui/app/components/app/dropdowns/network-dropdown.js index e578a8b75..16b645858 100644 --- a/ui/app/components/app/dropdowns/network-dropdown.js +++ b/ui/app/components/app/dropdowns/network-dropdown.js @@ -4,9 +4,9 @@ import { connect } from 'react-redux' import { withRouter } from 'react-router-dom' import { compose } from 'redux' import * as actions from '../../../store/actions' +import { NETWORKS_ROUTE } from '../../../helpers/constants/routes' import { Dropdown, DropdownMenuItem } from './components/dropdown' import NetworkDropdownIcon from './components/network-dropdown-icon' -import { NETWORKS_ROUTE } from '../../../helpers/constants/routes' // classes from nodes of the toggle element. const notToggleElementClassnames = [ @@ -86,7 +86,7 @@ class NetworkDropdown extends Component { renderCustomOption (provider) { const { rpcTarget, type, ticker, nickname } = provider - const network = this.props.network + const { network } = this.props if (type !== 'rpc') { return null @@ -135,45 +135,44 @@ class NetworkDropdown extends Component { if ((rpc === 'http://localhost:8545') || currentRpcTarget) { return null - } else { - const chainId = entry.chainId - return ( - this.props.hideNetworkDropdown()} - onClick={() => this.props.setRpcTarget(rpc, chainId, ticker, nickname)} + } + const { chainId } = entry + return ( + this.props.hideNetworkDropdown()} + onClick={() => this.props.setRpcTarget(rpc, chainId, ticker, nickname)} + style={{ + fontSize: '16px', + lineHeight: '20px', + padding: '12px 0', + }} + > + { + currentRpcTarget + ? + :
✓
+ } + + - { - currentRpcTarget - ? - :
✓
- } - - - {nickname || rpc} - - { - e.stopPropagation() - this.props.delRpcTarget(rpc) - }} - /> -
- ) - } + {nickname || rpc} + + { + e.stopPropagation() + this.props.delRpcTarget(rpc) + }} + /> +
+ ) }) } diff --git a/ui/app/components/app/dropdowns/tests/dropdown.test.js b/ui/app/components/app/dropdowns/tests/dropdown.test.js index b32d1327f..20d736800 100644 --- a/ui/app/components/app/dropdowns/tests/dropdown.test.js +++ b/ui/app/components/app/dropdowns/tests/dropdown.test.js @@ -1,8 +1,8 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import sinon from 'sinon' import { shallow } from 'enzyme' -import { DropdownMenuItem } from '../components/dropdown.js' +import { DropdownMenuItem } from '../components/dropdown' describe('Dropdown', function () { let wrapper diff --git a/ui/app/components/app/dropdowns/tests/menu.test.js b/ui/app/components/app/dropdowns/tests/menu.test.js deleted file mode 100644 index 2291be41d..000000000 --- a/ui/app/components/app/dropdowns/tests/menu.test.js +++ /dev/null @@ -1,69 +0,0 @@ -import React from 'react' -import assert from 'assert' -import sinon from 'sinon' -import { shallow } from 'enzyme' -import { Menu, Item, Divider, CloseArea } from '../components/menu' - -describe('Dropdown Menu Components', function () { - describe('Menu', function () { - it('adds prop className to menu', function () { - const wrapper = shallow( - , - ) - assert.equal(wrapper.find('.menu').prop('className'), 'menu Test Class') - }) - }) - - describe('Item', function () { - let wrapper - const onClickSpy = sinon.spy() - - beforeEach(function () { - wrapper = shallow( - , - ) - }) - - it('add className based on props', function () { - assert.equal(wrapper.find('.menu__item').prop('className'), 'menu__item test foo1 menu__item--clickable') - }) - - it('simulates onClick called', function () { - wrapper.find('.menu__item').prop('onClick')() - assert.equal(onClickSpy.callCount, 1) - }) - - it('adds icon based on icon props', function () { - assert.equal(wrapper.find('.menu__item__icon').text(), 'test icon') - }) - - it('adds html text based on text props', function () { - assert.equal(wrapper.find('.menu__item__text').text(), 'test text') - }) - }) - - describe('Divider', function () { - it('renders menu divider', function () { - const wrapper = shallow() - assert.equal(wrapper.find('.menu__divider').length, 1) - }) - }) - - describe('CloseArea', function () { - it('simulates click', function () { - const onClickSpy = sinon.spy() - const wrapper = shallow(( - - )) - wrapper.prop('onClick')() - assert.ok(onClickSpy.calledOnce) - }) - }) -}) diff --git a/ui/app/components/app/dropdowns/tests/network-dropdown-icon.test.js b/ui/app/components/app/dropdowns/tests/network-dropdown-icon.test.js index 2d1ad59b0..370ed334f 100644 --- a/ui/app/components/app/dropdowns/tests/network-dropdown-icon.test.js +++ b/ui/app/components/app/dropdowns/tests/network-dropdown-icon.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import { shallow } from 'enzyme' import NetworkDropdownIcon from '../components/network-dropdown-icon' 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 04005f19b..5aa458ddb 100644 --- a/ui/app/components/app/dropdowns/tests/network-dropdown.test.js +++ b/ui/app/components/app/dropdowns/tests/network-dropdown.test.js @@ -1,5 +1,5 @@ -import React from 'react' 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' 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 3bf49aca1..a18e0e114 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,8 +1,8 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import sinon from 'sinon' import { mount } from 'enzyme' -import AdvancedTabContent from '../index' +import AdvancedTabContent from '..' describe('Advanced Gas Inputs', function () { let wrapper, clock @@ -29,7 +29,8 @@ describe('Advanced Gas Inputs', function () { context: { t: (str) => str, }, - }) + }, + ) }) afterEach(function () { 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 19e3aa776..91c36f0a4 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 @@ -86,9 +86,9 @@ export default class AdvancedTabContent extends Component { ? (
{ t('liveGasPricePredictions') }
- {!gasEstimatesLoading - ? - : + {gasEstimatesLoading + ? + : }
{ t('slower') } 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 303224d5e..4668ced0b 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,8 +1,8 @@ -import React from 'react' import assert from 'assert' -import shallow from '../../../../../../../lib/shallow-with-context' +import React from 'react' import sinon from 'sinon' -import AdvancedTabContent from '../advanced-tab-content.component.js' +import shallow from '../../../../../../../lib/shallow-with-context' +import AdvancedTabContent from '../advanced-tab-content.component' import GasPriceChart from '../../../gas-price-chart' import Loading from '../../../../../ui/loading-screen' 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 94d22ee4a..5a80e4c98 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 @@ -20,15 +20,15 @@ export default class BasicTabContent extends Component {
{ t('estimatedProcessingTimes') }
{ t('selectAHigherGasFee') }
- {!gasPriceButtonGroupProps.loading - ? ( + {gasPriceButtonGroupProps.loading + ? + : ( ) - : }
{ t('acceleratingATransaction') }
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 2e2e8dab5..f8cec8a0c 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,5 +1,5 @@ -import React from 'react' 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' 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 0af8673d1..c56f705b2 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,6 +1,6 @@ import { connect } from 'react-redux' -import GasModalPageContainer from './gas-modal-page-container.component' import { captureException } from '@sentry/browser' +import { addHexPrefix } from 'ethereumjs-util' import { hideModal, setGasLimit, @@ -63,8 +63,8 @@ import { calcGasTotal, isBalanceSufficient, } from '../../../../pages/send/send.utils' -import { addHexPrefix } from 'ethereumjs-util' import { calcMaxAmount } from '../../../../pages/send/send-content/send-amount-row/amount-max-button/amount-max-button.utils' +import GasModalPageContainer from './gas-modal-page-container.component' const mapStateToProps = (state, ownProps) => { const { currentNetworkTxList, send } = state.metamask @@ -98,7 +98,7 @@ const mapStateToProps = (state, ownProps) => { const newTotalFiat = addHexWEIsToRenderableFiat(value, customGasTotal, currentCurrency, conversionRate) - const hideBasic = state.appState.modal.modalState.props.hideBasic + const { hideBasic } = state.appState.modal.modalState.props const customGasPrice = calcCustomGasPrice(customModalGasPriceInHex) @@ -220,6 +220,7 @@ const mapDispatchToProps = (dispatch) => { const mergeProps = (stateProps, dispatchProps, ownProps) => { const { gasPriceButtonGroupProps, + // eslint-disable-next-line no-shadow isConfirm, txId, isSpeedUp, diff --git a/ui/app/components/app/gas-customization/gas-modal-page-container/index.scss b/ui/app/components/app/gas-customization/gas-modal-page-container/index.scss index 1794a45c1..d8edc10c1 100644 --- a/ui/app/components/app/gas-customization/gas-modal-page-container/index.scss +++ b/ui/app/components/app/gas-customization/gas-modal-page-container/index.scss @@ -34,10 +34,11 @@ font-size: 14px; color: #4eade7; position: absolute; - top: 16px; + top: 4px; right: 16px; cursor: pointer; overflow: hidden; + width: min-content; } &__title { 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 473a651ce..9c8b399fe 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,8 +1,8 @@ -import React from 'react' import assert from 'assert' -import shallow from '../../../../../../lib/shallow-with-context' +import React from 'react' import sinon from 'sinon' -import GasModalPageContainer from '../gas-modal-page-container.component.js' +import shallow from '../../../../../../lib/shallow-with-context' +import GasModalPageContainer from '../gas-modal-page-container.component' import timeout from '../../../../../../lib/test-timeout' import PageContainer from '../../../../ui/page-container' 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 bc2e45ba7..f27d0de52 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 @@ -168,21 +168,18 @@ describe('gas-modal-page-container container', function () { const tests = [ { mockState: baseMockState, expectedResult: baseExpectedResult, mockOwnProps: baseMockOwnProps }, { - mockState: Object.assign({}, baseMockState, { - metamask: { ...baseMockState.metamask, balance: '0xfffffffffffffffffffff' }, - }), - expectedResult: Object.assign({}, baseExpectedResult, { balance: '0xfffffffffffffffffffff', insufficientBalance: false }), + mockState: { ...baseMockState, metamask: { ...baseMockState.metamask, balance: '0xfffffffffffffffffffff' } }, + expectedResult: { ...baseExpectedResult, balance: '0xfffffffffffffffffffff', insufficientBalance: false }, mockOwnProps: baseMockOwnProps, }, { mockState: baseMockState, - mockOwnProps: Object.assign({}, baseMockOwnProps, { - transaction: { id: 34, status: 'submitted' }, - }), - expectedResult: Object.assign({}, baseExpectedResult, { isSpeedUp: true, transaction: { id: 34 } }), + mockOwnProps: { ...baseMockOwnProps, transaction: { id: 34, status: 'submitted' } }, + expectedResult: { ...baseExpectedResult, isSpeedUp: true, transaction: { id: 34 } }, }, { - mockState: Object.assign({}, baseMockState, { + mockState: { + ...baseMockState, metamask: { ...baseMockState.metamask, preferences: { @@ -194,7 +191,7 @@ describe('gas-modal-page-container container', function () { type: 'rinkeby', }, }, - }), + }, mockOwnProps: baseMockOwnProps, expectedResult: { ...baseExpectedResult, @@ -206,7 +203,8 @@ describe('gas-modal-page-container container', function () { }, }, { - mockState: Object.assign({}, baseMockState, { + mockState: { + ...baseMockState, metamask: { ...baseMockState.metamask, preferences: { @@ -218,7 +216,7 @@ describe('gas-modal-page-container container', function () { type: 'rinkeby', }, }, - }), + }, mockOwnProps: baseMockOwnProps, expectedResult: { ...baseExpectedResult, @@ -226,7 +224,8 @@ describe('gas-modal-page-container container', function () { }, }, { - mockState: Object.assign({}, baseMockState, { + mockState: { + ...baseMockState, metamask: { ...baseMockState.metamask, preferences: { @@ -238,7 +237,7 @@ describe('gas-modal-page-container container', function () { type: 'mainnet', }, }, - }), + }, mockOwnProps: baseMockOwnProps, expectedResult: baseExpectedResult, }, @@ -404,7 +403,7 @@ describe('gas-modal-page-container container', function () { }) it('should return the expected props when isConfirm is false', function () { - const result = mergeProps(Object.assign({}, stateProps, { isConfirm: false }), dispatchProps, ownProps) + const result = mergeProps({ ...stateProps, isConfirm: false }, dispatchProps, ownProps) assert.equal(result.isConfirm, false) assert.equal(result.someOtherStateProp, 'baz') @@ -435,7 +434,7 @@ describe('gas-modal-page-container container', function () { }) it('should dispatch the expected actions from obSubmit when isConfirm is false and isSpeedUp is true', function () { - const result = mergeProps(Object.assign({}, stateProps, { isSpeedUp: true, isConfirm: false }), dispatchProps, ownProps) + const result = mergeProps({ ...stateProps, isSpeedUp: true, isConfirm: false }, dispatchProps, ownProps) result.onSubmit() 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 b578ff1ed..77c098983 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 @@ -4,7 +4,6 @@ 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)).isRequired, feeInPrimaryCurrency: PropTypes.string, @@ -89,18 +88,18 @@ export default class GasPriceButtonGroup extends Component { } = this.props return ( - !buttonDataLoading - ? ( + buttonDataLoading + ?
{this.context.t('loading')}
+ : ( - { gasButtonInfo.map((obj, index) => this.renderButton(obj, buttonPropsAndFlags, index)) } + {gasButtonInfo.map((obj, index) => this.renderButton(obj, buttonPropsAndFlags, index))} ) - :
{ this.context.t('loading') }
) } } 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 1ca1c50d0..4cd44066c 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,7 +1,7 @@ -import React from 'react' import assert from 'assert' -import shallow from '../../../../../../lib/shallow-with-context' +import React from 'react' import sinon from 'sinon' +import shallow from '../../../../../../lib/shallow-with-context' import GasPriceButtonGroup from '../gas-price-button-group.component' import ButtonGroup from '../../../../ui/button-group' @@ -41,11 +41,11 @@ describe('GasPriceButtonGroup Component', function () { showCheck: true, } - mockButtonPropsAndFlags = Object.assign({}, { + mockButtonPropsAndFlags = { className: mockGasPriceButtonGroupProps.className, handleGasPriceSelection: mockGasPriceButtonGroupProps.handleGasPriceSelection, showCheck: mockGasPriceButtonGroupProps.showCheck, - }) + } sinon.spy(GasPriceButtonGroup.prototype, 'renderButton') sinon.spy(GasPriceButtonGroup.prototype, 'renderButtonContent') @@ -77,12 +77,12 @@ describe('GasPriceButtonGroup Component', function () { assert.equal(noButtonActiveByDefault, true) }) - function renderButtonArgsTest (i, mockButtonPropsAndFlags) { + function renderButtonArgsTest (i, mockPropsAndFlags) { assert.deepEqual( GasPriceButtonGroup.prototype.renderButton.getCall(i).args, [ - Object.assign({}, mockGasPriceButtonGroupProps.gasButtonInfo[i]), - mockButtonPropsAndFlags, + { ...mockGasPriceButtonGroupProps.gasButtonInfo[i] }, + mockPropsAndFlags, i, ], ) @@ -109,7 +109,7 @@ describe('GasPriceButtonGroup Component', function () { beforeEach(function () { GasPriceButtonGroup.prototype.renderButtonContent.resetHistory() const renderButtonResult = GasPriceButtonGroup.prototype.renderButton( - Object.assign({}, mockGasPriceButtonGroupProps.gasButtonInfo[0]), + { ...mockGasPriceButtonGroupProps.gasButtonInfo[0] }, mockButtonPropsAndFlags, ) wrappedRenderButtonResult = shallow(renderButtonResult) @@ -225,7 +225,6 @@ describe('GasPriceButtonGroup Component', function () { assert.equal(wrappedRenderButtonContentResult.children().length, 5) }) - it('should render no elements if all args passed', function () { const renderButtonContentResult = GasPriceButtonGroup.prototype.renderButtonContent({}, {}) const wrappedRenderButtonContentResult = shallow(renderButtonContentResult) diff --git a/ui/app/components/app/gas-customization/gas-price-chart/gas-price-chart.component.js b/ui/app/components/app/gas-customization/gas-price-chart/gas-price-chart.component.js index 03aa53a9d..ef5f9e074 100644 --- a/ui/app/components/app/gas-customization/gas-price-chart/gas-price-chart.component.js +++ b/ui/app/components/app/gas-customization/gas-price-chart/gas-price-chart.component.js @@ -8,7 +8,7 @@ import { hideDataUI, setTickPosition, handleMouseMove, -} from './gas-price-chart.utils.js' +} from './gas-price-chart.utils' export default class GasPriceChart extends Component { static contextTypes = { diff --git a/ui/app/components/app/gas-customization/gas-price-chart/gas-price-chart.utils.js b/ui/app/components/app/gas-customization/gas-price-chart/gas-price-chart.utils.js index ab948d941..ff6dd9390 100644 --- a/ui/app/components/app/gas-customization/gas-price-chart/gas-price-chart.utils.js +++ b/ui/app/components/app/gas-customization/gas-price-chart/gas-price-chart.utils.js @@ -124,9 +124,10 @@ export function setTickPosition (axis, n, newPosition, secondNewPosition) { .style('visibility', 'visible') } +/* eslint-disable babel/no-invalid-this */ export function appendOrUpdateCircle ({ data, itemIndex, cx, cy, cssId, appendOnly }) { const circle = this.main - .select('.c3-selected-circles' + this.getTargetSelectorSuffix(data.id)) + .select(`.c3-selected-circles${this.getTargetSelectorSuffix(data.id)}`) .selectAll(`.c3-selected-circle-${itemIndex}`) if (appendOnly || circle.empty()) { @@ -144,6 +145,7 @@ export function appendOrUpdateCircle ({ data, itemIndex, cx, cy, cssId, appendOn .attr('cy', cy) } } +/* eslint-enable babel/no-invalid-this */ export function setSelectedCircle ({ chart, @@ -163,7 +165,7 @@ export function setSelectedCircle ({ while (lowerX === higherX) { higherX = getCoordinateData(`.c3-circle-${count}`).x higherY = getCoordinateData(`.c3-circle-${count}`).y - count++ + count += 1 } } @@ -180,7 +182,6 @@ export function setSelectedCircle ({ ) } - export function generateChart (gasPrices, estimatedTimes, gasPricesMax, estimatedTimesMax) { const gasPricesMaxPadded = gasPricesMax + 1 const chart = c3.generate({ @@ -214,8 +215,8 @@ export function generateChart (gasPrices, estimatedTimes, gasPricesMax, estimate tick: { values: [Math.floor(gasPrices[0]), Math.ceil(gasPricesMax)], outer: false, - format: function (val) { - return val + ' GWEI' + format (val) { + return `${val} GWEI` }, }, padding: { left: gasPricesMax / 50, right: gasPricesMax / 50 }, @@ -258,17 +259,17 @@ export function generateChart (gasPrices, estimatedTimes, gasPricesMax, estimate format: { title: (v) => v.toPrecision(4), }, - contents: function (d) { + contents (d) { const titleFormat = this.config.tooltip_format_title let text d.forEach((el) => { if (el && (el.value || el.value === 0) && !text) { - text = "" + "' + text = `
" + titleFormat(el.x) + '
` } }) - return text + '
${titleFormat(el.x)}
' + "
" + return `${text}
` }, - position: function () { + position () { if (d3.select('#overlayed-circle').empty()) { return { top: -100, left: -100 } } @@ -330,7 +331,7 @@ export function generateChart (gasPrices, estimatedTimes, gasPricesMax, estimate const tHeight = this.tooltip.property('offsetHeight') const position = this.config.tooltip_position.call(this, dataToShow, tWidth, tHeight, element) // Set tooltip - this.tooltip.style('top', position.top + 'px').style('left', position.left + 'px') + this.tooltip.style('top', `${position.top}px`).style('left', `${position.left}px`) } } diff --git a/ui/app/components/app/gas-customization/gas-price-chart/index.scss b/ui/app/components/app/gas-customization/gas-price-chart/index.scss index a26b477a0..774760cff 100644 --- a/ui/app/components/app/gas-customization/gas-price-chart/index.scss +++ b/ui/app/components/app/gas-customization/gas-price-chart/index.scss @@ -17,7 +17,6 @@ .tick text, .c3-axis-x-label, .c3-axis-y-label { - font-family: Roboto; font-style: normal; font-weight: bold; line-height: normal; @@ -53,7 +52,6 @@ } .custom-tooltip th { - font-family: Roboto; font-style: normal; font-weight: 500; line-height: normal; diff --git a/ui/app/components/app/gas-customization/gas-price-chart/tests/gas-price-chart.component.test.js b/ui/app/components/app/gas-customization/gas-price-chart/tests/gas-price-chart.component.test.js index ecb5bafa7..d95fa63a1 100644 --- a/ui/app/components/app/gas-customization/gas-price-chart/tests/gas-price-chart.component.test.js +++ b/ui/app/components/app/gas-customization/gas-price-chart/tests/gas-price-chart.component.test.js @@ -1,9 +1,9 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import proxyquire from 'proxyquire' import sinon from 'sinon' -import shallow from '../../../../../../lib/shallow-with-context' import * as d3 from 'd3' +import shallow from '../../../../../../lib/shallow-with-context' function timeout (time) { return new Promise((resolve) => { @@ -69,7 +69,7 @@ describe('GasPriceChart Component', function () { './gas-price-chart.utils.js': gasPriceChartUtilsSpies, 'd3': { ...d3, - select: function (...args) { + select (...args) { const result = d3.select(...args) return result.empty() ? mockSelectReturn diff --git a/ui/app/components/app/home-notification/index.scss b/ui/app/components/app/home-notification/index.scss index 1aedb90ec..56222b454 100644 --- a/ui/app/components/app/home-notification/index.scss +++ b/ui/app/components/app/home-notification/index.scss @@ -35,7 +35,6 @@ } &__text { - font-family: Roboto, 'sans-serif'; font-style: normal; font-weight: normal; font-size: 12px; @@ -112,7 +111,6 @@ } &__content { - font-family: Roboto, 'sans-serif'; font-style: normal; font-weight: normal; font-size: 12px; 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 68aae5d11..163869ef5 100644 --- a/ui/app/components/app/info-box/info-box.component.js +++ b/ui/app/components/app/info-box/info-box.component.js @@ -29,17 +29,17 @@ export default class InfoBox extends Component { render () { const { title, description } = this.props - return !this.state.isShowing - ? null - : ( + return this.state.isShowing + ? (
this.handleClose()} /> -
{ title }
-
{ description }
+
{title}
+
{description}
) + : 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 e04d4ca67..5ad89b4fd 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,9 +1,9 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import sinon from 'sinon' import { shallow } from 'enzyme' -import InfoBox from '../index' +import InfoBox from '..' describe('InfoBox', function () { 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 2b5456e4d..9c348dab7 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,7 +1,7 @@ import { connect } from 'react-redux' -import LoadingNetworkScreen from './loading-network-screen.component' import * as actions from '../../../store/actions' import { getNetworkIdentifier } from '../../../selectors' +import LoadingNetworkScreen from './loading-network-screen.component' const mapStateToProps = (state) => { const { 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 9edf908d4..241f6dc92 100644 --- a/ui/app/components/app/menu-bar/account-options-menu.js +++ b/ui/app/components/app/menu-bar/account-options-menu.js @@ -6,7 +6,7 @@ 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 genAccountLink from '../../../../lib/account-link' +import getAccountLink from '../../../../lib/account-link' import { getCurrentKeyring, getCurrentNetwork, getRpcPrefsForCurrentProvider, getSelectedIdentity } from '../../../selectors' import { useI18nContext } from '../../../hooks/useI18nContext' import { useMetricEvent } from '../../../hooks/useMetricEvent' @@ -51,7 +51,7 @@ export default function AccountOptionsMenu ({ anchorElement, onClose }) { const rpcPrefs = useSelector(getRpcPrefsForCurrentProvider) const selectedIdentity = useSelector(getSelectedIdentity) - const address = selectedIdentity.address + const { address } = selectedIdentity const isRemovable = keyring.type !== 'HD Key Tree' return ( @@ -90,14 +90,14 @@ export default function AccountOptionsMenu ({ anchorElement, onClose }) { { viewOnEtherscanEvent() - global.platform.openTab({ url: genAccountLink(address, network, rpcPrefs) }) + global.platform.openTab({ url: getAccountLink(address, network, rpcPrefs) }) onClose() }} subtitle={ rpcPrefs.blockExplorerUrl ? ( - { rpcPrefs.blockExplorerUrl.match(/^https?:\/\/(.+)/)[1] } + { rpcPrefs.blockExplorerUrl.match(/^https?:\/\/(.+)/u)[1] } ) : null diff --git a/ui/app/components/app/menu-bar/menu-bar.js b/ui/app/components/app/menu-bar/menu-bar.js index 282307f59..8c4f5c8b9 100644 --- a/ui/app/components/app/menu-bar/menu-bar.js +++ b/ui/app/components/app/menu-bar/menu-bar.js @@ -4,13 +4,13 @@ import { useHistory } from 'react-router-dom' import { useSelector } from 'react-redux' import SelectedAccount from '../selected-account' import ConnectedStatusIndicator from '../connected-status-indicator' -import AccountOptionsMenu from './account-options-menu' import { getEnvironmentType } from '../../../../../app/scripts/lib/util' import { ENVIRONMENT_TYPE_POPUP } from '../../../../../app/scripts/lib/enums' 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() 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 e48b23ae6..1212977be 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 React from 'react' 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 '../index' +import MenuBar from '..' const initState = { activeTab: {}, diff --git a/ui/app/components/app/menu-droppo.js b/ui/app/components/app/menu-droppo.js index 7ea66927b..35d7b458e 100644 --- a/ui/app/components/app/menu-droppo.js +++ b/ui/app/components/app/menu-droppo.js @@ -17,7 +17,7 @@ export default class MenuDroppoComponent extends Component { } renderPrimary () { - const isOpen = this.props.isOpen + const { isOpen } = this.props if (!isOpen) { return null } @@ -32,18 +32,15 @@ export default class MenuDroppoComponent extends Component { } manageListeners () { - const isOpen = this.props.isOpen - const onClickOutside = this.props.onClickOutside + const { isOpen, onClickOutside } = this.props if (isOpen) { this.outsideClickHandler = onClickOutside - } else if (isOpen) { - this.outsideClickHandler = null } } globalClickOccurred = (event) => { - const target = event.target + const { target } = event // eslint-disable-next-line react/no-find-dom-node const container = findDOMNode(this) @@ -72,16 +69,16 @@ export default class MenuDroppoComponent extends Component { render () { const { containerClassName = '', style } = this.props const speed = this.props.speed || '300ms' - const useCssTransition = this.props.useCssTransition + const { useCssTransition } = this.props const zIndex = ('zIndex' in this.props) ? this.props.zIndex : 0 this.manageListeners() - const baseStyle = Object.assign( - { position: 'fixed' }, - style, - { zIndex }, - ) + const baseStyle = { + position: 'fixed', + ...style, + zIndex, + } return (
@@ -113,8 +110,8 @@ export default class MenuDroppoComponent extends Component { {this.renderPrimary()} 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 468775797..058727cc2 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,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import { shallow } from 'enzyme' import ModalContent from '../modal-content.component' diff --git a/ui/app/components/app/modal/modal.component.js b/ui/app/components/app/modal/modal.component.js index 6c45160fd..5e2ad00f5 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 Button from '../../ui/button' import classnames from 'classnames' +import Button from '../../ui/button' export default class Modal extends PureComponent { static propTypes = { @@ -63,31 +63,32 @@ export default class Modal extends PureComponent {
{ children }
- { !hideFooter - ? ( -
- { - onCancel && ( - - ) - } - -
- ) - : null + { + hideFooter + ? null + : ( +
+ { + onCancel && ( + + ) + } + +
+ ) }
) 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 83d9a81e7..5dceb4292 100644 --- a/ui/app/components/app/modal/tests/modal.component.test.js +++ b/ui/app/components/app/modal/tests/modal.component.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import { mount, shallow } from 'enzyme' import sinon from 'sinon' import Modal from '../modal.component' @@ -48,10 +48,10 @@ describe('Modal Component', function () { it('should render a modal with different button types', function () { const wrapper = shallow( {}} + onCancel={() => undefined} cancelText="Cancel" cancelType="secondary" - onSubmit={() => {}} + onSubmit={() => undefined} submitText="Submit" submitType="confirm" />, @@ -66,9 +66,9 @@ describe('Modal Component', function () { it('should render a modal with children', function () { const wrapper = shallow( {}} + onCancel={() => undefined} cancelText="Cancel" - onSubmit={() => {}} + onSubmit={() => undefined} submitText="Submit" >
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 fafdd8444..faa910c43 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,7 +1,7 @@ import React, { Component } from 'react' import PropTypes from 'prop-types' import AccountModalContainer from '../account-modal-container' -import genAccountLink from '../../../../../lib/account-link.js' +import getAccountLink from '../../../../../lib/account-link' import QrView from '../../../ui/qr-code' import EditableLabel from '../../../ui/editable-label' import Button from '../../../ui/button' @@ -42,9 +42,9 @@ export default class AccountDetailsModal extends Component { } return ( - + setAccountLabel(address, label)} /> @@ -52,21 +52,21 @@ export default class AccountDetailsModal extends Component { -
+
@@ -75,7 +75,7 @@ export default class AccountDetailsModal extends Component { ? (
@@ -44,6 +46,7 @@ AccountModalContainer.defaultProps = { } AccountModalContainer.propTypes = { + className: PropTypes.string, selectedIdentity: PropTypes.object.isRequired, showBackButton: PropTypes.bool, backButtonAction: PropTypes.func, diff --git a/ui/app/components/app/modals/account-modal-container/index.scss b/ui/app/components/app/modals/account-modal-container/index.scss new file mode 100644 index 000000000..6e553249b --- /dev/null +++ b/ui/app/components/app/modals/account-modal-container/index.scss @@ -0,0 +1,52 @@ +// Account Modal Container +.account-modal { + &__container { + display: flex; + flex-direction: column; + justify-content: flex-start; + align-items: center; + position: relative; + padding: 5px 0 31px 0; + border: 1px solid $silver; + border-radius: 4px; + } + + &__back { + color: $dusty-gray; + position: absolute; + top: 13px; + left: 17px; + cursor: pointer; + display: flex; + align-items: center; + } + + &__back-text { + font-size: 14px; + line-height: 18px; + padding-left: 3px; + } + + &__close { + font-size: 40px; + background-color: transparent; + color: $dusty-gray; + position: absolute; + cursor: pointer; + top: 10px; + right: 12px; + + &::after { + content: '\00D7'; + } + } + + & .identicon { + position: relative; + left: 0; + right: 0; + margin: 0 auto; + top: -32px; + margin-bottom: -32px; + } +} 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 ff3a6ad12..176ac86bc 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,6 +1,6 @@ import { connect } from 'react-redux' -import AddToAddressBookModal from './add-to-addressbook-modal.component' import * as actions from '../../../../store/actions' +import AddToAddressBookModal from './add-to-addressbook-modal.component' function mapStateToProps (state) { return { diff --git a/ui/app/components/app/modals/add-to-addressbook-modal/index.scss b/ui/app/components/app/modals/add-to-addressbook-modal/index.scss index b5e3b9ae7..cb84f30a0 100644 --- a/ui/app/components/app/modals/add-to-addressbook-modal/index.scss +++ b/ui/app/components/app/modals/add-to-addressbook-modal/index.scss @@ -9,7 +9,7 @@ border-bottom: 1px solid $Grey-100; &__header { - @extend %h3; + @include H3; } } 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 ee9bf1d1c..339d34544 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,5 +1,5 @@ -import React from 'react' 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' 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 6bab5ec1f..f13cca550 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,8 +1,8 @@ import React, { PureComponent } from 'react' import PropTypes from 'prop-types' import Modal from '../../modal' -import CancelTransactionGasFee from './cancel-transaction-gas-fee' import { SUBMITTED_STATUS } from '../../../../helpers/constants/transactions' +import CancelTransactionGasFee from './cancel-transaction-gas-fee' export default class CancelTransaction extends PureComponent { static contextTypes = { @@ -26,7 +26,6 @@ export default class CancelTransaction extends PureComponent { if (transactionStatus !== SUBMITTED_STATUS) { showTransactionConfirmedModal() - 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 0f2a8593a..9645a5df1 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 @@ -3,9 +3,9 @@ import { compose } from 'redux' import ethUtil from 'ethereumjs-util' import { multiplyCurrencies } from '../../../../helpers/utils/conversion-util' import withModalProps from '../../../../helpers/higher-order-components/with-modal-props' -import CancelTransaction from './cancel-transaction.component' import { showModal, createCancelTransaction } from '../../../../store/actions' import { getHexGasTotal } from '../../../../helpers/utils/confirm-tx.util' +import CancelTransaction from './cancel-transaction.component' const mapStateToProps = (state, ownProps) => { const { metamask } = state @@ -44,6 +44,7 @@ const mapDispatchToProps = (dispatch) => { const mergeProps = (stateProps, dispatchProps, ownProps) => { const { transactionId, defaultNewGasPrice, ...restStateProps } = stateProps + // eslint-disable-next-line no-shadow const { createCancelTransaction, ...restDispatchProps } = dispatchProps return { 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 416b796bc..aaa87c21b 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,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import { shallow } from 'enzyme' import sinon from 'sinon' import CancelTransaction from '../cancel-transaction.component' @@ -34,7 +34,7 @@ describe('CancelTransaction Component', function () { defaultNewGasPrice="0x3b9aca00" createCancelTransaction={createCancelTransactionSpy} hideModal={hideModalSpy} - showTransactionConfirmedModal={() => {}} + showTransactionConfirmedModal={() => undefined} />, { context: { t } }, ) 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 ca8011d0d..b6a5c99f5 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,8 +1,8 @@ import { connect } from 'react-redux' import { compose } from 'redux' import withModalProps from '../../../../helpers/higher-order-components/with-modal-props' -import ConfirmDeleteNetwork from './confirm-delete-network.component' import { delRpcTarget } from '../../../../store/actions' +import ConfirmDeleteNetwork from './confirm-delete-network.component' const mapDispatchToProps = (dispatch) => { return { 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 f4f85d589..adf8de80a 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,8 +1,8 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import sinon from 'sinon' import { mount } from 'enzyme' -import ConfirmDeleteNetwork from '../index' +import ConfirmDeleteNetwork from '..' describe('Confirm Delete Network', function () { let wrapper 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 12d652514..4258d9462 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 @@ -3,7 +3,7 @@ import PropTypes from 'prop-types' import Modal from '../../modal' import { addressSummary } from '../../../../helpers/utils/util' import Identicon from '../../../ui/identicon' -import genAccountLink from '../../../../../lib/account-link' +import getAccountLink from '../../../../../lib/account-link' export default class ConfirmRemoveAccount extends Component { static propTypes = { @@ -47,7 +47,7 @@ export default class ConfirmRemoveAccount extends Component {
{ return { 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 c380e06da..12f6d3655 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,11 +1,11 @@ +import assert from 'assert' import React from 'react' import PropTypes from 'prop-types' import { Provider } from 'react-redux' -import assert from 'assert' import sinon from 'sinon' import configureStore from 'redux-mock-store' import { mount } from 'enzyme' -import ConfirmRemoveAccount from '../index' +import ConfirmRemoveAccount from '..' describe('Confirm Remove Account', function () { let wrapper @@ -26,7 +26,6 @@ describe('Confirm Remove Account', function () { }, } - const mockStore = configureStore() const store = mockStore(state) 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 6ef230f41..fcbcb9c7a 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,8 +1,8 @@ import { connect } from 'react-redux' import { compose } from 'redux' import withModalProps from '../../../../helpers/higher-order-components/with-modal-props' -import ConfirmResetAccount from './confirm-reset-account.component' import { resetAccount } from '../../../../store/actions' +import ConfirmResetAccount from './confirm-reset-account.component' const mapDispatchToProps = (dispatch) => { return { 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 be27151f1..005993059 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,8 +1,8 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import sinon from 'sinon' import { mount } from 'enzyme' -import ConfirmResetAccount from '../index' +import ConfirmResetAccount from '..' describe('Confirm Reset Account', function () { let wrapper 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 5c7c8caec..7217ac21e 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 @@ -30,5 +30,4 @@ function mapDispatchToProps (dispatch) { } } - export default connect(mapStateToProps, mapDispatchToProps)(DepositEtherModal) diff --git a/ui/app/components/app/modals/deposit-ether-modal/index.scss b/ui/app/components/app/modals/deposit-ether-modal/index.scss new file mode 100644 index 000000000..c52e4e563 --- /dev/null +++ b/ui/app/components/app/modals/deposit-ether-modal/index.scss @@ -0,0 +1,162 @@ +.deposit-ether-modal { + border-radius: 8px; + display: flex; + flex-flow: column; + height: 100%; + + &__header { + width: 100%; + border-radius: 8px 8px 0 0; + background-color: $mid-gray; + display: flex; + position: relative; + padding: 25px; + flex-flow: column; + align-items: flex-start; + + &__title { + color: $white; + font-size: 24px; + line-height: 32px; + } + + &__description { + color: $white; + font-size: 16px; + line-height: 22px; + margin-top: 10px; + } + + &__close::after { + content: '\00D7'; + font-size: 2em; + color: $white; + position: absolute; + top: 20.8px; + right: 28px; + cursor: pointer; + } + } + + &__buy-rows { + width: 100%; + padding: 0 30px; + display: flex; + flex-flow: column nowrap; + flex: 1; + align-items: center; + + @media screen and (max-width: 575px) { + height: 0; + } + } + + &__logo { + height: 60px; + background-repeat: no-repeat; + background-size: contain; + background-position: center; + width: 100%; + display: flex; + justify-content: center; + align-items: center; + } + + &__buy-row { + border-bottom: 1px solid $alto; + display: flex; + justify-content: space-between; + align-items: center; + flex: 1 0 auto; + padding: 30px 0 20px; + min-height: 170px; + + @media screen and (max-width: 575px) { + min-height: 270px; + flex-flow: column; + justify-content: flex-start; + } + + &__back { + position: absolute; + top: 10px; + left: 0; + } + + &__logo-container { + display: flex; + justify-content: center; + flex: 0 0 auto; + padding: 0 20px; + + @media screen and (min-width: 576px) { + width: 12rem; + } + + @media screen and (max-width: 575px) { + width: 100%; + max-height: 6rem; + padding-bottom: 20px; + } + } + + &__right { + display: flex; + } + + &__description { + color: $cape-cod; + padding-bottom: 20px; + align-self: flex-start; + + @media screen and (min-width: 575px) { + width: 15rem; + } + + &__title { + font-size: 20px; + line-height: 30px; + } + + &__text { + font-size: 14px; + line-height: 22px; + margin-top: 7px; + } + } + + &__button { + display: flex; + justify-content: flex-end; + + @media screen and (min-width: 575px) { + min-width: 300px; + } + } + } + + &__buy-row:last-of-type { + border-bottom: 0; + } + + &__deposit-button { + width: 257px; + } + + .simple-dropdown { + color: #5b5d67; + font-size: 16px; + line-height: 21px; + border: 1px solid #d8d8d8; + background-color: #fff; + text-align: center; + width: 100%; + height: 45px; + line-height: 44px; + font-weight: 300; + } + + .simple-dropdown__selected { + text-align: center; + } +} 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 3d134d9b8..9354dad2c 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,12 +1,12 @@ 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 classnames from 'classnames' -import BigNumber from 'bignumber.js' const MAX_UNSIGNED_256_INT = new BigNumber(2).pow(256).minus(1).toString(10) @@ -167,7 +167,7 @@ export default class EditApprovalPermission extends PureComponent { const { selectedOptionIsUnlimited, customSpendLimit } = this.state if (selectedOptionIsUnlimited || !customSpendLimit) { - return + return undefined } let customSpendLimitNumber @@ -186,6 +186,8 @@ export default class EditApprovalPermission extends PureComponent { if (customSpendLimitNumber.greaterThan(maxTokenAmount)) { return t('spendLimitTooLarge') } + + return undefined } render () { @@ -202,7 +204,7 @@ export default class EditApprovalPermission extends PureComponent { return ( { - setCustomAmount(!selectedOptionIsUnlimited ? customSpendLimit : '') + setCustomAmount(selectedOptionIsUnlimited ? '' : customSpendLimit) hideModal() }} submitText={t('save')} 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 357d70ef2..671d99cf6 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,8 +1,8 @@ import { connect } from 'react-redux' import { compose } from 'redux' import withModalProps from '../../../../helpers/higher-order-components/with-modal-props' -import EditApprovalPermission from './edit-approval-permission.component' import { getSelectedIdentity } from '../../../../selectors' +import EditApprovalPermission from './edit-approval-permission.component' const mapStateToProps = (state) => { const modalStateProps = state.appState.modal.modalState.props || {} 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 695762b73..965d5a703 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 @@ -25,6 +25,7 @@ export default class ExportPrivateKeyModal extends Component { warning: PropTypes.node, showAccountDetailModal: PropTypes.func.isRequired, hideModal: PropTypes.func.isRequired, + clearAccountDetails: PropTypes.func.isRequired, previousModalState: PropTypes.string, } @@ -34,6 +35,10 @@ export default class ExportPrivateKeyModal extends Component { showWarning: true, } + componentWillUnmount () { + this.props.clearAccountDetails() + } + exportAccountAndGetPrivateKey = (password, address) => { const { exportAccount } = this.props @@ -47,7 +52,7 @@ export default class ExportPrivateKeyModal extends Component { renderPasswordLabel (privateKey) { return ( - + { privateKey ? this.context.t('copyPrivateKey') @@ -64,7 +69,7 @@ export default class ExportPrivateKeyModal extends Component { return ( this.setState({ password: event.target.value })} /> ) @@ -72,8 +77,8 @@ export default class ExportPrivateKeyModal extends Component { return ( copyToClipboard(plainKey)} @@ -83,12 +88,12 @@ export default class ExportPrivateKeyModal extends Component { renderButtons (privateKey, address, hideModal) { return ( -
+
{!privateKey && ( @@ -111,7 +116,7 @@ export default class ExportPrivateKeyModal extends Component { onClick={() => this.exportAccountAndGetPrivateKey(this.state.password, address)} type="secondary" large - className="export-private-key__button" + className="export-private-key-modal__button" disabled={!this.state.password} > {this.context.t('confirm')} @@ -139,28 +144,28 @@ export default class ExportPrivateKeyModal extends Component { return ( showAccountDetailModal()} > - {name} + {name} -
- {this.context.t('showPrivateKeys')} -
+
+ {this.context.t('showPrivateKeys')} +
{this.renderPasswordLabel(privateKey)} {this.renderPasswordInput(privateKey)} { (showWarning && warning) - ? {warning} + ? {warning} : null }
-
{this.context.t('privateKeyWarning')}
+
{this.context.t('privateKeyWarning')}
{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 313729217..e1676f8be 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,5 +1,5 @@ import { connect } from 'react-redux' -import { exportAccount, hideWarning, showModal, hideModal } from '../../../../store/actions' +import { exportAccount, hideWarning, showModal, hideModal, clearAccountDetails } from '../../../../store/actions' import { getSelectedIdentity } from '../../../../selectors' import ExportPrivateKeyModal from './export-private-key-modal.component' @@ -32,6 +32,7 @@ function mapDispatchToProps (dispatch) { }, showAccountDetailModal: () => dispatch(showModal({ name: 'ACCOUNT_DETAILS' })), hideModal: () => dispatch(hideModal()), + clearAccountDetails: () => dispatch(clearAccountDetails()), } } diff --git a/ui/app/components/app/modals/export-private-key-modal/index.scss b/ui/app/components/app/modals/export-private-key-modal/index.scss new file mode 100644 index 000000000..8fd3c3133 --- /dev/null +++ b/ui/app/components/app/modals/export-private-key-modal/index.scss @@ -0,0 +1,106 @@ +.export-private-key-modal { + &__body-title { + margin-top: 16px; + margin-bottom: 16px; + font-size: 18px; + } + + &__divider { + width: 100%; + height: 1px; + margin: 19px 0 8px 0; + background-color: $alto; + } + + &__account-name { + margin-top: 9px; + font-size: 20px; + } + + &__password { + display: flex; + flex-direction: column; + } + + &__password-label, + &__password--error { + color: $scorpion; + font-size: 14px; + line-height: 18px; + margin-bottom: 10px; + } + + &__password--error { + color: $crimson; + margin-bottom: 0; + } + + &__password-input { + padding: 10px 0 13px 17px; + font-size: 16px; + line-height: 21px; + width: 291px; + height: 44px; + } + + &__password::-webkit-input-placeholder { + color: $dusty-gray; + } + + &__password--warning { + border-radius: 8px; + background-color: #fff6f6; + font-size: 12px; + font-weight: 500; + line-height: 15px; + color: $crimson; + width: 292px; + padding: 9px 15px; + margin-top: 18px; + } + + &__password-display-wrapper { + height: 80px; + width: 291px; + border: 1px solid $silver; + border-radius: 2px; + } + + &__password-display-textarea { + color: $crimson; + font-size: 16px; + line-height: 21px; + border: none; + height: 75px; + width: 100%; + overflow: hidden; + resize: none; + padding: 9px 13px 8px; + } + + &__buttons { + display: flex; + flex-direction: row; + justify-content: center; + } + + &__button { + margin-top: 17px; + width: 141px; + min-width: initial; + } + + &__button--cancel { + margin-right: 15px; + } + + & .ellip-address-wrapper { + display: flex; + justify-content: center; + border: 1px solid $alto; + padding: 5px 10px; + margin-top: 7px; + width: 286px; + } +} + diff --git a/ui/app/components/app/modals/fade-modal.js b/ui/app/components/app/modals/fade-modal.js index a59c8995b..72d1c7288 100644 --- a/ui/app/components/app/modals/fade-modal.js +++ b/ui/app/components/app/modals/fade-modal.js @@ -14,22 +14,22 @@ const insertRule = (css) => { extraSheet = extraSheet.sheet || extraSheet.styleSheet } - const index = (extraSheet.cssRules || extraSheet.rules).length - extraSheet.insertRule(css, index) + extraSheet.insertRule(css, (extraSheet.cssRules || extraSheet.rules).length) return extraSheet } const insertKeyframesRule = (keyframes) => { // random name - const name = 'anim_' + (++index) + (+new Date()) - let css = '@' + 'keyframes ' + name + ' {' + // eslint-disable-next-line no-plusplus + 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] + ';' + const part = `:${keyframes[key][property]};` css += property + part }) @@ -133,8 +133,8 @@ class FadeModal extends Component { } static defaultProps = { - onShow: function () {}, - onHide: function () {}, + onShow: () => undefined, + onHide: () => undefined, keyboard: true, backdrop: true, closeOnClick: true, @@ -179,20 +179,20 @@ class FadeModal extends Component { const { willHide } = this.state const { modalStyle } = this.props - const backdropStyle = Object.assign({}, { + const backdropStyle = { animationName: willHide ? animation.hideBackdropAnimation : animation.showBackdropAnimation, - animationTimingFunction: (willHide ? animation.hide : animation.show).animationTimingFunction, - }, this.props.backdropStyle) - const contentStyle = Object.assign({}, { + animationTimingFunction: (willHide ? animation.hide : animation.show).animationTimingFunction, ...this.props.backdropStyle, + } + const contentStyle = { animationDuration: (willHide ? animation.hide : animation.show).animationDuration, animationName: willHide ? animation.hideContentAnimation : animation.showContentAnimation, - animationTimingFunction: (willHide ? animation.hide : animation.show).animationTimingFunction, - }, this.props.contentStyle) + animationTimingFunction: (willHide ? animation.hide : animation.show).animationTimingFunction, ...this.props.contentStyle, + } const backdrop = this.props.backdrop ? (
(this.content = el)} tabIndex="-1" style={contentStyle} diff --git a/ui/app/components/app/modals/hide-token-confirmation-modal.js b/ui/app/components/app/modals/hide-token-confirmation-modal/hide-token-confirmation-modal.js similarity index 84% rename from ui/app/components/app/modals/hide-token-confirmation-modal.js rename to ui/app/components/app/modals/hide-token-confirmation-modal/hide-token-confirmation-modal.js index 5f8e6001a..57a0bdc01 100644 --- a/ui/app/components/app/modals/hide-token-confirmation-modal.js +++ b/ui/app/components/app/modals/hide-token-confirmation-modal/hide-token-confirmation-modal.js @@ -1,8 +1,9 @@ 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 * as actions from '../../../../store/actions' +import Identicon from '../../../ui/identicon' +import Button from '../../../ui/button' function mapStateToProps (state) { return { @@ -63,20 +64,22 @@ class HideTokenConfirmationModal extends Component { {this.context.t('readdToken')}
- - +
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 new file mode 100644 index 000000000..31e866398 --- /dev/null +++ b/ui/app/components/app/modals/hide-token-confirmation-modal/index.js @@ -0,0 +1 @@ +export { default } from './hide-token-confirmation-modal' diff --git a/ui/app/components/app/modals/hide-token-confirmation-modal/index.scss b/ui/app/components/app/modals/hide-token-confirmation-modal/index.scss new file mode 100644 index 000000000..9482caeba --- /dev/null +++ b/ui/app/components/app/modals/hide-token-confirmation-modal/index.scss @@ -0,0 +1,56 @@ +.hide-token-confirmation { + min-height: 250.72px; + border-radius: 4px; + background-color: $white; + box-shadow: 0 1px 7px 0 rgba(0, 0, 0, 0.5); + + &__container { + padding: 24px 27px 21px; + display: flex; + flex-direction: column; + align-items: center; + } + + &__identicon { + margin-bottom: 10px; + } + + &__symbol { + color: $tundora; + font-size: 16px; + line-height: 24px; + text-align: center; + margin-bottom: 7.5px; + } + + &__title { + height: 30px; + width: 271.28px; + color: $tundora; + font-size: 22px; + line-height: 30px; + text-align: center; + margin-bottom: 10.5px; + } + + &__copy { + height: 41px; + width: 318px; + color: $scorpion; + font-size: 14px; + line-height: 18px; + text-align: center; + } + + &__buttons { + display: flex; + flex-direction: row; + justify-content: center; + margin-top: 15px; + width: 100%; + } + + &__button { + margin: 0 5px; + } +} diff --git a/ui/app/components/app/modals/index.scss b/ui/app/components/app/modals/index.scss index ebb662b96..b6232aa16 100644 --- a/ui/app/components/app/modals/index.scss +++ b/ui/app/components/app/modals/index.scss @@ -1,8 +1,46 @@ +@import 'account-details-modal/index'; +@import 'account-modal-container/index'; +@import 'add-to-addressbook-modal/index'; @import 'cancel-transaction/index'; @import 'confirm-remove-account/index'; +@import 'deposit-ether-modal/index'; +@import 'edit-approval-permission/index'; +@import 'export-private-key-modal/index'; +@import 'hide-token-confirmation-modal/index'; +@import 'metametrics-opt-in-modal/index'; +@import 'new-account-modal/index'; +@import 'notification-modal/index'; @import 'qr-scanner/index'; @import 'transaction-confirmed/index'; -@import 'metametrics-opt-in-modal/index'; -@import './add-to-addressbook-modal/index'; -@import './edit-approval-permission/index'; -@import './new-account-modal/index'; + +.modal { + z-index: 1050; + position: fixed; + width: 500px; + transform: translate3d(-50%, -50%, 0); + top: 50%; + left: 50%; + + &__content { + margin: 0; + background-color: white; + animation-fill-mode: forwards; + } + + &__backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1040; + background-color: #373a47; + animation-fill-mode: forwards; + animation-duration: 0.3s; + } + + & > div:focus { + outline: none !important; + } +} + 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 38ea9b2ab..765cdf9c5 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 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) 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 c3e6fd8b3..8cef4a076 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,8 +1,8 @@ import { connect } from 'react-redux' import { compose } from 'redux' -import MetaMetricsOptInModal from './metametrics-opt-in-modal.component' 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 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 70e7d9924..bd39976b3 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,8 +1,8 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import sinon from 'sinon' import { mount } from 'enzyme' -import MetaMetricsOptIn from '../index' +import MetaMetricsOptIn from '..' describe('MetaMetrics Opt In', function () { let wrapper @@ -17,7 +17,7 @@ describe('MetaMetrics Opt In', function () { wrapper = mount( , { context: { - metricsEvent: () => {}, + metricsEvent: () => undefined, }, }, ) diff --git a/ui/app/components/app/modals/modal.js b/ui/app/components/app/modals/modal.js index 812090f10..d8e6ef214 100644 --- a/ui/app/components/app/modals/modal.js +++ b/ui/app/components/app/modals/modal.js @@ -9,6 +9,7 @@ import { getEnvironmentType } from '../../../../../app/scripts/lib/util' import { ENVIRONMENT_TYPE_POPUP } from '../../../../../app/scripts/lib/enums' // Modal Components +import ConfirmCustomizeGasModal from '../gas-customization/gas-modal-page-container' import DepositEtherModal from './deposit-ether-modal' import AccountDetailsModal from './account-details-modal' import ExportPrivateKeyModal from './export-private-key-modal' @@ -24,7 +25,6 @@ import CancelTransaction from './cancel-transaction' import FadeModal from './fade-modal' import MetaMetricsOptInModal from './metametrics-opt-in-modal' import RejectTransactions from './reject-transactions' -import ConfirmCustomizeGasModal from '../gas-customization/gas-modal-page-container' import ConfirmDeleteNetwork from './confirm-delete-network' import AddToAddressBookModal from './add-to-addressbook-modal' import EditApprovalPermission from './edit-approval-permission' diff --git a/ui/app/components/app/modals/new-account-modal/index.scss b/ui/app/components/app/modals/new-account-modal/index.scss index 31dfff92d..bbe440041 100644 --- a/ui/app/components/app/modals/new-account-modal/index.scss +++ b/ui/app/components/app/modals/new-account-modal/index.scss @@ -9,7 +9,7 @@ border-bottom: 1px solid $Grey-100; &__header { - @extend %header--18; + @include H4; font-weight: bold; display: flex; 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 adda14d37..c787af9a0 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,6 +1,6 @@ import { connect } from 'react-redux' -import NewAccountModal from './new-account-modal.component' import * as actions from '../../../../store/actions' +import NewAccountModal from './new-account-modal.component' function mapStateToProps (state) { return { diff --git a/ui/app/components/app/modals/notification-modal/index.js b/ui/app/components/app/modals/notification-modal/index.js new file mode 100644 index 000000000..a2aab7c1d --- /dev/null +++ b/ui/app/components/app/modals/notification-modal/index.js @@ -0,0 +1 @@ +export { default } from './notification-modal' diff --git a/ui/app/components/app/modals/notification-modal/index.scss b/ui/app/components/app/modals/notification-modal/index.scss new file mode 100644 index 000000000..93e085496 --- /dev/null +++ b/ui/app/components/app/modals/notification-modal/index.scss @@ -0,0 +1,56 @@ +.notification-modal { + &__wrapper { + display: flex; + flex-direction: column; + justify-content: flex-start; + align-items: center; + position: relative; + border: 1px solid $alto; + box-shadow: 0 0 2px 2px $alto; + } + + &__header { + background: $wild-sand; + width: 100%; + display: flex; + justify-content: center; + padding: 30px; + font-size: 22px; + color: $nile-blue; + } + + &__message { + padding: 20px; + width: 100%; + display: flex; + justify-content: center; + font-size: 17px; + color: $nile-blue; + } + + &__buttons { + display: flex; + justify-content: space-evenly; + width: 100%; + margin-bottom: 24px; + padding: 0 42px; + + &__btn { + cursor: pointer; + } + } + + &__link { + color: $primary-blue; + } + + .modal-close-x::after { + content: '\00D7'; + font-size: 2em; + color: $dusty-gray; + position: absolute; + top: 25px; + right: 17.5px; + cursor: pointer; + } +} diff --git a/ui/app/components/app/modals/notification-modal.js b/ui/app/components/app/modals/notification-modal/notification-modal.js similarity index 95% rename from ui/app/components/app/modals/notification-modal.js rename to ui/app/components/app/modals/notification-modal/notification-modal.js index 7fe776934..2cda61428 100644 --- a/ui/app/components/app/modals/notification-modal.js +++ b/ui/app/components/app/modals/notification-modal/notification-modal.js @@ -1,7 +1,7 @@ import PropTypes from 'prop-types' import React, { Component } from 'react' import { connect } from 'react-redux' -import { hideModal } from '../../../store/actions' +import { hideModal } from '../../../../store/actions' class NotificationModal extends Component { static contextProps = { @@ -14,6 +14,7 @@ class NotificationModal extends Component { message, showCancelButton = false, showConfirmButton = false, + // eslint-disable-next-line no-shadow hideModal, onConfirm, } = this.props 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 63ca45b88..d78db3d14 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 @@ -117,11 +117,11 @@ export default class QrScanner extends Component { const result = this.parseContent(content.text) if (!this.mounted) { return - } else if (result.type !== 'unknown') { + } else if (result.type === 'unknown') { + this.setState({ error: new Error(this.context.t('unknownQrCode')) }) + } else { this.props.qrCodeDetected(result) this.stopAndClose() - } else { - this.setState({ error: new Error(this.context.t('unknownQrCode')) }) } } catch (error) { if (!this.mounted) { @@ -144,7 +144,6 @@ export default class QrScanner extends Component { // To parse other type of links // For ex. EIP-681 (https://eips.ethereum.org/EIPS/eip-681) - // Ethereum address links - fox ex. ethereum:0x.....1111 if (content.split('ethereum:').length > 1) { @@ -161,7 +160,6 @@ export default class QrScanner extends Component { return { type, values } } - stopAndClose = () => { if (this.codeReader) { this.codeReader.reset() @@ -248,7 +246,7 @@ export default class QrScanner extends Component { display: ready === READY_STATE.READY ? 'block' : 'none', }} /> - { ready !== READY_STATE.READY ? : null} + {ready === READY_STATE.READY ? null : }
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 b7fce7523..98472c6ea 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,7 +1,6 @@ import { connect } from 'react-redux' -import QrScanner from './qr-scanner.component' - import { hideModal, qrCodeDetected } from '../../../../store/actions' +import QrScanner from './qr-scanner.component' const mapDispatchToProps = (dispatch) => { 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 72eddbc8b..08061a48d 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,7 +1,7 @@ import { connect } from 'react-redux' import { compose } from 'redux' -import RejectTransactionsModal from './reject-transactions.component' import withModalProps from '../../../../helpers/higher-order-components/with-modal-props' +import RejectTransactionsModal from './reject-transactions.component' const mapStateToProps = (_, ownProps) => { const { unapprovedTxCount } = ownProps 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 d7623604e..1d8a1df68 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,8 +1,8 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import sinon from 'sinon' import { mount } from 'enzyme' -import RejectTransactionsModal from '../index' +import RejectTransactionsModal from '..' describe('Reject Transactions Model', function () { let wrapper 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 3c0dd8f25..cc2dabdf2 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,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import sinon from 'sinon' import { shallow } from 'enzyme' import AccountDetailsModal from '../account-details-modal' @@ -46,7 +46,7 @@ describe('Account Details Modal', function () { }) it('sets account label when changing default account label', function () { - const accountLabel = wrapper.find('.account-modal__name').first() + const accountLabel = wrapper.find('.account-details-modal__name').first() accountLabel.simulate('submit', 'New Label') assert(props.setAccountLabel.calledOnce) @@ -54,7 +54,7 @@ describe('Account Details Modal', function () { }) it('opens new tab when view block explorer is clicked', function () { - const modalButton = wrapper.find('.account-modal__button') + const modalButton = wrapper.find('.account-details-modal__button') const etherscanLink = modalButton.first() etherscanLink.simulate('click') @@ -62,7 +62,7 @@ describe('Account Details Modal', function () { }) it('shows export private key modal when clicked', function () { - const modalButton = wrapper.find('.account-modal__button') + const modalButton = wrapper.find('.account-details-modal__button') const etherscanLink = modalButton.last() etherscanLink.simulate('click') @@ -73,9 +73,9 @@ describe('Account Details Modal', function () { const blockExplorerUrl = 'https://block.explorer' wrapper.setProps({ rpcPrefs: { blockExplorerUrl } }) - const modalButton = wrapper.find('.account-modal__button') + const modalButton = wrapper.find('.account-details-modal__button') const blockExplorerLink = modalButton.first() - assert.equal(blockExplorerLink.html(), '') + assert.equal(blockExplorerLink.html(), '') }) }) 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 47b653dd7..971ed324c 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,8 +1,8 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import sinon from 'sinon' import { mount } from 'enzyme' -import TransactionConfirmed from '../index' +import TransactionConfirmed from '..' describe('Transaction Confirmed', function () { it('clicks ok to submit and hide modal', function () { 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 9089ec158..3109c5e27 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 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) diff --git a/ui/app/components/app/network-display/network-display.component.js b/ui/app/components/app/network-display/network-display.component.js index 2dbe96adf..eb89755c3 100644 --- a/ui/app/components/app/network-display/network-display.component.js +++ b/ui/app/components/app/network-display/network-display.component.js @@ -57,7 +57,7 @@ export default class NetworkDisplay extends Component {
{ diff --git a/ui/app/components/app/permission-page-container/index.scss b/ui/app/components/app/permission-page-container/index.scss index c26189e0c..2e3f10aa8 100644 --- a/ui/app/components/app/permission-page-container/index.scss +++ b/ui/app/components/app/permission-page-container/index.scss @@ -31,7 +31,7 @@ } &__title { - @extend %header--18; + @include H4; line-height: 25px; text-align: center; @@ -84,7 +84,7 @@ } &__permissions-header { - @extend %content-text; + @include H6; line-height: 20px; color: #6a737d; 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 338a60631..94895e92d 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,7 +1,7 @@ import PropTypes from 'prop-types' import React, { PureComponent } from 'react' import PermissionsConnectHeader from '../../permissions-connect-header' -import Tooltip from '../../../ui/tooltip-v2' +import Tooltip from '../../../ui/tooltip' import CheckBox from '../../../ui/check-box' export default class PermissionPageContainerContent extends PureComponent { @@ -95,7 +95,7 @@ export default class PermissionPageContainerContent extends PureComponent { ) }) } { selectedIdentities.length > 6 - ? t('plusXMore', [ selectedIdentities.length - 6 ]) + ? t('plusXMore', [selectedIdentities.length - 6]) : null }
@@ -115,23 +115,19 @@ export default class PermissionPageContainerContent extends PureComponent { } else if (allIdentitiesSelected) { return t( 'connectToAll', - [ this.renderAccountTooltip(t('connectToAllAccounts')) ], + [this.renderAccountTooltip(t('connectToAllAccounts'))], ) } else if (selectedIdentities.length > 1) { return t( 'connectToMultiple', [ - this.renderAccountTooltip(t('connectToMultipleNumberOfAccounts', [ selectedIdentities.length ])), - ], - ) - } else { - return t( - 'connectTo', - [ - this.getAccountDescriptor(selectedIdentities[0]), + this.renderAccountTooltip(t('connectToMultipleNumberOfAccounts', [selectedIdentities.length])), ], ) } + return t('connectTo', [ + this.getAccountDescriptor(selectedIdentities[0]), + ]) } render () { 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 f61c9c0ab..8598ab976 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 { PermissionPageContainerContent } from '.' import { PageContainerFooter } from '../../ui/page-container' import PermissionsConnectFooter from '../permissions-connect-footer' +import { PermissionPageContainerContent } from '.' 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 4a2b7c660..bae0f43d9 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,6 +1,6 @@ import { connect } from 'react-redux' -import PermissionPageContainer from './permission-page-container.component' import { getMetaMaskIdentities } from '../../../selectors' +import PermissionPageContainer from './permission-page-container.component' const mapStateToProps = (state, ownProps) => { const { selectedIdentities } = ownProps diff --git a/ui/app/components/app/permissions-connect-footer/index.scss b/ui/app/components/app/permissions-connect-footer/index.scss index ac6508417..51ee8a09f 100644 --- a/ui/app/components/app/permissions-connect-footer/index.scss +++ b/ui/app/components/app/permissions-connect-footer/index.scss @@ -5,9 +5,8 @@ align-items: center; &__text { - @extend %content-text; + @include H7; - font-size: 12px; line-height: 17px; color: #6a737d; display: flex; diff --git a/ui/app/components/app/permissions-connect-header/index.scss b/ui/app/components/app/permissions-connect-header/index.scss index 1b29ec3e0..1ec0628e0 100644 --- a/ui/app/components/app/permissions-connect-header/index.scss +++ b/ui/app/components/app/permissions-connect-header/index.scss @@ -26,7 +26,7 @@ } &__title { - @extend %header--24; + @include H3; text-align: center; color: $Black-100; @@ -35,7 +35,7 @@ &__text, &__subtitle { - @extend %content-text; + @include H6; text-align: center; color: $Grey-500; 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 c9561f820..ff2dd17c9 100644 --- a/ui/app/components/app/selected-account/selected-account.component.js +++ b/ui/app/components/app/selected-account/selected-account.component.js @@ -3,7 +3,7 @@ import PropTypes from 'prop-types' import copyToClipboard from 'copy-to-clipboard' import { shortenAddress, checksumAddress } from '../../../helpers/utils/util' -import Tooltip from '../../ui/tooltip-v2.js' +import Tooltip from '../../ui/tooltip' class SelectedAccount extends Component { state = { 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 57a91cd10..154bf4311 100644 --- a/ui/app/components/app/selected-account/selected-account.container.js +++ b/ui/app/components/app/selected-account/selected-account.container.js @@ -1,7 +1,6 @@ import { connect } from 'react-redux' -import SelectedAccount from './selected-account.component' - import { getSelectedIdentity } from '../../../selectors' +import SelectedAccount from './selected-account.component' const mapStateToProps = (state) => { return { 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 73b659e10..943ccf00a 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,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import { render } from 'enzyme' import SelectedAccount from '../selected-account.component' @@ -9,7 +9,7 @@ describe('SelectedAccount Component', function () { - ), { context: { t: () => {} } }) + ), { context: { t: () => undefined } }) // Checksummed version of address is displayed assert.equal(wrapper.find('.selected-account__address').text(), '0x1B82...5C9D') assert.equal(wrapper.find('.selected-account__name').text(), 'testName') 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 8a203204e..ea9958775 100644 --- a/ui/app/components/app/sidebars/tests/sidebars-component.test.js +++ b/ui/app/components/app/sidebars/tests/sidebars-component.test.js @@ -1,9 +1,9 @@ -import React from 'react' 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.js' +import Sidebar from '../sidebar.component' import CustomizeGas from '../../gas-customization/gas-modal-page-container' diff --git a/ui/app/css/itcss/components/request-signature.scss b/ui/app/components/app/signature-request-original/index.scss similarity index 95% rename from ui/app/css/itcss/components/request-signature.scss rename to ui/app/components/app/signature-request-original/index.scss index 03623e187..6af476fd6 100644 --- a/ui/app/css/itcss/components/request-signature.scss +++ b/ui/app/components/app/signature-request-original/index.scss @@ -8,7 +8,6 @@ flex-flow: column nowrap; z-index: 25; align-items: center; - font-family: Roboto; position: relative; height: 100%; @@ -63,7 +62,6 @@ &__header__text { color: #5b5d67; - font-family: Roboto; font-size: 22px; line-height: 29px; z-index: 3; @@ -104,7 +102,6 @@ &__account-item { height: 22px; background-color: $white; - font-family: Roboto; line-height: 16px; font-size: 12px; width: 124px; @@ -163,7 +160,6 @@ height: 48px; width: 240px; color: $tundora; - font-family: Roboto; font-size: 18px; line-height: 24px; text-align: center; @@ -172,7 +168,6 @@ &__notice, &__warning { - font-family: "Avenir Next"; font-size: 14px; line-height: 19px; text-align: center; @@ -207,7 +202,6 @@ &__row-title { width: 80px; color: $dusty-gray; - font-family: Roboto; font-size: 16px; line-height: 22px; margin-top: 12px; @@ -217,7 +211,6 @@ &__row-value { color: $scorpion; - font-family: Roboto; font-size: 14px; line-height: 19px; width: 100%; 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 8587f024e..31c214e38 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 @@ -7,7 +7,7 @@ import { ObjectInspector } from 'react-inspector' import { ENVIRONMENT_TYPE_NOTIFICATION, MESSAGE_TYPE } from '../../../../../app/scripts/lib/enums' import { getEnvironmentType } from '../../../../../app/scripts/lib/util' import Identicon from '../../ui/identicon' -import AccountListItem from '../../../pages/send/account-list-item/account-list-item.component' +import AccountListItem from '../account-list-item' import { conversionUtil } from '../../../helpers/utils/conversion-util' import Button from '../../ui/button' @@ -95,7 +95,6 @@ export default class SignatureRequestOriginal extends Component {
@@ -248,6 +247,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() } return ( 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 63150d38d..8d0a397ef 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 @@ -10,8 +10,8 @@ import { } from '../../../selectors' import { getAccountByAddress } from '../../../helpers/utils/util' import { clearConfirmTransaction } from '../../../ducks/confirm-transaction/confirm-transaction.duck' -import SignatureRequestOriginal from './signature-request-original.component' import { getMostRecentOverviewPage } from '../../../ducks/history/history' +import SignatureRequestOriginal from './signature-request-original.component' function mapStateToProps (state) { return { diff --git a/ui/app/components/app/signature-request/index.scss b/ui/app/components/app/signature-request/index.scss index 27e7fcfbc..4de4f249b 100644 --- a/ui/app/components/app/signature-request/index.scss +++ b/ui/app/components/app/signature-request/index.scss @@ -38,7 +38,6 @@ min-height: min-content; &__title { - font-family: Roboto; font-style: normal; font-weight: 500; font-size: 18px; @@ -65,7 +64,6 @@ &__identicon-initial { position: absolute; - font-family: Roboto; font-style: normal; font-weight: 500; font-size: 60px; 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 89440acdc..2ec74748c 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,6 +1,6 @@ import React, { PureComponent } from 'react' import PropTypes from 'prop-types' -import AccountListItem from '../../../../pages/send/account-list-item/account-list-item.component' +import AccountListItem from '../../account-list-item' import NetworkDisplay from '../../network-display' export default class SignatureRequestHeader extends PureComponent { @@ -16,7 +16,6 @@ export default class SignatureRequestHeader extends PureComponent {
{fromAccount && ( )} diff --git a/ui/app/components/app/signature-request/signature-request-message/index.scss b/ui/app/components/app/signature-request/signature-request-message/index.scss index 7eef17560..37c0fba72 100644 --- a/ui/app/components/app/signature-request/signature-request-message/index.scss +++ b/ui/app/components/app/signature-request/signature-request-message/index.scss @@ -28,7 +28,6 @@ padding-left: 12px; padding-right: 12px; width: 360px; - font-family: monospace; @media screen and (min-width: 576px) { width: auto; @@ -36,7 +35,6 @@ } &__type-title { - font-family: monospace; font-style: normal; font-weight: normal; font-size: 14px; 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 16b6c3bea..5c4b455d3 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 @@ -14,7 +14,7 @@ export default class SignatureRequestMessage extends PureComponent { renderNode (data) { return (
- {Object.entries(data).map(([ label, value ], i) => ( + {Object.entries(data).map(([label, value], i) => (
{}} - cancel={() => {}} - sign={() => {}} + clearConfirmTransaction={() => undefined} + cancel={() => undefined} + sign={() => undefined} txData={{ msgParams: { data: '{"message": {"from": {"name": "hello"}}}', diff --git a/ui/app/components/app/tab-bar/index.js b/ui/app/components/app/tab-bar/index.js new file mode 100644 index 000000000..74f9a7529 --- /dev/null +++ b/ui/app/components/app/tab-bar/index.js @@ -0,0 +1 @@ +export { default } from './tab-bar' diff --git a/ui/app/components/app/tab-bar/index.scss b/ui/app/components/app/tab-bar/index.scss new file mode 100644 index 000000000..0b9d0605d --- /dev/null +++ b/ui/app/components/app/tab-bar/index.scss @@ -0,0 +1,80 @@ +.tab-bar { + display: flex; + flex-direction: column; + justify-content: flex-start; + + + &__tab { + display: flex; + flex-flow: row nowrap; + align-items: flex-start; + min-width: 0; + flex: 0 0 auto; + box-sizing: border-box; + font-size: 16px; + padding: 16px 24px; + opacity: 0.5; + transition: opacity 200ms ease-in-out; + + @media screen and (min-width: 576px) { + &:hover { + opacity: 0.4; + } + + &:active { + opacity: 0.6; + } + } + + @media screen and (max-width: 575px) { + font-size: 18px; + padding: 24px; + border-bottom: 1px solid $alto; + opacity: 1; + } + + &__content { + flex: 1 1 auto; + width: 0; + + &__description { + display: none; + + @media screen and (max-width: 575px) { + display: block; + font-size: 14px; + font-weight: 300; + margin-top: 8px; + min-height: 14px; + } + } + } + + &__caret { + display: none; + + @media screen and (max-width: 575px) { + display: block; + background-image: url('/images/caret-right.svg'); + width: 36px; + height: 36px; + opacity: 0.5; + background-size: contain; + background-repeat: no-repeat; + background-position: center; + + [dir='rtl'] & { + transform: rotate(180deg); + } + } + } + + &--active { + opacity: 1 !important; + } + } + + &__grow-tab { + flex-grow: 1; + } +} diff --git a/ui/app/components/app/tab-bar.js b/ui/app/components/app/tab-bar/tab-bar.js similarity index 100% rename from ui/app/components/app/tab-bar.js rename to ui/app/components/app/tab-bar/tab-bar.js diff --git a/ui/app/components/app/tests/signature-request.test.js b/ui/app/components/app/tests/signature-request.test.js index 21612e5a0..9efd70973 100644 --- a/ui/app/components/app/tests/signature-request.test.js +++ b/ui/app/components/app/tests/signature-request.test.js @@ -1,6 +1,6 @@ +import assert from 'assert' import React from 'react' import { Provider } from 'react-redux' -import assert from 'assert' import sinon from 'sinon' import configureMockStore from 'redux-mock-store' import { mountWithRouter } from '../../../../../test/lib/render-helpers' diff --git a/ui/app/components/app/token-cell/token-cell.js b/ui/app/components/app/token-cell/token-cell.js index e5f6a5d55..20de78bf3 100644 --- a/ui/app/components/app/token-cell/token-cell.js +++ b/ui/app/components/app/token-cell/token-cell.js @@ -1,13 +1,12 @@ import classnames from 'classnames' import PropTypes from 'prop-types' import React from 'react' -import AssetListItem from '../asset-list-item' 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, decimals, 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 b01f581cf..65a238b69 100644 --- a/ui/app/components/app/token-cell/token-cell.test.js +++ b/ui/app/components/app/token-cell/token-cell.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import thunk from 'redux-thunk' import { Provider } from 'react-redux' import configureMockStore from 'redux-mock-store' @@ -7,8 +7,8 @@ import { mount } from 'enzyme' import sinon from 'sinon' import { MemoryRouter } from 'react-router-dom' -import TokenCell from '.' import Identicon from '../../ui/identicon' +import TokenCell from '.' describe('Token Cell', function () { let wrapper diff --git a/ui/app/components/app/token-list/token-list.js b/ui/app/components/app/token-list/token-list.js index 591dbe33a..b71e6930b 100644 --- a/ui/app/components/app/token-list/token-list.js +++ b/ui/app/components/app/token-list/token-list.js @@ -2,10 +2,10 @@ 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 { useSelector } from 'react-redux' import { getAssetImages } from '../../../selectors' import { getTokens } from '../../../ducks/metamask/metamask' diff --git a/ui/app/components/app/transaction-action/tests/transaction-action.component.test.js b/ui/app/components/app/transaction-action/tests/transaction-action.component.test.js index 1d0263cb0..5e643a80a 100644 --- a/ui/app/components/app/transaction-action/tests/transaction-action.component.test.js +++ b/ui/app/components/app/transaction-action/tests/transaction-action.component.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import { shallow } from 'enzyme' import sinon from 'sinon' import TransactionAction from '../transaction-action.component' @@ -7,7 +7,6 @@ import TransactionAction from '../transaction-action.component' describe('TransactionAction Component', function () { const t = (key) => key - describe('Outgoing transaction', function () { beforeEach(function () { global.eth = { 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 c3422e58e..9b3c39792 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,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import { shallow } from 'enzyme' import TransactionActivityLog from '../transaction-activity-log.component' @@ -40,8 +40,8 @@ describe('TransactionActivityLog Component', function () { inlineRetryIndex={-1} inlineCancelIndex={-1} nativeCurrency="ETH" - onCancel={() => {}} - onRetry={() => {}} + onCancel={() => undefined} + onRetry={() => undefined} primaryTransactionStatus="confirmed" />, { context: { t: (str1, str2) => (str2 ? str1 + str2 : str1) } }, @@ -87,8 +87,8 @@ describe('TransactionActivityLog Component', function () { inlineRetryIndex={2} inlineCancelIndex={3} nativeCurrency="ETH" - onCancel={() => {}} - onRetry={() => {}} + onCancel={() => undefined} + onRetry={() => undefined} primaryTransactionStatus="pending" isEarliestNonce />, @@ -136,8 +136,8 @@ describe('TransactionActivityLog Component', function () { inlineRetryIndex={2} inlineCancelIndex={3} nativeCurrency="ETH" - onCancel={() => {}} - onRetry={() => {}} + onCancel={() => undefined} + onRetry={() => undefined} primaryTransactionStatus="pending" isEarliestNonce={false} />, 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 865320a45..9d071b432 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 @@ -3,9 +3,9 @@ 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' -import { getEtherscanNetworkPrefix } from '../../../../lib/etherscan-prefix-for-network' export default class TransactionActivityLog extends PureComponent { static contextTypes = { 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 7e01e8745..df7a3dc20 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,7 +1,7 @@ import { connect } from 'react-redux' import { findLastIndex } from 'lodash' -import TransactionActivityLog from './transaction-activity-log.component' import { conversionRateSelector, getNativeCurrency } from '../../../selectors' +import TransactionActivityLog from './transaction-activity-log.component' import { combineTransactionHistories } from './transaction-activity-log.util' import { TRANSACTION_RESUBMITTED_EVENT, 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 b01c66145..ed07e1ee4 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,13 +1,9 @@ import { getHexGasTotal } from '../../../helpers/utils/confirm-tx.util' -// path constants -const STATUS_PATH = '/status' -const GAS_PRICE_PATH = '/txParams/gasPrice' -const GAS_LIMIT_PATH = '/txParams/gas' - -// op constants -const REPLACE_OP = 'replace' - +import { + TRANSACTION_TYPE_CANCEL, + TRANSACTION_TYPE_RETRY, +} from '../../../../../app/scripts/controllers/transactions/enums' import { // event constants TRANSACTION_CREATED_EVENT, @@ -25,10 +21,13 @@ import { DROPPED_STATUS, } from './transaction-activity-log.constants' -import { - TRANSACTION_TYPE_CANCEL, - TRANSACTION_TYPE_RETRY, -} from '../../../../../app/scripts/controllers/transactions/enums' +// path constants +const STATUS_PATH = '/status' +const GAS_PRICE_PATH = '/txParams/gasPrice' +const GAS_LIMIT_PATH = '/txParams/gas' + +// op constants +const REPLACE_OP = 'replace' const eventPathsHash = { [STATUS_PATH]: true, 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 bd4c3332a..608ba34b9 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,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import { shallow } from 'enzyme' import TransactionBreakdown from '../transaction-breakdown.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 f9e144a42..f25773e58 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,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import { shallow } from 'enzyme' import TransactionBreakdownRow from '../transaction-breakdown-row.component' import Button from '../../../../ui/button' @@ -27,7 +27,7 @@ describe('TransactionBreakdownRow Component', function () { title="test" className="test-class" > - + , { context: { t: (str1, str2) => (str2 ? str1 + str2 : str1) } }, ) 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 85c24a3e3..7e99f02c3 100644 --- a/ui/app/components/app/transaction-breakdown/transaction-breakdown.component.js +++ b/ui/app/components/app/transaction-breakdown/transaction-breakdown.component.js @@ -1,11 +1,11 @@ import React, { PureComponent } from 'react' import PropTypes from 'prop-types' import classnames from 'classnames' -import TransactionBreakdownRow from './transaction-breakdown-row' 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 = { @@ -37,13 +37,14 @@ export default class TransactionBreakdown extends PureComponent { { t('transaction') }
- {typeof nonce !== 'undefined' - ? ( + {typeof nonce === 'undefined' + ? null + : ( - ) : null + ) } @@ -57,14 +58,14 @@ export default class TransactionBreakdown extends PureComponent { title={`${t('gasLimit')} (${t('units')})`} className="transaction-breakdown__row-title" > - {typeof gas !== 'undefined' - ? ( + {typeof gas === 'undefined' + ? '?' + : ( ) - : '?' } { @@ -81,8 +82,9 @@ export default class TransactionBreakdown extends PureComponent { ) } - {typeof gasPrice !== 'undefined' - ? ( + {typeof gasPrice === 'undefined' + ? '?' + : ( ) - : '?' } 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 bfc23913c..6aee276a7 100644 --- a/ui/app/components/app/transaction-breakdown/transaction-breakdown.container.js +++ b/ui/app/components/app/transaction-breakdown/transaction-breakdown.container.js @@ -1,8 +1,8 @@ import { connect } from 'react-redux' -import TransactionBreakdown from './transaction-breakdown.component' import { getIsMainnet, getNativeCurrency, getPreferences } from '../../../selectors' import { getHexGasTotal } from '../../../helpers/utils/confirm-tx.util' import { sumHexes } from '../../../helpers/utils/transactions.util' +import TransactionBreakdown from './transaction-breakdown.component' const mapStateToProps = (state, ownProps) => { const { transaction } = ownProps @@ -17,7 +17,7 @@ const mapStateToProps = (state, ownProps) => { return { nativeCurrency: getNativeCurrency(state), - showFiat: (isMainnet || !!showFiatInTestnets), + showFiat: (isMainnet || Boolean(showFiatInTestnets)), totalInHex, gas, gasPrice, diff --git a/ui/app/components/app/transaction-icon/transaction-icon.js b/ui/app/components/app/transaction-icon/transaction-icon.js index 24f4f4715..d0c7ef455 100644 --- a/ui/app/components/app/transaction-icon/transaction-icon.js +++ b/ui/app/components/app/transaction-icon/transaction-icon.js @@ -20,7 +20,6 @@ import { APPROVED_STATUS, } from '../../../helpers/constants/transactions' - const ICON_MAP = { [TRANSACTION_CATEGORY_APPROVAL]: Approve, [TRANSACTION_CATEGORY_INTERACTION]: Interaction, diff --git a/ui/app/components/app/transaction-list-item-details/index.scss b/ui/app/components/app/transaction-list-item-details/index.scss index 64fe19220..145e0e9a1 100644 --- a/ui/app/components/app/transaction-list-item-details/index.scss +++ b/ui/app/components/app/transaction-list-item-details/index.scss @@ -16,7 +16,7 @@ flex-direction: row; } - &__header-button { + & &__header-button { font-size: 0.625rem; &:not(:last-child) { 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 0c9726aef..d647362f5 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,5 +1,5 @@ -import React from 'react' 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' @@ -34,7 +34,7 @@ describe('TransactionListItemDetails Component', function () { title="Test Transaction Details" recipientAddress="0x1" senderAddress="0x2" - tryReverseResolveAddress={() => {}} + tryReverseResolveAddress={() => undefined} transactionGroup={transactionGroup} senderNickname="sender-nickname" recipientNickname="recipient-nickname" @@ -77,7 +77,7 @@ describe('TransactionListItemDetails Component', function () { {}} + tryReverseResolveAddress={() => undefined} transactionGroup={transactionGroup} showSpeedUp senderNickname="sender-nickname" @@ -117,7 +117,7 @@ describe('TransactionListItemDetails Component', function () { {}} + tryReverseResolveAddress={() => undefined} transactionGroup={transactionGroup} senderNickname="sender-nickname" recipientNickname="recipient-nickname" @@ -159,7 +159,7 @@ describe('TransactionListItemDetails Component', function () { {}} + tryReverseResolveAddress={() => undefined} transactionGroup={transactionGroup} senderNickname="sender-nickname" recipientNickname="recipient-nickname" 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 cc5418860..cfd2aecfd 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 @@ -114,7 +114,7 @@ export default class TransactionListItemDetails extends PureComponent { return cancelDisabled ? ( - +
) -export const linkType = () => ( - -) diff --git a/ui/app/components/ui/button/buttons.scss b/ui/app/components/ui/button/buttons.scss index 2fdc1da01..a8364ca65 100644 --- a/ui/app/components/ui/button/buttons.scss +++ b/ui/app/components/ui/button/buttons.scss @@ -10,11 +10,10 @@ $hover-red-primary: #c72837; $hover-orange: #ffd3b5; $warning-light-orange: #f8b588; -%button { - @include h6; +.button { + @include H6; font-weight: 500; - font-family: Roboto, Arial; line-height: 1.25rem; padding: 0.75rem 1rem; display: flex; @@ -31,41 +30,6 @@ $warning-light-orange: #f8b588; opacity: 0.5; pointer-events: none; } -} - -%link { - @include h4; - - color: $Blue-500; - line-height: 1.25rem; - cursor: pointer; - background-color: transparent; - - &:hover { - color: $Blue-400; - } - - &:active { - color: $Blue-600; - } - - &--disabled, - &[disabled] { - cursor: auto; - opacity: 1; - pointer-events: none; - color: $hover-secondary; - } -} - -%small-link { - @extend %link; - - @include h6; -} - -.button { - @extend %button; &__icon { display: flex; @@ -203,7 +167,28 @@ $warning-light-orange: #f8b588; } .btn-link { - @extend %link; + @include H4; + + color: $Blue-500; + line-height: 1.25rem; + cursor: pointer; + background-color: transparent; + + &:hover { + color: $Blue-400; + } + + &:active { + color: $Blue-600; + } + + &--disabled, + &[disabled] { + cursor: auto; + opacity: 1; + pointer-events: none; + color: $hover-secondary; + } } .btn--large { @@ -249,7 +234,6 @@ button.primary { box-shadow: 0 3px 6px rgba(247, 134, 28, 0.36); color: $white; font-size: 1.1em; - font-family: Roboto; text-transform: uppercase; } 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 bb7ce3f1a..9eb104351 100644 --- a/ui/app/components/ui/card/tests/card.component.test.js +++ b/ui/app/components/ui/card/tests/card.component.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import { shallow } from 'enzyme' import Card from '../card.component' 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 b1c62433a..4a7457140 100644 --- a/ui/app/components/ui/check-box/check-box.component.js +++ b/ui/app/components/ui/check-box/check-box.component.js @@ -12,6 +12,7 @@ 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 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 9ddc14a5f..7a573a14c 100644 --- a/ui/app/components/ui/check-box/check-box.stories.js +++ b/ui/app/components/ui/check-box/check-box.stories.js @@ -1,7 +1,7 @@ import React from 'react' import { action } from '@storybook/addon-actions' -import CheckBox, { CHECKED, INDETERMINATE, UNCHECKED } from './check-box.component' import { boolean, select, text } from '@storybook/addon-knobs/react' +import CheckBox, { CHECKED, INDETERMINATE, UNCHECKED } from './check-box.component' export default { title: 'Check Box', 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 862c160f8..68bac84cf 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,9 +1,9 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import { shallow } from 'enzyme' -import CurrencyDisplay from '../currency-display.component' import sinon from 'sinon' import * as reactRedux from 'react-redux' +import CurrencyDisplay from '../currency-display.component' describe('CurrencyDisplay Component', function () { beforeEach(function () { 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 d8c7a572c..581e1c1a2 100644 --- a/ui/app/components/ui/currency-input/currency-input.container.js +++ b/ui/app/components/ui/currency-input/currency-input.container.js @@ -1,11 +1,11 @@ import { connect } from 'react-redux' -import CurrencyInput from './currency-input.component' import { ETH } from '../../../helpers/constants/common' import { getSendMaxModeState, getIsMainnet, getPreferences, } from '../../../selectors' +import CurrencyInput from './currency-input.component' const mapStateToProps = (state) => { const { metamask: { nativeCurrency, currentCurrency, conversionRate } } = state 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 adbd4efd2..1e7936978 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,6 +1,6 @@ +import assert from 'assert' import React from 'react' import PropTypes from 'prop-types' -import assert from 'assert' import { shallow, mount } from 'enzyme' import sinon from 'sinon' import { Provider } from 'react-redux' @@ -137,7 +137,7 @@ describe('CurrencyInput Component', function () { /> , { - context: { t: (str) => str + '_t' }, + context: { t: (str) => `${str}_t` }, childContextTypes: { t: PropTypes.func }, }, ) diff --git a/ui/app/components/ui/dropdown/dropdown.scss b/ui/app/components/ui/dropdown/dropdown.scss index 296ea95c0..49a684bb7 100644 --- a/ui/app/components/ui/dropdown/dropdown.scss +++ b/ui/app/components/ui/dropdown/dropdown.scss @@ -11,7 +11,6 @@ background-position: right 18px top 50%; background-color: white; padding: 8px 32px 8px 16px; - font-family: Roboto, 'sans-serif'; font-size: 14px; [dir='rtl'] & { diff --git a/ui/app/components/ui/dropdown/dropdown.stories.js b/ui/app/components/ui/dropdown/dropdown.stories.js index 9b62f3c80..1ecb31bc9 100644 --- a/ui/app/components/ui/dropdown/dropdown.stories.js +++ b/ui/app/components/ui/dropdown/dropdown.stories.js @@ -1,7 +1,7 @@ import React from 'react' import { action } from '@storybook/addon-actions' -import Dropdown from '.' import { boolean, select, text } from '@storybook/addon-knobs/react' +import Dropdown from '.' export default { title: 'Dropdown', @@ -12,14 +12,13 @@ const unnamedOptions = [...Array(10).keys()].map((index) => { }) const namedOptions = unnamedOptions.map((option, index) => { - return Object.assign({}, option, { name: `Option ${index}` }) + return { ...option, name: `Option ${index}` } }) const namedOptionsWithVeryLongNames = unnamedOptions.map((option, index) => { - return Object.assign({}, option, { name: `Option ${index} with a very${', very'.repeat(index)} long name` }) + return { ...option, name: `Option ${index} with a very${', very'.repeat(index)} long name` } }) - export const simple = () => ( ( { diff --git a/ui/app/components/ui/identicon/identicon.stories.js b/ui/app/components/ui/identicon/identicon.stories.js index 69d4d2721..3785080d5 100644 --- a/ui/app/components/ui/identicon/identicon.stories.js +++ b/ui/app/components/ui/identicon/identicon.stories.js @@ -1,7 +1,7 @@ import React from 'react' import { text, boolean } from '@storybook/addon-knobs/react' -import Identicon from './identicon.component' import { number } from '@storybook/addon-knobs' +import Identicon from './identicon.component' export default { title: 'Identicon' } 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 8735294a0..f14229bfd 100644 --- a/ui/app/components/ui/identicon/tests/identicon.component.test.js +++ b/ui/app/components/ui/identicon/tests/identicon.component.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import thunk from 'redux-thunk' import configureMockStore from 'redux-mock-store' import { mount } from 'enzyme' diff --git a/ui/app/components/ui/info-tooltip/index.js b/ui/app/components/ui/info-tooltip/index.js new file mode 100644 index 000000000..2fe0f2786 --- /dev/null +++ b/ui/app/components/ui/info-tooltip/index.js @@ -0,0 +1 @@ +export { default } from './info-tooltip' diff --git a/ui/app/components/ui/info-tooltip/index.scss b/ui/app/components/ui/info-tooltip/index.scss new file mode 100644 index 000000000..a85f041ce --- /dev/null +++ b/ui/app/components/ui/info-tooltip/index.scss @@ -0,0 +1,39 @@ +.info-tooltip { + img { + height: 10px; + width: 10px; + } +} + +.tippy-popper[x-placement^=top] .info-theme [x-arrow] { + border-top-color: $white; +} + +.tippy-popper[x-placement^=right] .info-theme [x-arrow] { + border-right-color: $white; +} + +.tippy-popper[x-placement^=left] .info-theme [x-arrow] { + border-left-color: $white; +} + +.tippy-popper[x-placement^=bottom] .info-theme [x-arrow] { + border-bottom-color: $white; +} + +.tippy-tooltip.info-theme { + background: white; + color: black; + box-shadow: 0 0 14px rgba(0, 0, 0, 0.18); + border-radius: 8px; + max-width: 203px; + padding: 16px; + padding-bottom: 15px; + + .tippy-tooltip-content { + @include H8; + + text-align: left; + color: $Grey-500; + } +} diff --git a/ui/app/components/ui/info-tooltip/info-tooltip.js b/ui/app/components/ui/info-tooltip/info-tooltip.js new file mode 100644 index 000000000..aecba58ef --- /dev/null +++ b/ui/app/components/ui/info-tooltip/info-tooltip.js @@ -0,0 +1,36 @@ +import React from 'react' +import PropTypes from 'prop-types' +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 = '', + position = '', +}) { + return ( +
+ + + +
+ ) +} + +InfoTooltip.propTypes = { + contentText: PropTypes.string, + position: PropTypes.oneOf(['top', 'left', 'bottom', 'right']), +} diff --git a/ui/app/components/ui/info-tooltip/info-tooltip.stories.js b/ui/app/components/ui/info-tooltip/info-tooltip.stories.js new file mode 100644 index 000000000..10e6bec09 --- /dev/null +++ b/ui/app/components/ui/info-tooltip/info-tooltip.stories.js @@ -0,0 +1,35 @@ +import React from 'react' +import { text } from '@storybook/addon-knobs/react' +import InfoTooltip from './info-tooltip' + +export default { + title: 'InfoTooltip', +} + +export const Top = () => ( + +) + +export const Bottom = () => ( + +) + +export const Left = () => ( + +) + +export const Right = () => ( + +) diff --git a/ui/app/components/ui/list-item/index.scss b/ui/app/components/ui/list-item/index.scss index a26efcb4c..2117dfc4d 100644 --- a/ui/app/components/ui/list-item/index.scss +++ b/ui/app/components/ui/list-item/index.scss @@ -5,7 +5,7 @@ background: #fff; padding: 24px 16px; - @extend %font; + @include Paragraph; border-top: 1px solid $mercury; border-bottom: 1px solid $mercury; 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 c26015c34..197a06296 100644 --- a/ui/app/components/ui/list-item/list-item.stories.js +++ b/ui/app/components/ui/list-item/list-item.stories.js @@ -1,6 +1,5 @@ import React from 'react' import PropTypes from 'prop-types' -import ListItem from './list-item.component' import { text } from '@storybook/addon-knobs/react' import Send from '../icon/send-icon.component' import Interaction from '../icon/interaction-icon.component' @@ -8,6 +7,7 @@ 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', @@ -69,7 +69,6 @@ export const pending = () => ( /> ) - export const approve = () => ( } 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 d5855a75b..10e534446 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,8 +1,8 @@ +import assert from 'assert' import { shallow } from 'enzyme' import React from 'react' -import ListItem from '../list-item.component' -import assert from 'assert' 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' diff --git a/ui/app/components/ui/mascot/index.js b/ui/app/components/ui/mascot/index.js new file mode 100644 index 000000000..ad6ece331 --- /dev/null +++ b/ui/app/components/ui/mascot/index.js @@ -0,0 +1 @@ +export { default } from './mascot.component' diff --git a/ui/app/components/ui/mascot.js b/ui/app/components/ui/mascot/mascot.component.js similarity index 100% rename from ui/app/components/ui/mascot.js rename to ui/app/components/ui/mascot/mascot.component.js diff --git a/ui/app/components/ui/menu/menu.scss b/ui/app/components/ui/menu/menu.scss index de3935539..a34deda53 100644 --- a/ui/app/components/ui/menu/menu.scss +++ b/ui/app/components/ui/menu/menu.scss @@ -9,7 +9,6 @@ flex-direction: column; align-items: center; padding: 0 16px; - font-family: Roboto, 'sans-serif'; font-size: 14px; font-weight: normal; line-height: 20px; @@ -28,7 +27,6 @@ .menu-item { background: none; - font-family: inherit; font-size: inherit; display: grid; grid-template-columns: min-content auto; diff --git a/ui/app/components/ui/menu/menu.stories.js b/ui/app/components/ui/menu/menu.stories.js index c3071c798..02eb2186a 100644 --- a/ui/app/components/ui/menu/menu.stories.js +++ b/ui/app/components/ui/menu/menu.stories.js @@ -1,6 +1,6 @@ import React, { useState } from 'react' -import { Menu, MenuItem } from '.' import { action } from '@storybook/addon-actions' +import { Menu, MenuItem } from '.' export default { title: 'Menu', 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 b44754c14..acdf4c1c7 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,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import { mount } from 'enzyme' import MetaFoxLogo from '..' 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 f7b365e8e..8a5cf1114 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,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import { shallow } from 'enzyme' import sinon from 'sinon' import Button from '../../../button' @@ -28,7 +28,7 @@ describe('Page Footer', function () { }) it('should render a secondary footer inside page-container__footer when given children', function () { - const wrapper = shallow( + wrapper = shallow(
Works
, 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 c5ff365db..5d5a88a9e 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,6 +1,7 @@ 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 = { @@ -72,7 +73,7 @@ export default class PageContainerHeader extends Component { { onClose && headerCloseText - ?
onClose()}>{ headerCloseText }
+ ? : onClose && (
+
+
+
+
+ ) +} diff --git a/ui/app/components/ui/pulse-loader/pulse-loader.stories.js b/ui/app/components/ui/pulse-loader/pulse-loader.stories.js new file mode 100644 index 000000000..4823ac604 --- /dev/null +++ b/ui/app/components/ui/pulse-loader/pulse-loader.stories.js @@ -0,0 +1,8 @@ +import React from 'react' +import PulseLoader from '.' + +export default { + title: 'PulseLoader', +} + +export const common = () => () diff --git a/ui/app/components/ui/qr-code/index.js b/ui/app/components/ui/qr-code/index.js new file mode 100644 index 000000000..f638ae4fb --- /dev/null +++ b/ui/app/components/ui/qr-code/index.js @@ -0,0 +1 @@ +export { default } from './qr-code' diff --git a/ui/app/components/ui/qr-code/index.scss b/ui/app/components/ui/qr-code/index.scss new file mode 100644 index 000000000..86bd5af43 --- /dev/null +++ b/ui/app/components/ui/qr-code/index.scss @@ -0,0 +1,25 @@ +.qr-code { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + + &__message-container > div:first-child { + margin-top: 18px; + font-size: 15px; + color: #4d4d4d; + } + + &__message { + font-size: 12px; + color: #f7861c; + } + + &__error { + display: flex; + justify-content: center; + align-items: center; + color: #f7861c; + margin-bottom: 9px; + } +} diff --git a/ui/app/components/ui/qr-code.js b/ui/app/components/ui/qr-code/qr-code.js similarity index 75% rename from ui/app/components/ui/qr-code.js rename to ui/app/components/ui/qr-code/qr-code.js index 267277c01..53a0d85d5 100644 --- a/ui/app/components/ui/qr-code.js +++ b/ui/app/components/ui/qr-code/qr-code.js @@ -3,8 +3,8 @@ import React from 'react' import qrCode from 'qrcode-generator' import { connect } from 'react-redux' import { isHexPrefixed } from 'ethereumjs-util' -import ReadOnlyInput from './readonly-input' -import { checksumAddress } from '../../helpers/utils/util' +import ReadOnlyInput from '../readonly-input/readonly-input' +import { checksumAddress } from '../../../helpers/utils/util' export default connect(mapStateToProps)(QrCodeView) @@ -24,20 +24,20 @@ function QrCodeView (props) { qrImage.make() return ( -
+
{ Array.isArray(message) ? ( -
- {props.Qr.message.map((message, index) => ( -
- {message} +
+ {props.Qr.message.map((msg, index) => ( +
+ {msg}
))}
) : message && ( -
+
{message}
) @@ -45,21 +45,20 @@ function QrCodeView (props) { { props.warning ? (props.warning && ( - + {props.warning} )) : null }
diff --git a/ui/app/components/ui/readonly-input/index.js b/ui/app/components/ui/readonly-input/index.js new file mode 100644 index 000000000..151a02ee8 --- /dev/null +++ b/ui/app/components/ui/readonly-input/index.js @@ -0,0 +1 @@ +export { default } from './readonly-input' diff --git a/ui/app/components/ui/readonly-input/index.scss b/ui/app/components/ui/readonly-input/index.scss new file mode 100644 index 000000000..9eff60bbb --- /dev/null +++ b/ui/app/components/ui/readonly-input/index.scss @@ -0,0 +1,8 @@ +.readonly-input { + &__input { + direction: ltr; + overflow: hidden; + text-overflow: ellipsis; + width: 100%; + } +} diff --git a/ui/app/components/ui/readonly-input.js b/ui/app/components/ui/readonly-input/readonly-input.js similarity index 78% rename from ui/app/components/ui/readonly-input.js rename to ui/app/components/ui/readonly-input/readonly-input.js index b884da1bc..eba6fd6c2 100644 --- a/ui/app/components/ui/readonly-input.js +++ b/ui/app/components/ui/readonly-input/readonly-input.js @@ -1,5 +1,6 @@ import PropTypes from 'prop-types' import React from 'react' +import classnames from 'classnames' export default function ReadOnlyInput (props) { const { @@ -13,9 +14,9 @@ export default function ReadOnlyInput (props) { const InputType = textarea ? 'textarea' : 'input' return ( -
+
event.target.select()} 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 87707dc5c..de7e54745 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,14 +1,13 @@ import React, { useState } from 'react' import PropTypes from 'prop-types' import classnames from 'classnames' -import Identicon from '../identicon' -import Tooltip from '../tooltip-v2' import copyToClipboard from 'copy-to-clipboard' -import { DEFAULT_VARIANT, CARDS_VARIANT, FLAT_VARIANT } from './sender-to-recipient.constants' +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' const variantHash = { [DEFAULT_VARIANT]: 'sender-to-recipient--default', @@ -161,7 +160,6 @@ RecipientWithAddress.propTypes = { onRecipientClick: PropTypes.func, } - function Arrow ({ variant }) { return variant === DEFAULT_VARIANT ? ( diff --git a/ui/app/components/ui/tabs/tabs.component.js b/ui/app/components/ui/tabs/tabs.component.js index 17e2c2021..c524759fc 100644 --- a/ui/app/components/ui/tabs/tabs.component.js +++ b/ui/app/components/ui/tabs/tabs.component.js @@ -41,7 +41,7 @@ export default class Tabs extends Component { return React.Children.map(this.props.children, (child, index) => { const tabName = child?.props.name return child && React.cloneElement(child, { - onClick: (index) => this.handleTabClick(index, tabName), + onClick: (idx) => this.handleTabClick(idx, tabName), tabIndex: index, isActive: numberOfTabs > 1 && index === this.state.activeTabIndex, }) diff --git a/ui/app/components/ui/tabs/tabs.stories.js b/ui/app/components/ui/tabs/tabs.stories.js index 0e2caffed..2cf40736c 100644 --- a/ui/app/components/ui/tabs/tabs.stories.js +++ b/ui/app/components/ui/tabs/tabs.stories.js @@ -1,7 +1,7 @@ import React from 'react' +import { text } from '@storybook/addon-knobs/react' import Tab from './tab/tab.component' import Tabs from './tabs.component' -import { text } from '@storybook/addon-knobs/react' export default { title: 'Tabs', 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 008e621d4..9e80e3bc8 100644 --- a/ui/app/components/ui/text-field/text-field.component.js +++ b/ui/app/components/ui/text-field/text-field.component.js @@ -146,7 +146,7 @@ const getBorderedThemeInputProps = ({ disableUnderline: true, classes: { root: inputRoot, - input: input, + input, focused: inputFocused, }, inputProps: { diff --git a/ui/app/components/ui/toggle-button/index.scss b/ui/app/components/ui/toggle-button/index.scss index cdd99f7f7..09827888c 100644 --- a/ui/app/components/ui/toggle-button/index.scss +++ b/ui/app/components/ui/toggle-button/index.scss @@ -3,7 +3,6 @@ $self: &; &__status { - font-family: Roboto; font-style: normal; font-weight: normal; font-size: 16px; 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 201c6b4ab..a7cda504f 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,6 +1,6 @@ +import assert from 'assert' import React from 'react' import PropTypes from 'prop-types' -import assert from 'assert' import { shallow, mount } from 'enzyme' import sinon from 'sinon' import { Provider } from 'react-redux' @@ -32,7 +32,8 @@ describe('TokenInput Component', function () { }} /> , - { context: { t }, + { + context: { t }, childContextTypes: { t: PropTypes.func, }, @@ -66,7 +67,8 @@ describe('TokenInput Component', function () { tokenExchangeRates={{ '0x1': 2 }} /> , - { context: { t }, + { + context: { t }, childContextTypes: { t: PropTypes.func, }, 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 a425b3c0a..785601171 100644 --- a/ui/app/components/ui/token-input/token-input.component.js +++ b/ui/app/components/ui/token-input/token-input.component.js @@ -1,9 +1,9 @@ import React, { PureComponent } from 'react' import PropTypes from 'prop-types' +import ethUtil from 'ethereumjs-util' import UnitInput from '../unit-input' import CurrencyDisplay from '../currency-display' import { getWeiHexFromDecimalValue } from '../../../helpers/utils/conversions.util' -import ethUtil from 'ethereumjs-util' import { conversionUtil, multiplyCurrencies } from '../../../helpers/utils/conversion-util' import { ETH } from '../../../helpers/constants/common' 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 b56efc131..f20670d31 100644 --- a/ui/app/components/ui/token-input/token-input.container.js +++ b/ui/app/components/ui/token-input/token-input.container.js @@ -1,11 +1,11 @@ import { connect } from 'react-redux' import PropTypes from 'prop-types' -import TokenInput from './token-input.component' import { getIsMainnet, getTokenExchangeRates, getPreferences, } from '../../../selectors' +import TokenInput from './token-input.component' const mapStateToProps = (state) => { const { metamask: { currentCurrency } } = state diff --git a/ui/app/components/ui/tooltip.js b/ui/app/components/ui/tooltip.js deleted file mode 100644 index 72c328ff9..000000000 --- a/ui/app/components/ui/tooltip.js +++ /dev/null @@ -1,189 +0,0 @@ -import PropTypes from 'prop-types' -import React, { Component } from 'react' -import ReactDOM from 'react-dom' - -class ReactTooltip extends Component { - static propTypes = { - container: PropTypes.any, - children: PropTypes.node.isRequired, - title: PropTypes.string.isRequired, - position: PropTypes.oneOf(['left', 'top', 'right', 'bottom']), - fixed: PropTypes.bool, - space: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), - } - - static defaultProps = { - container: document.body, - position: 'top', - fixed: true, - space: 5, - } - - componentDidMount = () => { - this.container = this.props.container || document.body - /* eslint-disable react/no-find-dom-node */ - this.componentEl = ReactDOM.findDOMNode(this) - this.tooltipEl = document.createElement('div') - - const tooltipArrowEl = document.createElement('div') - tooltipArrowEl.className = 'tooltip-arrow' - - const tooltipContentEl = document.createElement('div') - tooltipContentEl.className = 'tooltip-inner' - tooltipContentEl.textContent = this.props.title - - this.tooltipEl.appendChild(tooltipArrowEl) - this.tooltipEl.appendChild(tooltipContentEl) - this.tooltipEl.className = 'tooltip ' + this.props.position - this.container.appendChild(this.tooltipEl) - this.resetTooltip() - - this.componentEl.addEventListener(this.props.fixed ? 'mouseenter' : 'mousemove', this.handleMouseMove) - this.componentEl.addEventListener('mouseleave', this.handleMouseOut) - } - - componentDidUpdate = () => { - this.tooltipEl.className = 'tooltip ' + this.props.position - this.tooltipEl.childNodes[1].textContent = this.props.title - } - - - componentWillUnmount = () => { - this.componentEl.removeEventListener(this.props.fixed ? 'mouseenter' : 'mousemove', this.handleMouseMove) - this.componentEl.removeEventListener('mouseleave', this.handleMouseOut) - this.container.removeChild(this.tooltipEl) - } - - resetTooltip = () => { - this.tooltipEl.style.transition = 'opacity 0.4s' - this.tooltipEl.style.left = '-500px' - this.tooltipEl.style.top = '-500px' - this.tooltipEl.style.opacity = 0 - } - - handleMouseMove = (e) => { - if (this.props.title === '') { - return - } - - const tooltipPosition = this.getTooltipPosition(e) - const tooltipOffset = this.getTooltipOffset() - - this.tooltipEl.style.left = tooltipPosition.x + tooltipOffset.x + 'px' - this.tooltipEl.style.top = tooltipPosition.y + tooltipOffset.y + 'px' - this.tooltipEl.style.opacity = 1 - } - - handleMouseOut = () => { - this.resetTooltip() - } - - getTooltipPosition = (e) => { - let pointX - let pointY - const bodyRect = document.body.getBoundingClientRect() - const containerRect = this.container.getBoundingClientRect() - const containerOffsetX = containerRect.left - bodyRect.left - const containerOffsetY = containerRect.top - bodyRect.top - if (this.props.fixed) { - const componentRect = this.componentEl.getBoundingClientRect() - const componentOffsetX = componentRect.left - containerOffsetX - const componentOffsetY = componentRect.top - containerOffsetY - const componentWidth = this.componentEl.offsetWidth - const componentHeight = this.componentEl.offsetHeight - let cOffsetX = 0 - let cOffsetY = 0 - switch (this.props.position) { - case 'top': - cOffsetX = componentWidth / 2 - cOffsetY = 0 - break - case 'right': - cOffsetX = componentWidth - cOffsetY = componentHeight / 2 - break - case 'bottom': - cOffsetX = componentWidth / 2 - cOffsetY = componentHeight - break - case 'left': - cOffsetX = 0 - cOffsetY = componentHeight / 2 - break - default: - cOffsetX = componentWidth / 2 - cOffsetY = 0 - break - } - pointX = componentOffsetX + cOffsetX + (window.scrollX || window.pageXOffset) - pointY = componentOffsetY + cOffsetY + (window.scrollY || window.pageYOffset) - } else { - const clientX = e.clientX - const clientY = e.clientY - pointX = clientX - containerOffsetX + (window.scrollX || window.pageXOffset) - pointY = clientY - containerOffsetY + (window.scrollY || window.pageYOffset) - } - return { - x: pointX, - y: pointY, - } - } - - getTooltipOffset = () => { - const tooltipW = this.tooltipEl.offsetWidth - const tooltipH = this.tooltipEl.offsetHeight - let offsetX = 0 - let offsetY = 0 - switch (this.props.position) { - case 'top': - offsetX = -(tooltipW / 2) - offsetY = -(tooltipH + Number(this.props.space)) - break - case 'right': - offsetX = Number(this.props.space) - offsetY = -(tooltipH / 2) - break - case 'bottom': - offsetX = -(tooltipW / 2) - offsetY = Number(this.props.space) - break - case 'left': - offsetX = -(tooltipW + Number(this.props.space)) - offsetY = -(tooltipH / 2) - break - default: - offsetX = -(tooltipW + Number(this.props.space)) - offsetY = -(tooltipH / 2) - break - } - return { - x: offsetX, - y: offsetY, - } - } - - render () { - return this.props.children - } -} - -function Tooltip ({ position, title, children }) { - return ( - - {children} - - ) -} - -Tooltip.defaultProps = { - position: 'left', - children: null, -} - -Tooltip.propTypes = { - position: PropTypes.string, - title: PropTypes.string.isRequired, - children: PropTypes.node, -} - -export default Tooltip diff --git a/ui/app/components/ui/tooltip/index.js b/ui/app/components/ui/tooltip/index.js new file mode 100644 index 000000000..00a8d178a --- /dev/null +++ b/ui/app/components/ui/tooltip/index.js @@ -0,0 +1 @@ +export { default } from './tooltip' diff --git a/ui/app/components/ui/tooltip-v2.js b/ui/app/components/ui/tooltip/tooltip.js similarity index 96% rename from ui/app/components/ui/tooltip-v2.js rename to ui/app/components/ui/tooltip/tooltip.js index 8941aa1fd..e6b5726d4 100644 --- a/ui/app/components/ui/tooltip-v2.js +++ b/ui/app/components/ui/tooltip/tooltip.js @@ -16,6 +16,7 @@ export default class Tooltip extends PureComponent { title: null, trigger: 'mouseenter', wrapperClassName: undefined, + theme: '', } static propTypes = { @@ -40,6 +41,7 @@ export default class Tooltip extends PureComponent { trigger: PropTypes.any, wrapperClassName: PropTypes.string, style: PropTypes.object, + theme: PropTypes.string, } render () { @@ -58,6 +60,7 @@ export default class Tooltip extends PureComponent { offset, wrapperClassName, style, + theme, } = this.props if (!title && !html) { @@ -84,6 +87,7 @@ export default class Tooltip extends PureComponent { style={style} title={title} trigger={trigger} + theme={theme} > {children} diff --git a/ui/app/components/ui/ui-components.scss b/ui/app/components/ui/ui-components.scss new file mode 100644 index 000000000..7ebdec825 --- /dev/null +++ b/ui/app/components/ui/ui-components.scss @@ -0,0 +1,37 @@ +/** Please import your files in alphabetical order **/ +@import 'account-mismatch-warning/index'; +@import 'alert-circle-icon/index'; +@import 'alert/index'; +@import 'breadcrumbs/index'; +@import 'button-group/index'; +@import 'button/buttons'; +@import 'card/index'; +@import 'check-box/index'; +@import 'circle-icon/index'; +@import 'currency-display/index'; +@import 'currency-input/index'; +@import 'dialog/dialog'; +@import 'dropdown/dropdown'; +@import 'editable-label/index'; +@import 'error-message/index'; +@import 'export-text-container/index'; +@import 'icon-border/icon-border'; +@import 'icon-with-fallback/icon-with-fallback'; +@import 'icon-with-label/index'; +@import 'icon/index'; +@import 'icon/preloader/index'; +@import 'identicon/index'; +@import 'info-tooltip/index'; +@import 'list-item/index'; +@import 'menu/menu'; +@import 'page-container/index'; +@import 'popover/index'; +@import 'pulse-loader/index'; +@import 'qr-code/index'; +@import 'readonly-input/index'; +@import 'sender-to-recipient/index'; +@import 'snackbar/index'; +@import 'tabs/index'; +@import 'toggle-button/index'; +@import 'token-balance/index'; +@import 'unit-input/index'; diff --git a/ui/app/components/ui/unit-input/index.scss b/ui/app/components/ui/unit-input/index.scss index ed80f26ac..c86f487b5 100644 --- a/ui/app/components/ui/unit-input/index.scss +++ b/ui/app/components/ui/unit-input/index.scss @@ -36,7 +36,6 @@ &__input { color: #4d4d4d; font-size: 1rem; - font-family: Roboto; border: none; max-width: 22ch; height: 16px; 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 798ae3676..0b92fc5a0 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,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import { shallow, mount } from 'enzyme' import sinon from 'sinon' import UnitInput from '../unit-input.component' 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 d2368291f..6a9b76e7c 100644 --- a/ui/app/components/ui/unit-input/unit-input.component.js +++ b/ui/app/components/ui/unit-input/unit-input.component.js @@ -58,8 +58,8 @@ export default class UnitInput extends PureComponent { getInputWidth (value) { const valueString = String(value) const valueLength = valueString.length || 1 - const decimalPointDeficit = valueString.match(/\./) ? -0.5 : 0 - return (valueLength + decimalPointDeficit + 0.5) + 'ch' + const decimalPointDeficit = valueString.match(/\./u) ? -0.5 : 0 + return `${valueLength + decimalPointDeficit + 0.5}ch` } render () { diff --git a/ui/app/contexts/metametrics.js b/ui/app/contexts/metametrics.js index b1440429e..111622587 100644 --- a/ui/app/contexts/metametrics.js +++ b/ui/app/contexts/metametrics.js @@ -20,7 +20,6 @@ import { sendCountIsTrackable, } from '../helpers/utils/metametrics.util' - 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`), @@ -60,7 +59,7 @@ export function MetaMetricsProvider ({ children }) { const { eventOpts = {} } = config const { name = '' } = eventOpts const { currentPath: overrideCurrentPath = '' } = overrides - const isSendFlow = Boolean(name.match(/^send|^confirm/) || overrideCurrentPath.match(/send|confirm/)) + const isSendFlow = Boolean(name.match(/^send|^confirm/u) || overrideCurrentPath.match(/send|confirm/u)) if (participateInMetaMetrics || config.isOptIn) { return sendMetaMetricsEvent({ @@ -80,6 +79,8 @@ export function MetaMetricsProvider ({ children }) { ...overrides, }) } + + return undefined }, [ network, environmentType, diff --git a/ui/app/css/itcss/generic/index.scss b/ui/app/css/base-styles.scss similarity index 65% rename from ui/app/css/itcss/generic/index.scss rename to ui/app/css/base-styles.scss index 64c9688f6..8b2220f9c 100644 --- a/ui/app/css/itcss/generic/index.scss +++ b/ui/app/css/base-styles.scss @@ -1,8 +1,4 @@ -/* - Generic - */ -@import './reset'; * { box-sizing: border-box; @@ -10,9 +6,7 @@ html, body { - font-family: Roboto, Arial; color: #4d4d4d; - font-weight: 400; width: 100%; height: 100%; margin: 0; @@ -25,27 +19,38 @@ html { min-height: 500px; } -.app-root { - overflow: hidden; - position: relative; -} - -.app-primary { - display: flex; -} - .mouse-user-styles { button:focus, input:focus, textarea:focus, .unit-input__input, - .account-list-item__account-primary-balance, - .account-list-item__input, .currency-display__input { outline: none; } } +/* + This error class is used in the following files still: + /ui/app/pages/create-account/connect-hardware/index.js + /ui/app/pages/create-account/import-account/json.js + /ui/app/pages/create-account/import-account/private-key.js + /ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/import-with-seed-phrase.component.js + /ui/app/pages/keychains/restore-vault.js +*/ +.error { + color: #f7861c; + margin-bottom: 9px; +} + +/* + This warning class is used in the following files still: + /ui/app/pages/create-account/import-account/json.js + /ui/app/pages/confirm-add-suggested-token/confirm-add-suggested-token.component.js +*/ +.warning { + color: #ffae00; +} + /* stylelint-disable */ #app-content { overflow-x: hidden; @@ -121,19 +126,8 @@ input.form-control { } } -.hide-text-overflow { - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; +/** Default Typography on base elements **/ +* { + font-family: $font-family; } -.pinned-to-bottom { - position: absolute; - bottom: 0; -} - -.pinned-to-bottom-right { - position: absolute; - bottom: 0; - right: 0; -} diff --git a/ui/app/css/design-system/breakpoints.scss b/ui/app/css/design-system/breakpoints.scss new file mode 100644 index 000000000..80a4176b0 --- /dev/null +++ b/ui/app/css/design-system/breakpoints.scss @@ -0,0 +1,6 @@ +/* +Responsive Breakpoints +*/ +$break-small: 575px; +$break-midpoint: 780px; +$break-large: 576px; diff --git a/ui/app/css/variables/colors.scss b/ui/app/css/design-system/colors.scss similarity index 100% rename from ui/app/css/variables/colors.scss rename to ui/app/css/design-system/colors.scss diff --git a/ui/app/css/design-system/deprecated-colors.scss b/ui/app/css/design-system/deprecated-colors.scss new file mode 100644 index 000000000..c65f0bfa0 --- /dev/null +++ b/ui/app/css/design-system/deprecated-colors.scss @@ -0,0 +1,48 @@ +/** + These colors are either deprecated or will move into colors.scss + when approved for the design system +**/ + +// Base Colors +$white: #fff; +$black: #000; +$orange: #ffa500; +$red: #f00; +$gray: #808080; + +/* + Colors + http://chir.ag/projects/name-that-color + */ +$gallery: #efefef; +$wild-sand: #f6f6f6; +$dusty-gray: #9b9b9b; +$alto: #dedede; +$alabaster: #fafafa; +$silver-chalice: #aeaeae; +$tundora: #4d4d4d; +$nile-blue: #1b344d; +$scorpion: #5d5d5d; +$silver: #cdcdcd; +$caribbean-green: #02c9b1; +$monzo: #d0021b; +$crimson: #e91550; +$blue-lagoon: #038789; +$purple: #690496; +$tulip-tree: #ebb33f; +$malibu-blue: #7ac9fd; +$athens-grey: #e9edf0; +$geyser: #d2d8dd; +$manatee: #93949d; +$spindle: #c7ddec; +$mid-gray: #5b5d67; +$cape-cod: #38393a; +$dodger-blue: #3099f2; +$ecstasy: #f7861c; +$linen: #fdf4f4; +$oslo-gray: #8c8e94; +$polar: #fafcfe; +$blizzard-blue: #bfdef3; +$mischka: #dddee9; +$web-orange: #f2a202; +$mercury: #e5e5e5; diff --git a/ui/app/css/design-system/index.scss b/ui/app/css/design-system/index.scss new file mode 100644 index 000000000..2d85fcae3 --- /dev/null +++ b/ui/app/css/design-system/index.scss @@ -0,0 +1,5 @@ +@import 'breakpoints'; +@import 'colors'; +@import 'deprecated-colors'; +@import 'typography'; +@import 'z-index'; diff --git a/ui/app/css/design-system/typography.scss b/ui/app/css/design-system/typography.scss new file mode 100644 index 000000000..70cc4bef4 --- /dev/null +++ b/ui/app/css/design-system/typography.scss @@ -0,0 +1,151 @@ +$fa-font-path: 'fonts/fontawesome'; + +@import '../../../../node_modules/@fortawesome/fontawesome-free/scss/fontawesome'; +@import '../../../../node_modules/@fortawesome/fontawesome-free/scss/solid'; +@import '../../../../node_modules/@fortawesome/fontawesome-free/scss/regular'; + +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 100; + src: local('Roboto Thin'), local('Roboto-Thin'), url('fonts/Roboto/Roboto-Thin.ttf') format('truetype'); +} + +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 300; + src: local('Roboto Light'), local('Roboto-Light'), url('fonts/Roboto/Roboto-Light.ttf') format('truetype'); +} + +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 400; + src: local('Roboto'), local('Roboto-Regular'), url('fonts/Roboto/Roboto-Regular.ttf') format('truetype'); +} + +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 500; + src: local('Roboto Medium'), local('Roboto-Medium'), url('fonts/Roboto/Roboto-Medium.ttf') format('truetype'); +} + +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 700; + src: local('Roboto Bold'), local('Roboto-Bold'), url('fonts/Roboto/Roboto-Bold.ttf') format('truetype'); +} + +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 900; + src: local('Roboto Black'), local('Roboto-Black'), url('fonts/Roboto/Roboto-Black.ttf') format('truetype'); +} + +@font-face { + font-family: 'Euclid'; + font-style: normal; + font-weight: 400; + src: url('fonts/Euclid/EuclidCircularB-Regular-WebXL.ttf') format('truetype'); +} + +@font-face { + font-family: 'Euclid'; + font-style: italic; + font-weight: 400; + src: url('fonts/Euclid/EuclidCircularB-RegularItalic-WebXL.ttf') format('truetype'); +} + +@font-face { + font-family: 'Euclid'; + font-style: normal; + font-weight: 700; + src: url('fonts/Euclid/EuclidCircularB-Bold-WebXL.ttf') format('truetype'); +} + +$font-family: Euclid, Roboto, Helvetica, Arial, sans-serif; + +// Typography +@mixin H1 { + font-style: normal; + font-weight: normal; + font-size: 2.5rem; + font-family: $font-family; + line-height: 140%; +} + + +@mixin H2 { + font-style: normal; + font-weight: normal; + font-size: 2rem; + font-family: $font-family; + line-height: 140%; +} + +@mixin H3 { + font-style: normal; + font-weight: normal; + font-size: 1.5rem; + font-family: $font-family; + line-height: 140%; +} + +@mixin H4 { + font-style: normal; + font-weight: normal; + font-size: 1.125rem; + font-family: $font-family; + line-height: 140%; +} + +@mixin H5 { + font-style: normal; + font-weight: normal; + font-size: 1rem; + font-family: $font-family; + line-height: 140%; +} + +@mixin H6 { + font-style: normal; + font-weight: normal; + font-size: 0.875rem; // 14px @default + line-height: 140%; +} + +@mixin Paragraph { + font-style: normal; + font-weight: normal; + font-size: 1rem; + font-family: $font-family; + line-height: 140%; +} + +@mixin H7 { + font-style: normal; + font-weight: normal; + font-size: 0.75rem; + font-family: $font-family; + line-height: 140%; +} + +@mixin H8 { + font-style: normal; + font-weight: normal; + font-size: 0.625rem; + font-family: $font-family; + line-height: 140%; +} + +@mixin H9 { + font-style: normal; + font-weight: normal; + font-size: 0.5rem; + font-family: $font-family; + line-height: 140%; +} diff --git a/ui/app/css/design-system/z-index.scss b/ui/app/css/design-system/z-index.scss new file mode 100644 index 000000000..38086904a --- /dev/null +++ b/ui/app/css/design-system/z-index.scss @@ -0,0 +1,12 @@ +/* + Z-Indicies +*/ +$dropdown-z-index: 30; +$token-icon-z-index: 15; +$container-z-index: 15; +$header-z-index: 12; +$mobile-header-z-index: 26; +$main-container-z-index: 18; +$send-card-z-index: 20; +$sidebar-z-index: 26; +$sidebar-overlay-z-index: 25; diff --git a/ui/app/css/index.scss b/ui/app/css/index.scss index d757a2374..164d04b07 100644 --- a/ui/app/css/index.scss +++ b/ui/app/css/index.scss @@ -4,7 +4,12 @@ They are included first because they will be used to replace bad variable names in itcss prior to it being fully removed from the system. */ -@import './variables/index'; +@import './reset.scss'; +@import './design-system/index'; +@import './base-styles.scss'; +@import '../components/app/app-components'; +@import '../components/ui/ui-components'; +@import '../pages/pages'; /* ITCSS @@ -17,9 +22,12 @@ */ @import './itcss/settings/index'; @import './itcss/tools/index'; -@import './itcss/generic/index'; @import './itcss/objects/index'; @import './itcss/components/index'; @import './itcss/trumps/index'; -// Other imports + +/* + Third Party Library Styles +*/ +@import '../../../node_modules/react-tippy/dist/tippy'; @import '../../../node_modules/react-select/dist/react-select'; diff --git a/ui/app/css/itcss/components/account-dropdown.scss b/ui/app/css/itcss/components/account-dropdown.scss deleted file mode 100644 index 1d7baf7b6..000000000 --- a/ui/app/css/itcss/components/account-dropdown.scss +++ /dev/null @@ -1,110 +0,0 @@ -.account-dropdown-name { - font-family: Roboto; -} - -.account-dropdown-balance { - color: $dusty-gray; - line-height: 19px; -} - -.account-dropdown-edit-button { - color: $dusty-gray; - font-family: Roboto; - - &:hover { - color: $white; - } -} - -.account-list-item { - &__top-row { - display: flex; - margin-top: 10px; - margin-left: 8px; - position: relative; - } - - &__tooltip-wrapper { - left: -10px; - } - - &__account-balances { - height: auto; - border: none; - background-color: transparent; - color: #9b9b9b; - margin-left: 34px; - margin-top: 4px; - position: relative; - } - - &__primary-cached-container { - display: flex; - } - - &__cached-star { - margin-left: 4px; - } - - &__cached-balances { - div:first-of-type { - color: $web-orange; - } - - div:last-of-type { - color: rgba(220, 153, 18, 0.6901960784313725); - } - } - - &__account-name { - font-size: 16px; - margin-left: 8px; - } - - &__icon { - position: absolute; - right: 12px; - top: 1px; - } - - &__account-primary-balance, - &__account-secondary-balance { - font-family: Roboto; - line-height: 16px; - font-size: 12px; - } - - &__balance-flag { - position: absolute; - top: 3px; - left: -8px; - color: $primary-blue; - } - - &__account-primary-balance { - color: $scorpion; - border: none; - } - - &__account-secondary-balance { - color: $dusty-gray; - } - - &__account-address { - margin-left: 35px; - width: 80%; - overflow: hidden; - text-overflow: ellipsis; - } - - &__dropdown { - &:hover { - background: rgba($alto, 0.2); - cursor: pointer; - - input { - background: rgba($alto, 0.1); - } - } - } -} diff --git a/ui/app/css/itcss/components/confirm.scss b/ui/app/css/itcss/components/confirm.scss deleted file mode 100644 index 7a034e4e9..000000000 --- a/ui/app/css/itcss/components/confirm.scss +++ /dev/null @@ -1,350 +0,0 @@ -.confirm-screen-container { - position: relative; - align-items: center; - font-family: Roboto; - flex: 1 0 auto; - flex-flow: column nowrap; - box-shadow: 0 2px 4px 0 rgba($black, 0.08); - border-radius: 8px; - display: flex; - - @media screen and (max-width: 575px) { - width: 100%; - box-shadow: initial; - } -} - -.notification { - .confirm-screen-wrapper { - @media screen and (max-width: $break-small) { - height: calc(100vh - 85px); - } - } -} - -.confirm-screen-wrapper { - height: 100%; - width: 380px; - background-color: $white; - display: flex; - flex-flow: column nowrap; - z-index: 25; - align-items: center; - font-family: Roboto; - position: relative; - overflow-y: auto; - overflow-x: hidden; - border-top-left-radius: 8px; - border-top-right-radius: 8px; - - @media screen and (max-width: $break-small) { - width: 100%; - overflow-x: hidden; - overflow-y: auto; - top: 0; - box-shadow: none; - height: calc(100vh - 58px - 85px); - border-top-left-radius: 0; - border-top-right-radius: 0; - } -} - -.confirm-screen-wrapper > .confirm-screen-total-box { - margin-left: 10px; - margin-right: 10px; -} - -.confirm-screen-wrapper > .confirm-memo-wrapper { - margin: 0; -} - -.confirm-screen-header { - height: 88px; - background-color: $athens-grey; - position: relative; - display: flex; - justify-content: center; - align-items: center; - font-size: 22px; - line-height: 29px; - width: 100%; - padding: 25px 0; - flex: 0 0 auto; - - @media screen and (max-width: $break-small) { - font-size: 20px; - } -} - -.confirm-screen-header-tip { - height: 25px; - width: 25px; - background: $athens-grey; - position: absolute; - transform: rotate(45deg); - top: 71px; - left: 0; - right: 0; - margin: 0 auto; -} - -.confirm-screen-title { - line-height: 27px; - - @media screen and (max-width: $break-small) { - margin-left: 22px; - margin-right: 8px; - } -} - -.confirm-screen-back-button { - color: $primary-blue; - font-family: Roboto; - font-size: 1rem; - position: absolute; - top: 38px; - right: 38px; - background: none; -} - -.confirm-screen-account-wrapper { - display: flex; - flex-direction: column; - align-items: center; -} - -.confirm-screen-account-name { - margin-top: 12px; - font-size: 14px; - line-height: 19px; - color: $scorpion; - text-align: center; -} - -.confirm-screen-row-info { - font-size: 16px; - line-height: 21px; -} - -.confirm-screen-account-number { - font-size: 10px; - line-height: 16px; - color: $dusty-gray; - text-align: center; - height: 16px; -} - -.confirm-send-ether, -.confirm-send-token { - i.fa-arrow-right { - align-self: start; - margin: 24px 14px 0 !important; - } -} - -.confirm-screen-identicons { - margin-top: 24px; - flex: 0 0 auto; - - i.fa-arrow-right { - align-self: start; - margin: 42px 14px 0; - } - - i.fa-file-text-o { - font-size: 60px; - margin: 16px 8px 0 8px; - text-align: center; - } -} - -.confirm-screen-sending-to-message { - text-align: center; - font-size: 16px; - margin-top: 30px; - font-family: Roboto; - font-weight: 300; -} - -.confirm-screen-send-amount { - color: $scorpion; - margin-top: 12px; - text-align: center; - font-size: 40px; - line-height: 53px; - flex: 0 0 auto; -} - -.confirm-screen-send-amount-currency { - font-size: 20px; - line-height: 20px; - text-align: center; - flex: 0 0 auto; -} - -.confirm-memo-wrapper { - min-height: 24px; - width: 100%; - border-bottom: 1px solid $alto; - flex: 0 0 auto; -} - -.confirm-screen-send-memo { - color: $scorpion; - font-size: 16px; - line-height: 19px; - font-weight: 400; -} - -.confirm-screen-label { - font-size: 16px; - line-height: 40px; - color: $scorpion; - text-align: left; -} - -section .confirm-screen-account-name, -section .confirm-screen-account-number, -.confirm-screen-row-info, -.confirm-screen-row-detail { - text-align: left; -} - -.confirm-screen-rows { - display: flex; - flex-flow: column nowrap; - width: 100%; - flex: 0 0 auto; -} - -.confirm-screen-section-column { - flex: 0.5; -} - -.confirm-screen-row { - display: flex; - flex-flow: row nowrap; - width: 100%; - align-items: center; - padding: 12px; - padding-left: 35px; - font-size: 16px; - line-height: 22px; - - &:not(:last-of-type) { - border-bottom: 1px solid $alto; - } -} - -@media screen and (max-width: 379px) { - .confirm-screen-row { - span.confirm-screen-section-column { - flex: 0.4; - } - - div.confirm-screen-section-column { - flex: 0.6; - } - - .currency-display__input { - font-size: 14px; - } - } -} - -.confirm-screen-row-detail { - font-size: 12px; - line-height: 16px; - color: $dusty-gray; -} - -.confirm-screen-total-box { - background-color: $wild-sand; - position: relative; - - .confirm-screen-label { - line-height: 21px; - } - - .confirm-screen-row-detail { - color: $scorpion; - } - - &__subtitle { - font-size: 12px; - line-height: 16px; - } - - .confirm-screen-row-info { - font-size: 16px; - font-weight: 500; - line-height: 21px; - } -} - -.confirm-screen-error { - font-size: 12px; - line-height: 12px; - color: #f00; - position: absolute; - right: 12px; - width: 80px; - text-align: right; -} - -.confirm-screen-row.confirm-screen-total-box { - .confirm-screen-section-column--with-error { - flex: 0.6; - } -} - -@media screen and (max-width: 379px) { - .confirm-screen-row.confirm-screen-total-box { - .confirm-screen-section-column--with-error { - flex: 0.4; - } - } -} - -.confirm-screen-form { - position: relative; - - .confirm-screen-error { - right: 0; - width: 100%; - margin-top: 7px; - text-align: center; - } -} - -.confirm-screen-confirm-button { - height: 50px; - border-radius: 4px; - background-color: #02c9b1; - font-size: 16px; - color: $white; - text-align: center; - font-family: Roboto; - padding-top: 15px; - padding-bottom: 15px; - border-width: 0; - box-shadow: none; - flex: 1 0 auto; - margin: 0 5px; -} - -.btn-light.confirm-screen-cancel-button { - height: 50px; - background: none; - border: none; - opacity: 1; - font-family: Roboto; - border-width: 0; - padding-top: 15px; - padding-bottom: 15px; - font-size: 16px; - box-shadow: none; - cursor: pointer; - flex: 1 0 auto; - margin: 0 5px; -} diff --git a/ui/app/css/itcss/components/currency-display.scss b/ui/app/css/itcss/components/currency-display.scss deleted file mode 100644 index 9ece7a672..000000000 --- a/ui/app/css/itcss/components/currency-display.scss +++ /dev/null @@ -1,86 +0,0 @@ -.currency-display { - height: 54px; - border: 1px solid $alto; - border-radius: 4px; - background-color: $white; - color: $scorpion; - font-family: Roboto; - font-size: 16px; - padding: 8px 10px; - position: relative; - - &__primary-row { - display: flex; - } - - &__input { - color: $scorpion; - font-family: Roboto; - font-size: 16px; - line-height: 22px; - border: none; - max-width: 22ch; - } - - &__primary-currency { - color: $scorpion; - font-weight: 400; - font-family: Roboto; - font-size: 16px; - line-height: 22px; - } - - &__converted-row { - display: flex; - } - - &__converted-value, - &__converted-currency { - color: $dusty-gray; - font-family: Roboto; - font-size: 12px; - line-height: 12px; - } - - &__input-wrapper { - position: relative; - display: flex; - flex: 1; - max-width: 100%; - - input[type="number"] { - -moz-appearance: textfield; - } - - input[type="number"]::-webkit-inner-spin-button { - -webkit-appearance: none; - -moz-appearance: none; - display: none; - } - - input[type="number"]:hover::-webkit-inner-spin-button { - -webkit-appearance: none; - -moz-appearance: none; - display: none; - } - } - - &__currency-symbol { - margin-top: 1px; - color: $scorpion; - } - - .react-numeric-input { - input[type="number"]::-webkit-inner-spin-button { - -webkit-appearance: none; - -moz-appearance: none; - display: none; - } - - input[type="number"]:hover::-webkit-inner-spin-button { - -webkit-appearance: none; - -moz-appearance: none; - display: none; - } - } -} diff --git a/ui/app/css/itcss/components/index.scss b/ui/app/css/itcss/components/index.scss index b9a698503..b1726cf3e 100644 --- a/ui/app/css/itcss/components/index.scss +++ b/ui/app/css/itcss/components/index.scss @@ -1,32 +1,10 @@ -@import '../../../components/ui/button/buttons'; -@import '../../../components/ui/dialog/dialog'; -@import '../../../components/ui/snackbar/index'; -@import '../../../components/ui/list-item/index'; -@import '../../../components/ui/popover/index'; -@import '../../../components/ui/icon/preloader/index'; @import './footer'; @import './network'; -@import './modal'; -@import './alert'; @import './newui-sections'; -@import './account-dropdown'; @import './send'; -@import './confirm'; @import './loading-overlay'; // Tx List and Sections -@import './transaction-list'; -@import './sections'; -@import './currency-display'; -@import './menu'; @import './gas-slider'; -@import './tab-bar'; @import './simple-dropdown'; -@import './request-signature'; -@import './request-encryption-public-key'; -@import './request-decrypt-message'; -@import './editable-label'; @import './pages/index'; -@import './new-account'; -@import './tooltip'; -@import '../../../components/app/index'; diff --git a/ui/app/css/itcss/components/menu.scss b/ui/app/css/itcss/components/menu.scss deleted file mode 100644 index f2dfd8ca3..000000000 --- a/ui/app/css/itcss/components/menu.scss +++ /dev/null @@ -1,63 +0,0 @@ -.menu { - border-radius: 4px; - background: rgba($black, 0.8); - box-shadow: rgba($black, 0.15) 0 2px 2px 2px; - min-width: 150px; - color: $white; - - &__item { - padding: 18px; - display: flex; - flex-flow: row wrap; - align-items: center; - position: relative; - z-index: 201; - - @media screen and (max-width: 575px) { - padding: 14px; - } - - &--clickable { - cursor: pointer; - - &:hover { - background-color: rgba($white, 0.05); - } - - &:active { - background-color: rgba($white, 0.1); - } - } - - &__icon { - height: 16px; - width: 16px; - margin-right: 14px; - } - - &__text { - font-size: 16px; - line-height: 21px; - } - - &__subtext { - font-size: 12px; - padding: 5px 0 0 30px; - } - } - - &__divider { - background-color: $scorpion; - width: 100%; - height: 1px; - } - - &__close-area { - position: fixed; - width: 100%; - height: 100%; - top: 0; - left: 0; - z-index: 100; - } -} diff --git a/ui/app/css/itcss/components/modal.scss b/ui/app/css/itcss/components/modal.scss index 567e7a418..e69de29bb 100644 --- a/ui/app/css/itcss/components/modal.scss +++ b/ui/app/css/itcss/components/modal.scss @@ -1,549 +0,0 @@ -.modal { - z-index: 1050; - position: fixed; - width: 500px; - transform: translate3d(-50%, -50%, 0); - top: 50%; - left: 50%; - - .content { - margin: 0; - background-color: white; - animation-fill-mode: forwards; - } -} - -.backdrop { - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 1040; - background-color: #373a47; - animation-fill-mode: forwards; - animation-duration: 0.3s; -} - -.modal > div:focus { - outline: none !important; -} - -// Account Modal Container -.account-modal-container { - display: flex; - flex-direction: column; - justify-content: flex-start; - align-items: center; - position: relative; - padding: 5px 0 31px 0; - border: 1px solid $silver; - border-radius: 4px; - font-family: Roboto; - - button { - cursor: pointer; - } -} - -.account-modal-back { - color: $dusty-gray; - position: absolute; - top: 13px; - left: 17px; - cursor: pointer; - - &__text { - margin-top: 2px; - font-family: Roboto; - font-size: 14px; - line-height: 18px; - } -} - -.account-modal-close { - font-size: 40px; - background-color: transparent; - color: $dusty-gray; - position: absolute; - top: 10px; - right: 12px; -} - -.account-modal-close::after { - content: '\00D7'; -} - -.account-modal-container .identicon { - position: relative; - left: 0; - right: 0; - margin: 0 auto; - top: -32px; - margin-bottom: -32px; -} - - -// Account Details Modal - -.account-modal-container { - .qr-header { - margin-top: 9px; - font-size: 20px; - } - - .qr-wrapper { - margin-top: 5px; - } - - .ellip-address-wrapper { - display: flex; - justify-content: center; - border: 1px solid $alto; - padding: 5px 10px; - font-family: Roboto; - margin-top: 7px; - width: 286px; - } - - .account-modal__button { - margin-top: 17px; - padding: 10px 22px; - width: 286px; - } -} - -.account-modal-divider { - width: 100%; - height: 1px; - margin: 19px 0 8px 0; - background-color: $alto; -} - -// Export Private Key Modal - -.account-modal-container .account-name { - margin-top: 9px; - font-size: 20px; -} - -.account-modal-container .modal-body-title { - margin-top: 16px; - margin-bottom: 16px; - font-size: 18px; -} - -.account-modal__name { - margin-top: 9px; - font-size: 20px; -} - -.private-key-password { - display: flex; - flex-direction: column; -} - -.private-key-password-label, -.private-key-password-error { - color: $scorpion; - font-size: 14px; - line-height: 18px; - margin-bottom: 10px; -} - -.private-key-password-error { - color: $crimson; - margin-bottom: 0; -} - -.private-key-password-input { - padding: 10px 0 13px 17px; - font-size: 16px; - line-height: 21px; - width: 291px; - height: 44px; -} - -.private-key-password::-webkit-input-placeholder { - color: $dusty-gray; - font-family: Roboto; -} - -.private-key-password-warning { - border-radius: 8px; - background-color: #fff6f6; - font-size: 12px; - font-weight: 500; - line-height: 15px; - color: $crimson; - width: 292px; - padding: 9px 15px; - margin-top: 18px; - font-family: Roboto; -} - -.export-private-key-buttons { - display: flex; - flex-direction: row; - justify-content: center; -} - -.export-private-key__button { - margin-top: 17px; - width: 141px; - min-width: initial; -} - -.export-private-key__button--cancel { - margin-right: 15px; -} - -.private-key-password-display-wrapper { - height: 80px; - width: 291px; - border: 1px solid $silver; - border-radius: 2px; -} - -.private-key-password-display-textarea { - color: $crimson; - font-family: Roboto; - font-size: 16px; - line-height: 21px; - border: none; - height: 75px; - width: 100%; - overflow: hidden; - resize: none; - padding: 9px 13px 8px; -} - -.modal-close-x::after { - content: '\00D7'; - font-size: 2em; - color: $dusty-gray; - position: absolute; - top: 25px; - right: 17.5px; - font-family: sans-serif; - cursor: pointer; -} - -// Hide token confirmation - -.hide-token-confirmation { - min-height: 250.72px; - border-radius: 4px; - background-color: $white; - box-shadow: 0 1px 7px 0 rgba(0, 0, 0, 0.5); - - &__container { - padding: 24px 27px 21px; - display: flex; - flex-direction: column; - align-items: center; - } - - &__identicon { - margin-bottom: 10px; - } - - &__symbol { - color: $tundora; - font-family: Roboto; - font-size: 16px; - line-height: 24px; - text-align: center; - margin-bottom: 7.5px; - } - - &__title { - height: 30px; - width: 271.28px; - color: $tundora; - font-family: Roboto; - font-size: 22px; - line-height: 30px; - text-align: center; - margin-bottom: 10.5px; - } - - &__copy { - height: 41px; - width: 318px; - color: $scorpion; - font-family: Roboto; - font-size: 14px; - line-height: 18px; - text-align: center; - } - - &__buttons { - display: flex; - flex-direction: row; - justify-content: center; - margin-top: 15px; - width: 100%; - } - - &__button { - @include paragraph; - - @extend %button; - - width: 141px; - margin: 0 5px; - } -} - -//Notification Modal - -.notification-modal { - &__wrapper { - display: flex; - flex-direction: column; - justify-content: flex-start; - align-items: center; - position: relative; - border: 1px solid $alto; - box-shadow: 0 0 2px 2px $alto; - font-family: Roboto; - } - - &__header { - background: $wild-sand; - width: 100%; - display: flex; - justify-content: center; - padding: 30px; - font-size: 22px; - color: $nile-blue; - } - - &__message { - padding: 20px; - width: 100%; - display: flex; - justify-content: center; - font-size: 17px; - color: $nile-blue; - } - - &__buttons { - display: flex; - justify-content: space-evenly; - width: 100%; - margin-bottom: 24px; - padding: 0 42px; - - &__btn { - cursor: pointer; - } - } - - &__link { - color: $primary-blue; - } -} - -// Deposit Ether Modal -.deposit-ether-modal { - border-radius: 8px; - font-family: Roboto; - display: flex; - flex-flow: column; - height: 100%; - - &__header { - width: 100%; - border-radius: 8px 8px 0 0; - background-color: $mid-gray; - display: flex; - position: relative; - padding: 25px; - flex-flow: column; - align-items: flex-start; - - &__title { - color: $white; - font-size: 24px; - line-height: 32px; - } - - &__description { - color: $white; - font-size: 16px; - line-height: 22px; - margin-top: 10px; - } - - &__close::after { - content: '\00D7'; - font-size: 2em; - color: $white; - position: absolute; - top: 20.8px; - right: 28px; - cursor: pointer; - } - } - - &__buy-rows { - width: 100%; - padding: 0 30px; - display: flex; - flex-flow: column nowrap; - flex: 1; - align-items: center; - - @media screen and (max-width: 575px) { - height: 0; - } - } - - &__logo { - height: 60px; - background-repeat: no-repeat; - background-size: contain; - background-position: center; - width: 100%; - display: flex; - justify-content: center; - align-items: center; - } - - &__buy-row { - border-bottom: 1px solid $alto; - display: flex; - justify-content: space-between; - align-items: center; - flex: 1 0 auto; - padding: 30px 0 20px; - min-height: 170px; - - @media screen and (max-width: 575px) { - min-height: 270px; - flex-flow: column; - justify-content: flex-start; - } - - &__back { - position: absolute; - top: 10px; - left: 0; - } - - &__logo-container { - display: flex; - justify-content: center; - flex: 0 0 auto; - padding: 0 20px; - - @media screen and (min-width: 576px) { - width: 12rem; - } - - @media screen and (max-width: 575px) { - width: 100%; - max-height: 6rem; - padding-bottom: 20px; - } - } - - &__right { - display: flex; - } - - &__description { - color: $cape-cod; - padding-bottom: 20px; - align-self: flex-start; - - @media screen and (min-width: 575px) { - width: 15rem; - } - - &__title { - font-size: 20px; - line-height: 30px; - } - - &__text { - font-size: 14px; - line-height: 22px; - margin-top: 7px; - } - } - - &__button { - display: flex; - justify-content: flex-end; - - @media screen and (min-width: 575px) { - min-width: 300px; - } - } - } - - &__buy-row:last-of-type { - border-bottom: 0; - } - - &__deposit-button { - width: 257px; - } - - .simple-dropdown { - color: #5b5d67; - font-size: 16px; - line-height: 21px; - border: 1px solid #d8d8d8; - background-color: #fff; - text-align: center; - width: 100%; - height: 45px; - line-height: 44px; - font-family: Roboto; - font-weight: 300; - } - - .simple-dropdown__selected { - text-align: center; - } -} - -//Notification Modal - -.notification-modal-wrapper { - display: flex; - flex-direction: column; - justify-content: flex-start; - align-items: center; - position: relative; - border: 1px solid $alto; - box-shadow: 0 0 2px 2px $alto; - font-family: Roboto; -} - -.notification-modal-header { - background: $wild-sand; - width: 100%; - display: flex; - justify-content: center; - align-items: center; - padding: 30px; - font-size: 22px; - color: $nile-blue; -} - -.notification-modal-message { - padding: 20px; -} - -.notification-modal-message { - width: 100%; - display: flex; - justify-content: center; - font-size: 17px; - color: $nile-blue; -} diff --git a/ui/app/css/itcss/components/network.scss b/ui/app/css/itcss/components/network.scss index b00fa5ec1..31ca8c201 100644 --- a/ui/app/css/itcss/components/network.scss +++ b/ui/app/css/itcss/components/network.scss @@ -66,7 +66,6 @@ .network-name { padding: 0 4px; - font-family: Roboto; font-size: 12px; line-height: 14px; flex: 1 1 auto; @@ -167,7 +166,6 @@ height: 25px; width: 120px; color: $white; - font-family: Roboto; font-size: 18px; line-height: 25px; text-align: center; @@ -177,7 +175,6 @@ min-height: 36px; width: 265px; color: $dusty-gray; - font-family: Roboto; font-size: 14px; line-height: 18px; } diff --git a/ui/app/css/itcss/components/newui-sections.scss b/ui/app/css/itcss/components/newui-sections.scss index 2572c5fa4..57c1f6d77 100644 --- a/ui/app/css/itcss/components/newui-sections.scss +++ b/ui/app/css/itcss/components/newui-sections.scss @@ -17,7 +17,6 @@ $sub-mid-size-breakpoint-range: "screen and (min-width: #{$break-large}) and (ma // Main container .main-container { z-index: $main-container-z-index; - font-family: Roboto; } .main-container::-webkit-scrollbar { @@ -120,7 +119,6 @@ $sub-mid-size-breakpoint-range: "screen and (min-width: #{$break-large}) and (ma .unlock-screen-container { z-index: $main-container-z-index; - font-family: Roboto; display: flex; justify-content: center; align-items: center; diff --git a/ui/app/css/itcss/components/sections.scss b/ui/app/css/itcss/components/sections.scss deleted file mode 100644 index f9bba2827..000000000 --- a/ui/app/css/itcss/components/sections.scss +++ /dev/null @@ -1,435 +0,0 @@ -// Old scss, do not lint - clean up later -/* stylelint-disable */ - - -/* -App Sections - TODO: Move into separate files. -*/ - -/* initialize */ -textarea.twelve-word-phrase { - padding: 12px; - width: 300px; - height: 140px; - font-size: 16px; - background: $white; - resize: none; -} - -.initialize-screen { - width: 100%; - z-index: $main-container-z-index; - background: #f7f7f7; -} - -.initialize-screen hr { - width: 60px; - margin: 12px; - border-color: #f7861c; - border-style: solid; -} - -.initialize-screen label { - margin-top: 20px; -} - -.initialize-screen button.create-vault { - margin-top: 40px; -} - -.initialize-screen .warning { - font-size: 14px; - margin: 0 16px; -} - -/* unlock */ -.error { - color: #f7861c; - margin-bottom: 9px; -} - -.warning { - color: #ffae00; -} - -.lock { - width: 50px; - height: 50px; -} - -.lock.locked { - transform: scale(1.5); - opacity: 0; - transition: opacity 400ms ease-in, transform 400ms ease-in; -} - -.lock.unlocked { - transform: scale(1); - opacity: 1; - transition: opacity 500ms ease-out, transform 500ms ease-out, background 200ms ease-in; -} - -.lock.locked .lock-top { - transform: scaleX(1) translateX(0); - transition: transform 250ms ease-in; -} - -.lock.unlocked .lock-top { - transform: scaleX(-1) translateX(-12px); - transition: transform 250ms ease-in; -} - -.lock.unlocked:hover { - border-radius: 4px; - background: #e5e5e5; - border: 1px solid #b1b1b1; -} - -.lock.unlocked:active { - background: #c3c3c3; -} - -.section-title .fa-arrow-left { - margin: -2px 8px 0 -8px; -} - -.sizing-input { - font-size: 14px; - height: 30px; - padding-left: 5px; -} - -.editable-label { - display: flex; -} - -/* accounts */ - -.accounts-section { - margin: 0 0; -} - -.accounts-section .horizontal-line { - margin: 0 18px; -} - -.accounts-list-option { - height: 120px; -} - -.accounts-list-option .identicon-wrapper { - width: 100px; -} - -.unconftx-link { - margin-top: 24px; - cursor: pointer; -} - -.unconftx-link .fa-arrow-right { - margin: 0 -8px 0 8px; -} - -/* identity panel */ - -.identity-panel { - font-weight: 500; -} - -.identity-panel .identicon-wrapper { - margin: 4px; - margin-top: 8px; - display: flex; - align-items: center; -} - -.identity-panel .identicon-wrapper span { - margin: 0 auto; -} - -.identity-panel .identity-data { - margin: 8px 8px 8px 18px; -} - -.identity-panel i { - margin-top: 32px; - margin-right: 6px; - color: #b9b9b9; -} - -.identity-panel .arrow-right { - padding-left: 18px; - width: 42px; - min-width: 18px; - height: 100%; -} - -.identity-copy.flex-column { - flex: 0.25 0 auto; - justify-content: center; -} - -/* accounts screen */ - -.identity-section { -} - -.identity-section .identity-panel { - background: #e9e9e9; - border-bottom: 1px solid #b1b1b1; - cursor: pointer; -} - -.identity-section .identity-panel.selected { - background: $white; - color: #f3c83e; -} - -.identity-section .identity-panel.selected .identicon { - border-color: $orange; -} - -.identity-section .accounts-list-option:hover, -.identity-section .accounts-list-option.selected { - background: $white; -} - -/* account detail screen */ - -.account-detail-section { - display: flex; - flex-wrap: wrap; - overflow-y: auto; - flex-direction: inherit; -} - -.grow-tenx { - flex-grow: 10; -} - -.name-label { -} - -.unapproved-tx-icon { - height: 16px; - width: 16px; - background: rgb(47, 174, 244); - border-color: $silver-chalice; - border-radius: 13px; -} - -.edit-text { - height: 100%; - visibility: hidden; -} - -.editing-label { - display: flex; - justify-content: flex-start; - margin-left: 50px; - margin-bottom: 2px; - font-size: 11px; - text-rendering: geometricPrecision; - color: #f7861c; -} - -.name-label:hover .edit-text { - visibility: visible; -} - -/* tx confirm */ - -.unconftx-section input[type=password] { - height: 22px; - padding: 2px; - margin: 12px; - margin-bottom: 24px; - border-radius: 4px; - border: 2px solid #f3c83e; - background: #faf6f0; -} - -/* Info screen */ -.info-gray { - font-family: Roboto; - text-transform: uppercase; - color: $silver-chalice; -} - -.icon-size { - width: 20px; -} - -.info { - font-family: Roboto, Arial; - padding-bottom: 10px; - display: inline-block; - padding-left: 5px; -} - -/* buy eth warning screen */ -.custom-radios { - justify-content: space-around; - align-items: center; -} - -.custom-radio-selected { - width: 17px; - height: 17px; - border: solid; - border-style: double; - border-radius: 15px; - border-width: 5px; - background: rgba(247, 134, 28, 1); - border-color: #f7f7f7; -} - -.custom-radio-inactive { - width: 14px; - height: 14px; - border: solid; - border-width: 1px; - border-radius: 24px; - border-color: $silver-chalice; -} - -.radio-titles { - color: rgba(247, 134, 28, 1); -} - -.eth-warning { - transition: opacity 400ms ease-in, transform 400ms ease-in; -} - -.buy-subview { - transition: opacity 400ms ease-in, transform 400ms ease-in; -} - -.input-container:hover .edit-text { - visibility: visible; -} - -.buy-inputs { - font-family: Roboto; - font-size: 13px; - height: 20px; - background: transparent; - box-sizing: border-box; - border: solid; - border-color: transparent; - border-width: 0.5px; - border-radius: 2px; -} - -.input-container:hover .buy-inputs { - box-sizing: inherit; - border: solid; - border-color: #f7861c; - border-width: 0.5px; - border-radius: 2px; -} - -.buy-inputs:focus { - border: solid; - border-color: #f7861c; - border-width: 0.5px; - border-radius: 2px; -} - -.activeForm { - background: #f7f7f7; - border: none; - border-radius: 8px 8px 0 0; - width: 50%; - text-align: center; - padding-bottom: 4px; -} - -.inactiveForm { - border: none; - border-radius: 8px 8px 0 0; - width: 50%; - text-align: center; - padding-bottom: 4px; -} - -.ex-coins { - font-family: Roboto; - text-transform: uppercase; - text-align: center; - font-size: 33px; - width: 118px; - height: 42px; - padding: 1px; - color: #4d4d4d; -} - -.marketinfo { - font-family: Roboto; - color: $silver-chalice; - font-size: 15px; - line-height: 17px; -} - -#fromCoin::-webkit-calendar-picker-indicator { - display: none; -} - -#coinList { - width: 400px; - height: 500px; - overflow: scroll; -} - -.icon-control .fa-sync { - visibility: hidden; -} - -.icon-control:hover .fa-sync { - visibility: visible; -} - -.icon-control:hover .fa-chevron-right { - visibility: hidden; -} - -.inactive { - color: $silver-chalice; -} - -.inactive button { - background: $silver-chalice; - color: $white; -} - -.qr-ellip-address, -.ellip-address { - /*rtl:ignore*/ - direction: ltr; - overflow: hidden; - text-overflow: ellipsis; - width: 100%; -} - -.qr-header { - font-size: 25px; - margin-top: 40px; -} - -.qr-message { - font-size: 12px; - color: #f7861c; -} - -div.message-container > div:first-child { - margin-top: 18px; - font-size: 15px; - color: #4d4d4d; -} - -.pop-hover:hover { - transform: scale(1.1); -} - -/* stylelint-enable */ diff --git a/ui/app/css/itcss/components/send.scss b/ui/app/css/itcss/components/send.scss index e82d938d6..df18572cd 100644 --- a/ui/app/css/itcss/components/send.scss +++ b/ui/app/css/itcss/components/send.scss @@ -2,7 +2,6 @@ display: flex; flex-flow: column nowrap; z-index: 25; - font-family: Roboto; @media screen and (max-width: $break-small) { width: 100%; @@ -76,7 +75,6 @@ margin: 4px 0 20px; font-size: 16px; line-height: 22.4px; - font-family: Roboto; } .send-screen-gas-input { @@ -186,7 +184,6 @@ padding: 13px 19px; font-size: 16px; border-radius: 4px; - font-family: Roboto; font-weight: 500; } @@ -316,7 +313,6 @@ display: flex; flex-flow: column nowrap; z-index: 25; - font-family: Roboto; &__content { width: 498px; @@ -407,7 +403,6 @@ flex-flow: column nowrap; z-index: 25; align-items: center; - font-family: Roboto; position: relative; @media screen and (max-width: $break-small) { @@ -588,7 +583,6 @@ &__form-label { color: $scorpion; - font-family: Roboto; font-size: 16px; line-height: 22px; width: 95px; @@ -602,7 +596,6 @@ border: 1px solid $alto; border-radius: 4px; background-color: $white; - font-family: Roboto; line-height: 16px; font-size: 12px; color: $tundora; @@ -745,7 +738,6 @@ background-color: $white; color: $tundora; padding: 10px; - font-family: Roboto; font-size: 16px; line-height: 21px; } @@ -763,14 +755,12 @@ background-color: $white; color: $tundora; padding: 10px; - font-family: Roboto; font-size: 16px; line-height: 21px; } } &__amount-max { - font-family: Roboto; font-size: 12px; position: relative; display: inline-block; @@ -873,7 +863,6 @@ border-radius: 4px; background-color: #fff; box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.14); - font-family: Roboto; display: flex; flex-flow: column; @@ -903,7 +892,6 @@ content: '\00D7'; font-size: 1.8em; color: $dusty-gray; - font-family: sans-serif; cursor: pointer; margin-right: 19.25px; } @@ -1000,7 +988,6 @@ &__title { height: 26px; color: $tundora; - font-family: Roboto; font-size: 20px; line-height: 26px; margin-top: 17px; @@ -1010,7 +997,6 @@ height: 38px; width: 314px; color: $tundora; - font-family: Roboto; font-size: 14px; line-height: 19px; margin-top: 17px; @@ -1101,7 +1087,6 @@ font-size: 1em; font-size: 14px; color: #2f9ae0; - font-family: Roboto; } .sliders-icon { diff --git a/ui/app/css/itcss/components/tab-bar.scss b/ui/app/css/itcss/components/tab-bar.scss deleted file mode 100644 index 2579b279f..000000000 --- a/ui/app/css/itcss/components/tab-bar.scss +++ /dev/null @@ -1,79 +0,0 @@ -.tab-bar { - display: flex; - flex-direction: column; - justify-content: flex-start; -} - -.tab-bar__tab { - display: flex; - flex-flow: row nowrap; - align-items: flex-start; - min-width: 0; - flex: 0 0 auto; - box-sizing: border-box; - font-size: 16px; - padding: 16px 24px; - opacity: 0.5; - transition: opacity 200ms ease-in-out; - - @media screen and (min-width: 576px) { - &:hover { - opacity: 0.4; - } - - &:active { - opacity: 0.6; - } - } - - @media screen and (max-width: 575px) { - font-size: 18px; - padding: 24px; - border-bottom: 1px solid $alto; - opacity: 1; - } - - &__content { - flex: 1 1 auto; - width: 0; - - &__description { - display: none; - - @media screen and (max-width: 575px) { - display: block; - font-size: 14px; - font-weight: 300; - margin-top: 8px; - min-height: 14px; - } - } - } - - &__caret { - display: none; - - @media screen and (max-width: 575px) { - display: block; - background-image: url('/images/caret-right.svg'); - width: 36px; - height: 36px; - opacity: 0.5; - background-size: contain; - background-repeat: no-repeat; - background-position: center; - - [dir='rtl'] & { - transform: rotate(180deg); - } - } - } - - &--active { - opacity: 1 !important; - } -} - -.tab-bar__grow-tab { - flex-grow: 1; -} diff --git a/ui/app/css/itcss/components/tooltip.scss b/ui/app/css/itcss/components/tooltip.scss deleted file mode 100644 index 97840ca1a..000000000 --- a/ui/app/css/itcss/components/tooltip.scss +++ /dev/null @@ -1,127 +0,0 @@ -@import '../../../../../node_modules/react-tippy/dist/tippy'; - -.metamask-tooltip { - padding: 5px !important; -} - -.tooltip { - position: absolute; - z-index: 1070; - display: block; - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-style: normal; - font-weight: normal; - letter-spacing: normal; - line-break: auto; - line-height: 1.42857143; - text-align: left; - text-decoration: none; - text-shadow: none; - text-transform: none; - white-space: normal; - word-break: normal; - word-spacing: normal; - word-wrap: normal; - font-size: 12px; -} - -.tooltip.top { - margin-top: -3px; - padding: 5px 0; -} - -.tooltip.right { - margin-left: 3px; - padding: 0 5px; -} - -.tooltip.bottom { - margin-top: 3px; - padding: 5px 0; -} - -.tooltip.left { - margin-left: -3px; - padding: 0 5px; -} - -.tooltip-inner { - max-width: 200px; - padding: 3px 8px; - color: #fff; - text-align: center; - background-color: #000; - border-radius: 4px; -} - -.tooltip-arrow { - position: absolute; - width: 0; - height: 0; - border-color: transparent; - border-style: solid; -} - -.tooltip.top .tooltip-arrow { - bottom: 0; - left: 50%; - margin-left: -5px; - border-width: 5px 5px 0; - border-top-color: #000; -} - -.tooltip.top-left .tooltip-arrow { - bottom: 0; - right: 5px; - margin-bottom: -5px; - border-width: 5px 5px 0; - border-top-color: #000; -} - -.tooltip.top-right .tooltip-arrow { - bottom: 0; - left: 5px; - margin-bottom: -5px; - border-width: 5px 5px 0; - border-top-color: #000; -} - -.tooltip.right .tooltip-arrow { - top: 50%; - left: 0; - margin-top: -5px; - border-width: 5px 5px 5px 0; - border-right-color: #000; -} - -.tooltip.left .tooltip-arrow { - top: 50%; - right: 0; - margin-top: -5px; - border-width: 5px 0 5px 5px; - border-left-color: #000; -} - -.tooltip.bottom .tooltip-arrow { - top: 0; - left: 50%; - margin-left: -5px; - border-width: 0 5px 5px; - border-bottom-color: #000; -} - -.tooltip.bottom-left .tooltip-arrow { - top: 0; - right: 5px; - margin-top: -5px; - border-width: 0 5px 5px; - border-bottom-color: #000; -} - -.tooltip.bottom-right .tooltip-arrow { - top: 0; - left: 5px; - margin-top: -5px; - border-width: 0 5px 5px; - border-bottom-color: #000; -} diff --git a/ui/app/css/itcss/components/transaction-list.scss b/ui/app/css/itcss/components/transaction-list.scss deleted file mode 100644 index 486c48694..000000000 --- a/ui/app/css/itcss/components/transaction-list.scss +++ /dev/null @@ -1,299 +0,0 @@ -.tx-list-container { - height: 87.5%; - - @media screen and (min-width: $break-large) { - overflow-y: scroll; - } -} - -.tx-list-header-wrapper { - flex: 0 0 auto; -} - -.tx-list-header { - text-transform: capitalize; -} - -@media screen and (max-width: $break-small) { - .tx-list-header-wrapper { - margin-top: 0.2em; - margin-bottom: 0.6em; - justify-content: center; - flex: 0 0 auto; - } - - .tx-list-header { - align-self: center; - font-size: 12px; - color: $dusty-gray; - font-family: Roboto; - text-transform: uppercase; - } -} - -@media screen and (min-width: $break-large) { - .tx-list-header { - font-size: 16px; - margin: 1.1em 2.37em 0.8em; - } - - .tx-list-container::-webkit-scrollbar { - display: none; - } -} - -.tx-list-content-divider { - height: 1px; - background: rgb(231, 231, 231); - flex: 0 0 1px; - - @media screen and (max-width: $break-small) { - margin: 0.1em 0; - } - - @media screen and (min-width: $break-large) { - margin: 0.1em 2.37em; - } -} - -.tx-list-item-wrapper { - flex: 1 1 auto; - width: 0; - align-items: stretch; - justify-content: flex-start; - display: flex; - flex-flow: column nowrap; - - @media screen and (max-width: $break-small) { - padding: 0 1.3em 0.8em; - } - - @media screen and (min-width: $break-large) { - padding-bottom: 8px; - } -} - -.tx-list-pending-item-container { - cursor: pointer; - opacity: 0.5; -} - -.tx-list-date-wrapper { - margin-top: 6px; - flex: 1 1 auto; -} - -.tx-list-content-wrapper { - align-items: stretch; - margin: 4px 0; - flex: 1 0 auto; - width: 100%; - display: flex; - flex-flow: row nowrap; - - @media screen and (max-width: $break-small) { - font-size: 12px; - - .tx-list-status { - font-size: 12px !important; - } - - .tx-list-account { - font-size: 14px !important; - } - - .tx-list-value { - font-size: 14px; - line-height: 18px; - } - - .tx-list-fiat-value { - font-size: 12px; - line-height: 22px; - } - } -} - -.tx-list-item-retry-container { - background: #d1edff; - width: 100%; - border-radius: 12px; - font-size: 0.75rem; - display: flex; - justify-content: center; - margin-left: 44px; - width: calc(100% - 44px); - padding: 4px; - cursor: pointer; - - @media screen and (min-width: 576px) and (max-width: 679px) { - flex-flow: column; - align-items: center; - } - - @media screen and (min-width: 380px) and (max-width: 575px) { - flex-flow: row; - } - - @media screen and (max-width: 379px) { - flex-flow: column; - align-items: center; - } -} - -.tx-list-item-retry-link { - text-decoration: underline; - margin-left: 6px; - cursor: pointer; - - @media screen and (min-width: 576px) and (max-width: 679px) { - margin-left: 0; - } - - @media screen and (min-width: 380px) and (max-width: 575px) { - margin-left: 6px; - } - - @media screen and (max-width: 379px) { - margin-left: 0; - text-align: center; - } -} - -.tx-list-date { - color: $dusty-gray; - font-size: 12px; - font-family: Roboto; -} - -.tx-list-identicon-wrapper { - align-self: center; - flex: 0 0 auto; - margin-right: 16px; - display: flex; -} - -.tx-list-account-and-status-wrapper { - display: flex; - flex: 1 1 auto; - flex-flow: row wrap; - width: 0; - - @media screen and (max-width: $break-small) { - flex-direction: column; - justify-content: flex-start; - align-items: flex-start; - align-self: center; - - .tx-list-account-wrapper { - height: 18px; - - .tx-list-account { - line-height: 14px; - } - } - } - - @media screen and (min-width: $break-large) { - flex-direction: row; - justify-content: flex-start; - align-items: center; - - .tx-list-account-wrapper { - flex: 1.3 2 auto; - min-width: 153px; - } - - .tx-list-status-wrapper { - flex: 6 6 auto; - } - } - - .tx-list-account { - font-size: 16px; - color: $scorpion; - } - - .tx-list-status { - color: $dusty-gray; - font-size: 16px; - text-transform: capitalize; - } - - .tx-list-status--rejected, - .tx-list-status--failed { - color: $monzo; - } - - .tx-list-status--dropped { - opacity: 0.5; - } -} - -.tx-list-item { - border-bottom: 1px solid $geyser; - flex: 0 0 auto; - display: flex; - flex-flow: row nowrap; - - @media screen and (min-width: $break-large) { - padding: 0 2.37em; - } - - &:last-of-type { - border-bottom: 1px solid rgb(231, 231, 231); - margin-bottom: 32px; - } - - &__wrapper { - align-self: center; - flex: 2 2 auto; - color: $dusty-gray; - - .tx-list-value { - font-size: 16px; - text-align: right; - } - - .tx-list-value--confirmed { - color: $caribbean-green; - } - - .tx-list-fiat-value { - font-size: 12px; - text-align: right; - } - } - - &--empty { - text-align: center; - border-bottom: none !important; - padding: 16px; - } -} - -.tx-list-details-wrapper { - overflow: hidden; - flex: 0 0 35%; -} - -.tx-list-value { - font-size: 16px; - text-align: right; - text-overflow: ellipsis; - white-space: nowrap; - overflow: hidden; -} - -.tx-list-fiat-value { - font-size: 12px; - line-height: initial; - text-align: right; - text-overflow: ellipsis; - white-space: nowrap; - overflow: hidden; -} - -.tx-list-value--confirmed { - color: $caribbean-green; -} diff --git a/ui/app/css/itcss/settings/index.scss b/ui/app/css/itcss/settings/index.scss index bbf79c80f..a7152a435 100644 --- a/ui/app/css/itcss/settings/index.scss +++ b/ui/app/css/itcss/settings/index.scss @@ -1,2 +1 @@ @import './variables'; -@import './typography'; diff --git a/ui/app/css/itcss/settings/typography.scss b/ui/app/css/itcss/settings/typography.scss deleted file mode 100644 index 27390b6ee..000000000 --- a/ui/app/css/itcss/settings/typography.scss +++ /dev/null @@ -1,84 +0,0 @@ -$fa-font-path: 'fonts/fontawesome'; - -@import '../../../../../node_modules/@fortawesome/fontawesome-free/scss/fontawesome'; -@import '../../../../../node_modules/@fortawesome/fontawesome-free/scss/solid'; -@import '../../../../../node_modules/@fortawesome/fontawesome-free/scss/regular'; - -@font-face { - font-family: 'Roboto'; - font-style: normal; - font-weight: 100; - src: local('Roboto Thin'), local('Roboto-Thin'), url('fonts/Roboto/Roboto-Thin.ttf') format('truetype'); -} - -@font-face { - font-family: 'Roboto'; - font-style: normal; - font-weight: 300; - src: local('Roboto Light'), local('Roboto-Light'), url('fonts/Roboto/Roboto-Light.ttf') format('truetype'); -} - -@font-face { - font-family: 'Roboto'; - font-style: normal; - font-weight: 400; - src: local('Roboto'), local('Roboto-Regular'), url('fonts/Roboto/Roboto-Regular.ttf') format('truetype'); -} - -@font-face { - font-family: 'Roboto'; - font-style: normal; - font-weight: 500; - src: local('Roboto Medium'), local('Roboto-Medium'), url('fonts/Roboto/Roboto-Medium.ttf') format('truetype'); -} - -@font-face { - font-family: 'Roboto'; - font-style: normal; - font-weight: 700; - src: local('Roboto Bold'), local('Roboto-Bold'), url('fonts/Roboto/Roboto-Bold.ttf') format('truetype'); -} - -@font-face { - font-family: 'Roboto'; - font-style: normal; - font-weight: 900; - src: local('Roboto Black'), local('Roboto-Black'), url('fonts/Roboto/Roboto-Black.ttf') format('truetype'); -} - -@mixin fontScale($weight: 400, $size: 1rem) { - font-weight: $weight; - font-size: $size; -} - -@mixin h1($weight: 400, $size: 2.5rem) { - @include fontScale($weight, $size); -} - -@mixin h2($weight: 400, $size: 2rem) { - @include fontScale($weight, $size); -} - -@mixin h3($weight: 400, $size: 1.5rem) { - @include fontScale($weight, $size); -} - -@mixin h4($weight: 400, $size: 1.125rem) { - @include fontScale($weight, $size); -} - -@mixin h5($weight: 400, $size: 1rem) { - @include fontScale($weight, $size); -} - -@mixin h6($weight: 400, $size: 0.875rem) { - @include fontScale($weight, $size); -} - -@mixin h7($weight: 400, $size: 0.75rem) { - @include fontScale($weight, $size); -} - -@mixin paragraph($weight: 400, $size: 1rem) { - @include fontScale($weight, $size); -} diff --git a/ui/app/css/itcss/settings/variables.scss b/ui/app/css/itcss/settings/variables.scss index 9a40ec9ff..235fc37a2 100644 --- a/ui/app/css/itcss/settings/variables.scss +++ b/ui/app/css/itcss/settings/variables.scss @@ -1,64 +1,3 @@ -/* - Variables - */ - -// Base Colors -$white: #fff; -$black: #000; -$orange: #ffa500; -$red: #f00; -$gray: #808080; - -/* - Colors - http://chir.ag/projects/name-that-color - */ -$gallery: #efefef; -$wild-sand: #f6f6f6; -$dusty-gray: #9b9b9b; -$alto: #dedede; -$alabaster: #fafafa; -$silver-chalice: #aeaeae; -$tundora: #4d4d4d; -$nile-blue: #1b344d; -$scorpion: #5d5d5d; -$silver: #cdcdcd; -$caribbean-green: #02c9b1; -$monzo: #d0021b; -$crimson: #e91550; -$blue-lagoon: #038789; -$purple: #690496; -$tulip-tree: #ebb33f; -$malibu-blue: #7ac9fd; -$athens-grey: #e9edf0; -$geyser: #d2d8dd; -$manatee: #93949d; -$spindle: #c7ddec; -$mid-gray: #5b5d67; -$cape-cod: #38393a; -$dodger-blue: #3099f2; -$ecstasy: #f7861c; -$linen: #fdf4f4; -$oslo-gray: #8c8e94; -$polar: #fafcfe; -$blizzard-blue: #bfdef3; -$mischka: #dddee9; -$web-orange: #f2a202; -$mercury: #e5e5e5; - -/* - Z-Indicies - */ -$dropdown-z-index: 30; -$token-icon-z-index: 15; -$container-z-index: 15; -$header-z-index: 12; -$mobile-header-z-index: 26; -$main-container-z-index: 18; -$send-card-z-index: 20; -$sidebar-z-index: 26; -$sidebar-overlay-z-index: 25; - // Flex %row-nowrap { display: flex; @@ -98,48 +37,6 @@ $sidebar-overlay-z-index: 25; mascot - 0 - remove? */ -/* - Responsive Breakpoints - */ -$break-small: 575px; -$break-midpoint: 780px; -$break-large: 576px; - - -$primary-font-type: Roboto; - - -// Font Sizes -%h3 { - font-size: 1.5rem; - line-height: 2.125rem; - font-weight: 400; -} - -%h4 { - font-size: 1.125rem; - line-height: 1.3125rem; - font-weight: 400; -} - -%h5 { - font-size: 1rem; - line-height: 1.25rem; - font-weight: 400; -} - -%h6 { - font-size: 0.875rem; - line-height: 1.25rem; - font-weight: 400; -} - -%h8 { - font-size: 0.75rem; - line-height: 1.0625rem; - font-weight: 400; -} - /* Spacing Variables @@ -176,36 +73,3 @@ $xxlarge-spacing: 64px; border-color: $Blue-500; } } - -// Font mixin - -%font { - font-family: Roboto; - font-style: normal; - font-weight: normal; - color: $Grey-800; -} - -%font--bold { - @extend %font; - - font-weight: bold; -} - -%header--18 { - @extend %font; - - font-size: 18px; -} - -%header--24 { - @extend %font; - - font-size: 24px; -} - -%content-text { - @extend %font; - - font-size: 14px; -} diff --git a/ui/app/css/itcss/tools/utilities.scss b/ui/app/css/itcss/tools/utilities.scss index 1d0d1c463..aa80ab867 100644 --- a/ui/app/css/itcss/tools/utilities.scss +++ b/ui/app/css/itcss/tools/utilities.scss @@ -112,14 +112,6 @@ z-index: 1; } -.select-none { - cursor: inherit; - -moz-user-select: none; - -webkit-user-select: none; - -ms-user-select: none; - user-select: none; -} - .pointer { cursor: pointer; } diff --git a/ui/app/css/itcss/generic/reset.scss b/ui/app/css/reset.scss similarity index 91% rename from ui/app/css/itcss/generic/reset.scss rename to ui/app/css/reset.scss index b60fcd068..9ee5607cf 100644 --- a/ui/app/css/itcss/generic/reset.scss +++ b/ui/app/css/reset.scss @@ -88,9 +88,11 @@ video { padding: 0; border: 0; font-size: 100%; - /* stylelint-disable */ - font: inherit; - /* stylelint-enable */ + font-weight: inherit; + font-style: inherit; + font-variant: inherit; + font-size: inherit; + line-height: inherit; vertical-align: baseline; } diff --git a/ui/app/css/variables/index.scss b/ui/app/css/variables/index.scss deleted file mode 100644 index 7aa2d674f..000000000 --- a/ui/app/css/variables/index.scss +++ /dev/null @@ -1 +0,0 @@ -@import './colors.scss'; diff --git a/ui/app/ducks/app/app.js b/ui/app/ducks/app/app.js index 177ed812c..2b905a1ac 100644 --- a/ui/app/ducks/app/app.js +++ b/ui/app/ducks/app/app.js @@ -5,7 +5,7 @@ const SET_THREEBOX_LAST_UPDATED = 'metamask/app/SET_THREEBOX_LAST_UPDATED' export default function reduceApp (state = {}, action) { // default state - const appState = Object.assign({ + const appState = { shouldClose: false, menuOpen: false, modal: { @@ -51,7 +51,8 @@ export default function reduceApp (state = {}, action) { requestAccountTabs: {}, openMetaMaskTabs: {}, currentWindowTab: {}, - }, state) + ...state, + } switch (action.type) { // dropdown methods @@ -108,9 +109,8 @@ export default function reduceApp (state = {}, action) { qrCodeData: action.value, } - // modal methods: - case actionConstants.MODAL_OPEN: + case actionConstants.MODAL_OPEN: { const { name, ...modalProps } = action.payload return { @@ -118,12 +118,13 @@ export default function reduceApp (state = {}, action) { modal: { open: true, modalState: { - name: name, + name, props: { ...modalProps }, }, previousModalState: { ...appState.modal.modalState }, }, } + } case actionConstants.MODAL_CLOSE: return { @@ -136,6 +137,12 @@ export default function reduceApp (state = {}, action) { ), } + case actionConstants.CLEAR_ACCOUNT_DETAILS: + return { + ...appState, + accountDetail: {}, + } + case actionConstants.FORGOT_PASSWORD: return { ...appState, @@ -202,17 +209,16 @@ export default function reduceApp (state = {}, action) { txId: null, warning: null, } - } else { - return { - ...appState, - // indicate notification should close - shouldClose: true, - warning: null, - txId: null, - accountDetail: { - subview: 'transactions', - }, - } + } + return { + ...appState, + // indicate notification should close + shouldClose: true, + warning: null, + txId: null, + accountDetail: { + subview: 'transactions', + }, } case actionConstants.TRANSACTION_ERROR: @@ -232,7 +238,7 @@ export default function reduceApp (state = {}, action) { warning: '', } - case actionConstants.SET_HARDWARE_WALLET_DEFAULT_HD_PATH: + case actionConstants.SET_HARDWARE_WALLET_DEFAULT_HD_PATH: { const { device, path } = action.value const newDefaults = { ...appState.defaultHdPaths } newDefaults[device] = path @@ -241,6 +247,7 @@ export default function reduceApp (state = {}, action) { ...appState, defaultHdPaths: newDefaults, } + } case actionConstants.SHOW_LOADING: return { diff --git a/ui/app/ducks/confirm-transaction/confirm-transaction.duck.js b/ui/app/ducks/confirm-transaction/confirm-transaction.duck.js index 416407d5d..2285e8bd7 100644 --- a/ui/app/ducks/confirm-transaction/confirm-transaction.duck.js +++ b/ui/app/ducks/confirm-transaction/confirm-transaction.duck.js @@ -1,3 +1,4 @@ +import { addHexPrefix } from 'ethereumjs-util' import { conversionRateSelector, currentCurrencySelector, @@ -21,7 +22,6 @@ import { } from '../../helpers/utils/transactions.util' import { conversionUtil } from '../../helpers/utils/conversion-util' -import { addHexPrefix } from 'ethereumjs-util' // Actions const createActionType = (action) => `metamask/confirm-transaction/${action}` @@ -104,7 +104,7 @@ export default function reducer (state = initState, action = {}) { ...state, methodData: {}, } - case UPDATE_TRANSACTION_AMOUNTS: + case UPDATE_TRANSACTION_AMOUNTS: { const { fiatTransactionAmount, ethTransactionAmount, hexTransactionAmount } = action.payload return { ...state, @@ -112,7 +112,8 @@ export default function reducer (state = initState, action = {}) { ethTransactionAmount: ethTransactionAmount || state.ethTransactionAmount, hexTransactionAmount: hexTransactionAmount || state.hexTransactionAmount, } - case UPDATE_TRANSACTION_FEES: + } + case UPDATE_TRANSACTION_FEES: { const { fiatTransactionFee, ethTransactionFee, hexTransactionFee } = action.payload return { ...state, @@ -120,7 +121,8 @@ export default function reducer (state = initState, action = {}) { ethTransactionFee: ethTransactionFee || state.ethTransactionFee, hexTransactionFee: hexTransactionFee || state.hexTransactionFee, } - case UPDATE_TRANSACTION_TOTALS: + } + case UPDATE_TRANSACTION_TOTALS: { const { fiatTransactionTotal, ethTransactionTotal, hexTransactionTotal } = action.payload return { ...state, @@ -128,7 +130,8 @@ export default function reducer (state = initState, action = {}) { ethTransactionTotal: ethTransactionTotal || state.ethTransactionTotal, hexTransactionTotal: hexTransactionTotal || state.hexTransactionTotal, } - case UPDATE_TOKEN_PROPS: + } + case UPDATE_TOKEN_PROPS: { const { tokenSymbol = '', tokenDecimals = '' } = action.payload return { ...state, @@ -138,6 +141,7 @@ export default function reducer (state = initState, action = {}) { tokenDecimals, }, } + } case UPDATE_NONCE: return { ...state, @@ -254,16 +258,14 @@ export function setFetchingData (isFetching) { } export function updateGasAndCalculate ({ gasLimit, gasPrice }) { - gasLimit = addHexPrefix(gasLimit) - gasPrice = addHexPrefix(gasPrice) return (dispatch, getState) => { const { confirmTransaction: { txData } } = getState() const newTxData = { ...txData, txParams: { ...txData.txParams, - gas: gasLimit, - gasPrice, + gas: addHexPrefix(gasLimit), + gasPrice: addHexPrefix(gasPrice), }, } @@ -364,7 +366,6 @@ export function setTransactionToConfirm (transactionId) { if (txParams.data) { const { data } = txParams - const tokenData = getTokenData(data) dispatch(updateTokenData(tokenData)) 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 720d0307b..60ada9797 100644 --- a/ui/app/ducks/confirm-transaction/confirm-transaction.duck.test.js +++ b/ui/app/ducks/confirm-transaction/confirm-transaction.duck.test.js @@ -3,7 +3,7 @@ import configureMockStore from 'redux-mock-store' import thunk from 'redux-thunk' import sinon from 'sinon' -import ConfirmTransactionReducer, * as actions from './confirm-transaction.duck.js' +import ConfirmTransactionReducer, * as actions from './confirm-transaction.duck' const initialState = { txData: {}, @@ -482,7 +482,7 @@ describe('Confirm Transaction Duck', function () { beforeEach(function () { global.eth = { getCode: sinon.stub().callsFake( - (address) => Promise.resolve(address && address.match(/isContract/) ? 'not-0x' : '0x'), + (address) => Promise.resolve(address && address.match(/isContract/u) ? 'not-0x' : '0x'), ), } }) diff --git a/ui/app/ducks/gas/gas-duck.test.js b/ui/app/ducks/gas/gas-duck.test.js index c46875693..d7ae9b873 100644 --- a/ui/app/ducks/gas/gas-duck.test.js +++ b/ui/app/ducks/gas/gas-duck.test.js @@ -67,11 +67,11 @@ describe('Gas Duck', function () { { expectedTime: 1, expectedWait: 0.5, gasprice: 20, somethingElse: 'foobar' }, ] const fakeFetch = (url) => new Promise((resolve) => { - const dataToResolve = url.match(/ethgasAPI/) + const dataToResolve = url.match(/ethgasAPI/u) ? mockEthGasApiResponse : mockPredictTableResponse resolve({ - json: () => new Promise((resolve) => resolve(dataToResolve)), + json: () => Promise.resolve(dataToResolve), }) }) @@ -288,7 +288,7 @@ describe('Gas Duck', function () { })) assert.deepEqual( mockDistpatch.getCall(0).args, - [{ type: BASIC_GAS_ESTIMATE_LOADING_STARTED } ], + [{ type: BASIC_GAS_ESTIMATE_LOADING_STARTED }], ) assert.ok( window.fetch.getCall(0).args[0].startsWith('https://ethgasstation.info/json/ethgasAPI.json'), @@ -296,7 +296,7 @@ describe('Gas Duck', function () { ) assert.deepEqual( mockDistpatch.getCall(1).args, - [{ type: SET_BASIC_PRICE_ESTIMATES_LAST_RETRIEVED, value: 2000000 } ], + [{ type: SET_BASIC_PRICE_ESTIMATES_LAST_RETRIEVED, value: 2000000 }], ) assert.deepEqual( mockDistpatch.getCall(2).args, @@ -334,14 +334,10 @@ describe('Gas Duck', function () { safeLow: 15, }) - await fetchBasicGasEstimates()(mockDistpatch, () => ({ gas: Object.assign( - {}, - initState, - {}, - ) })) + await fetchBasicGasEstimates()(mockDistpatch, () => ({ gas: { ...initState } })) assert.deepEqual( mockDistpatch.getCall(0).args, - [{ type: BASIC_GAS_ESTIMATE_LOADING_STARTED } ], + [{ type: BASIC_GAS_ESTIMATE_LOADING_STARTED }], ) assert.ok(window.fetch.notCalled) assert.deepEqual( @@ -370,14 +366,10 @@ describe('Gas Duck', function () { .withArgs('BASIC_PRICE_ESTIMATES_LAST_RETRIEVED') .returns(2000000 - 1) // one second ago from "now" - await fetchBasicGasEstimates()(mockDistpatch, () => ({ gas: Object.assign( - {}, - initState, - {}, - ) })) + await fetchBasicGasEstimates()(mockDistpatch, () => ({ gas: { ...initState } })) assert.deepEqual( mockDistpatch.getCall(0).args, - [{ type: BASIC_GAS_ESTIMATE_LOADING_STARTED } ], + [{ type: BASIC_GAS_ESTIMATE_LOADING_STARTED }], ) assert.ok( window.fetch.getCall(0).args[0].startsWith('https://ethgasstation.info/json/ethgasAPI.json'), @@ -385,7 +377,7 @@ describe('Gas Duck', function () { ) assert.deepEqual( mockDistpatch.getCall(1).args, - [{ type: SET_BASIC_PRICE_ESTIMATES_LAST_RETRIEVED, value: 2000000 } ], + [{ type: SET_BASIC_PRICE_ESTIMATES_LAST_RETRIEVED, value: 2000000 }], ) assert.deepEqual( mockDistpatch.getCall(2).args, @@ -412,16 +404,16 @@ describe('Gas Duck', function () { it('should call fetch with the expected params', async function () { const mockDistpatch = sinon.spy() - await fetchBasicGasAndTimeEstimates()(mockDistpatch, () => ({ gas: Object.assign( - {}, - initState, - { basicPriceAndTimeEstimatesLastRetrieved: 1000000 }, - ), - metamask: { provider: { type: 'ropsten' } }, + await fetchBasicGasAndTimeEstimates()(mockDistpatch, () => ({ + gas: { + ...initState, + basicPriceAndTimeEstimatesLastRetrieved: 1000000, + }, + metamask: { provider: { type: 'ropsten' } }, })) assert.deepEqual( mockDistpatch.getCall(0).args, - [{ type: BASIC_GAS_ESTIMATE_LOADING_STARTED } ], + [{ type: BASIC_GAS_ESTIMATE_LOADING_STARTED }], ) assert.ok( window.fetch.getCall(0).args[0].startsWith('https://ethgasstation.info/json/ethgasAPI.json'), @@ -430,7 +422,7 @@ describe('Gas Duck', function () { assert.deepEqual( mockDistpatch.getCall(1).args, - [{ type: SET_BASIC_API_ESTIMATES_LAST_RETRIEVED, value: 2000000 } ], + [{ type: SET_BASIC_API_ESTIMATES_LAST_RETRIEVED, value: 2000000 }], ) assert.deepEqual( @@ -479,16 +471,15 @@ describe('Gas Duck', function () { speed: 'mockSpeed', }) - await fetchBasicGasAndTimeEstimates()(mockDistpatch, () => ({ gas: Object.assign( - {}, - initState, - {}, - ), - metamask: { provider: { type: 'ropsten' } }, + await fetchBasicGasAndTimeEstimates()(mockDistpatch, () => ({ + gas: { + ...initState, + }, + metamask: { provider: { type: 'ropsten' } }, })) assert.deepEqual( mockDistpatch.getCall(0).args, - [{ type: BASIC_GAS_ESTIMATE_LOADING_STARTED } ], + [{ type: BASIC_GAS_ESTIMATE_LOADING_STARTED }], ) assert.ok(window.fetch.notCalled) @@ -523,16 +514,15 @@ describe('Gas Duck', function () { .withArgs('BASIC_GAS_AND_TIME_API_ESTIMATES_LAST_RETRIEVED') .returns(2000000 - 1) // one second ago from "now" - await fetchBasicGasAndTimeEstimates()(mockDistpatch, () => ({ gas: Object.assign( - {}, - initState, - {}, - ), - metamask: { provider: { type: 'ropsten' } }, + await fetchBasicGasAndTimeEstimates()(mockDistpatch, () => ({ + gas: { + ...initState, + }, + metamask: { provider: { type: 'ropsten' } }, })) assert.deepEqual( mockDistpatch.getCall(0).args, - [{ type: BASIC_GAS_ESTIMATE_LOADING_STARTED } ], + [{ type: BASIC_GAS_ESTIMATE_LOADING_STARTED }], ) assert.ok( window.fetch.getCall(0).args[0].startsWith('https://ethgasstation.info/json/ethgasAPI.json'), @@ -541,7 +531,7 @@ describe('Gas Duck', function () { assert.deepEqual( mockDistpatch.getCall(1).args, - [{ type: SET_BASIC_API_ESTIMATES_LAST_RETRIEVED, value: 2000000 } ], + [{ type: SET_BASIC_API_ESTIMATES_LAST_RETRIEVED, value: 2000000 }], ) assert.deepEqual( @@ -574,16 +564,16 @@ describe('Gas Duck', function () { it('should call fetch with the expected params', async function () { const mockDistpatch = sinon.spy() - await fetchGasEstimates(5)(mockDistpatch, () => ({ gas: Object.assign( - {}, - initState, - { priceAndTimeEstimatesLastRetrieved: 1000000 }, - ), - metamask: { provider: { type: 'ropsten' } }, + await fetchGasEstimates(5)(mockDistpatch, () => ({ + gas: { + ...initState, + priceAndTimeEstimatesLastRetrieved: 1000000, + }, + metamask: { provider: { type: 'ropsten' } }, })) assert.deepEqual( mockDistpatch.getCall(0).args, - [{ type: GAS_ESTIMATE_LOADING_STARTED } ], + [{ type: GAS_ESTIMATE_LOADING_STARTED }], ) assert.ok( window.fetch.getCall(0).args[0].startsWith('https://ethgasstation.info/json/predictTable.json'), @@ -611,10 +601,9 @@ describe('Gas Duck', function () { it('should not call fetch if the estimates were retrieved < 75000 ms ago', async function () { const mockDistpatch = sinon.spy() - await fetchGasEstimates(5)(mockDistpatch, () => ({ gas: Object.assign( - {}, - initState, - { + await fetchGasEstimates(5)(mockDistpatch, () => ({ + gas: { + ...initState, priceAndTimeEstimatesLastRetrieved: Date.now(), priceAndTimeEstimates: [{ expectedTime: '10', @@ -622,12 +611,11 @@ describe('Gas Duck', function () { gasprice: 50, }], }, - ), - metamask: { provider: { type: 'ropsten' } }, + metamask: { provider: { type: 'ropsten' } }, })) assert.deepEqual( mockDistpatch.getCall(0).args, - [{ type: GAS_ESTIMATE_LOADING_STARTED } ], + [{ type: GAS_ESTIMATE_LOADING_STARTED }], ) assert.equal(window.fetch.callCount, 0) @@ -741,5 +729,4 @@ describe('Gas Duck', function () { ) }) }) - }) diff --git a/ui/app/ducks/gas/gas.duck.js b/ui/app/ducks/gas/gas.duck.js index c1d7336e3..9d83a66e0 100644 --- a/ui/app/ducks/gas/gas.duck.js +++ b/ui/app/ducks/gas/gas.duck.js @@ -194,8 +194,8 @@ async function queryEthGasStationPredictionTable () { 'referrerPolicy': 'no-referrer-when-downgrade', 'body': null, 'method': 'GET', - 'mode': 'cors' }, - ) + 'mode': 'cors', + }) } export function fetchBasicGasEstimates () { @@ -323,20 +323,22 @@ async function fetchExternalBasicGasAndTimeEstimates (dispatch) { } function extrapolateY ({ higherY, lowerY, higherX, lowerX, xForExtrapolation }) { + /* eslint-disable no-param-reassign */ higherY = new BigNumber(higherY, 10) lowerY = new BigNumber(lowerY, 10) higherX = new BigNumber(higherX, 10) lowerX = new BigNumber(lowerX, 10) xForExtrapolation = new BigNumber(xForExtrapolation, 10) + /* eslint-enable no-param-reassign */ const slope = (higherY.minus(lowerY)).div(higherX.minus(lowerX)) const newTimeEstimate = slope.times(higherX.minus(xForExtrapolation)).minus(higherY).negated() return Number(newTimeEstimate.toPrecision(10)) } -function getRandomArbitrary (min, max) { - min = new BigNumber(min, 10) - max = new BigNumber(max, 10) +function getRandomArbitrary (minStr, maxStr) { + const min = new BigNumber(minStr, 10) + const max = new BigNumber(maxStr, 10) const random = new BigNumber(String(Math.random()), 10) return new BigNumber(random.times(max.minus(min)).plus(min)).toPrecision(10) } @@ -399,29 +401,28 @@ export function fetchGasEstimates (blockTime) { const next = arr[i + 1] if (!next) { return [{ expectedWait, gasprice }] - } else { - const supplementalPrice = getRandomArbitrary(gasprice, next.gasprice) - const supplementalTime = extrapolateY({ - higherY: next.expectedWait, - lowerY: expectedWait, - higherX: next.gasprice, - lowerX: gasprice, - xForExtrapolation: supplementalPrice, - }) - const supplementalPrice2 = getRandomArbitrary(supplementalPrice, next.gasprice) - const supplementalTime2 = extrapolateY({ - higherY: next.expectedWait, - lowerY: supplementalTime, - higherX: next.gasprice, - lowerX: supplementalPrice, - xForExtrapolation: supplementalPrice2, - }) - return [ - { expectedWait, gasprice }, - { expectedWait: supplementalTime, gasprice: supplementalPrice }, - { expectedWait: supplementalTime2, gasprice: supplementalPrice2 }, - ] } + const supplementalPrice = getRandomArbitrary(gasprice, next.gasprice) + const supplementalTime = extrapolateY({ + higherY: next.expectedWait, + lowerY: expectedWait, + higherX: next.gasprice, + lowerX: gasprice, + xForExtrapolation: supplementalPrice, + }) + const supplementalPrice2 = getRandomArbitrary(supplementalPrice, next.gasprice) + const supplementalTime2 = extrapolateY({ + higherY: next.expectedWait, + lowerY: supplementalTime, + higherX: next.gasprice, + lowerX: supplementalPrice, + xForExtrapolation: supplementalPrice2, + }) + return [ + { expectedWait, gasprice }, + { expectedWait: supplementalTime, gasprice: supplementalPrice }, + { expectedWait: supplementalTime2, gasprice: supplementalPrice2 }, + ] })) const withOutliersRemoved = inliersByIQR(withSupplementalTimeEstimates.slice(0).reverse(), 'expectedWait').reverse() const timeMappedToSeconds = withOutliersRemoved.map(({ expectedWait, gasprice }) => { @@ -441,8 +442,7 @@ export function fetchGasEstimates (blockTime) { }) : Promise.resolve(priceAndTimeEstimates.length ? priceAndTimeEstimates - : loadLocalStorageData('GAS_API_ESTIMATES'), - ) + : loadLocalStorageData('GAS_API_ESTIMATES')) return promiseToFetch.then((estimates) => { dispatch(setPricesAndTimeEstimates(estimates)) @@ -453,11 +453,11 @@ export function fetchGasEstimates (blockTime) { export function setCustomGasPriceForRetry (newPrice) { return (dispatch) => { - if (newPrice !== '0x0') { - dispatch(setCustomGasPrice(newPrice)) - } else { + if (newPrice === '0x0') { const { fast } = loadLocalStorageData('BASIC_PRICE_ESTIMATES') dispatch(setCustomGasPrice(decGWEIToHexWEI(fast))) + } else { + dispatch(setCustomGasPrice(newPrice)) } } } diff --git a/ui/app/ducks/index.js b/ui/app/ducks/index.js index 09af8914e..91ba222cb 100644 --- a/ui/app/ducks/index.js +++ b/ui/app/ducks/index.js @@ -1,4 +1,5 @@ import { combineReducers } from 'redux' +import { ALERT_TYPES } from '../../../app/scripts/controllers/alert' import metamaskReducer from './metamask/metamask' import localeMessagesReducer from './locale/locale' import sendReducer from './send/send.duck' @@ -7,7 +8,6 @@ import confirmTransactionReducer from './confirm-transaction/confirm-transaction import gasReducer from './gas/gas.duck' import { unconnectedAccount } from './alerts' import historyReducer from './history/history' -import { ALERT_TYPES } from '../../../app/scripts/controllers/alert' export default combineReducers({ [ALERT_TYPES.unconnectedAccount]: unconnectedAccount, diff --git a/ui/app/ducks/metamask/metamask.js b/ui/app/ducks/metamask/metamask.js index e3f35bf38..c2058fc06 100644 --- a/ui/app/ducks/metamask/metamask.js +++ b/ui/app/ducks/metamask/metamask.js @@ -2,7 +2,7 @@ import * as actionConstants from '../../store/actionConstants' import { ALERT_TYPES } from '../../../../app/scripts/controllers/alert' export default function reduceMetamask (state = {}, action) { - const metamaskState = Object.assign({ + const metamaskState = { isInitialized: false, isUnlocked: false, isAccountMenuOpen: false, @@ -46,7 +46,8 @@ export default function reduceMetamask (state = {}, action) { participateInMetaMetrics: null, metaMetricsSendCount: 0, nextNonce: null, - }, state) + ...state, + } switch (action.type) { @@ -84,13 +85,14 @@ export default function reduceMetamask (state = {}, action) { selectedAddress: action.value, } - case actionConstants.SET_ACCOUNT_LABEL: - const account = action.value.account + case actionConstants.SET_ACCOUNT_LABEL: { + const { account } = action.value const name = action.value.label const id = {} - id[account] = Object.assign({}, metamaskState.identities[account], { name }) - const identities = Object.assign({}, metamaskState.identities, id) + id[account] = { ...metamaskState.identities[account], name } + const identities = { ...metamaskState.identities, ...id } return Object.assign(metamaskState, { identities }) + } case actionConstants.SET_CURRENT_FIAT: return Object.assign(metamaskState, { @@ -197,7 +199,7 @@ export default function reduceMetamask (state = {}, action) { }, }) - case actionConstants.UPDATE_SEND_TOKEN: + case actionConstants.UPDATE_SEND_TOKEN: { const newSend = { ...metamaskState.send, token: action.value, @@ -225,6 +227,7 @@ export default function reduceMetamask (state = {}, action) { return Object.assign(metamaskState, { send: newSend, }) + } case actionConstants.UPDATE_SEND_ENS_RESOLUTION: return { @@ -265,12 +268,12 @@ export default function reduceMetamask (state = {}, action) { }, } - case actionConstants.UPDATE_TRANSACTION_PARAMS: + case actionConstants.UPDATE_TRANSACTION_PARAMS: { const { id: txId, value } = action let { currentNetworkTxList } = metamaskState currentNetworkTxList = currentNetworkTxList.map((tx) => { if (tx.id === txId) { - const newTx = Object.assign({}, tx) + const newTx = { ...tx } newTx.txParams = value return newTx } @@ -281,6 +284,7 @@ export default function reduceMetamask (state = {}, action) { ...metamaskState, currentNetworkTxList, } + } case actionConstants.SET_PARTICIPATE_IN_METAMETRICS: return { diff --git a/ui/app/ducks/send/send-duck.test.js b/ui/app/ducks/send/send-duck.test.js index 3dda8728b..9731d5b2c 100644 --- a/ui/app/ducks/send/send-duck.test.js +++ b/ui/app/ducks/send/send-duck.test.js @@ -6,7 +6,7 @@ import SendReducer, { updateSendErrors, showGasButtonGroup, hideGasButtonGroup, -} from './send.duck.js' +} from './send.duck' describe('Send Duck', function () { const mockState = { diff --git a/ui/app/helpers/higher-order-components/initialized/index.js b/ui/app/helpers/higher-order-components/initialized/index.js index 863fcb389..5aa9f0809 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.js' +export { default } from './initialized.container' diff --git a/ui/app/helpers/utils/common.util.js b/ui/app/helpers/utils/common.util.js index a45fdc407..4df816941 100644 --- a/ui/app/helpers/utils/common.util.js +++ b/ui/app/helpers/utils/common.util.js @@ -1,5 +1,5 @@ export function camelCaseToCapitalize (str = '') { return str - .replace(/([A-Z])/g, ' $1') - .replace(/^./, (str) => str.toUpperCase()) + .replace(/([A-Z])/ug, ' $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 169b780b6..cd2d71b03 100644 --- a/ui/app/helpers/utils/common.util.test.js +++ b/ui/app/helpers/utils/common.util.test.js @@ -1,5 +1,5 @@ -import * as utils from './common.util' import assert from 'assert' +import * as utils from './common.util' describe('Common utils', function () { describe('camelCaseToCapitalize', function () { diff --git a/ui/app/helpers/utils/confirm-tx.util.js b/ui/app/helpers/utils/confirm-tx.util.js index e1cd83615..a6319ef97 100644 --- a/ui/app/helpers/utils/confirm-tx.util.js +++ b/ui/app/helpers/utils/confirm-tx.util.js @@ -3,6 +3,7 @@ import currencies from 'currency-formatter/currencies' import ethUtil from 'ethereumjs-util' import BigNumber from 'bignumber.js' +import { unconfirmedTransactionsCountSelector } from '../../selectors' import { conversionUtil, addCurrencies, @@ -10,8 +11,6 @@ import { conversionGreaterThan, } from './conversion-util' -import { unconfirmedTransactionsCountSelector } from '../../selectors' - export function increaseLastGasPrice (lastGasPrice) { return ethUtil.addHexPrefix(multiplyCurrencies(lastGasPrice || '0x0', 1.1, { multiplicandBase: 16, diff --git a/ui/app/helpers/utils/confirm-tx.util.test.js b/ui/app/helpers/utils/confirm-tx.util.test.js index 71783402e..065631c7d 100644 --- a/ui/app/helpers/utils/confirm-tx.util.test.js +++ b/ui/app/helpers/utils/confirm-tx.util.test.js @@ -1,5 +1,5 @@ -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 () { diff --git a/ui/app/helpers/utils/conversion-util.js b/ui/app/helpers/utils/conversion-util.js index adc9b65e2..6991e1482 100644 --- a/ui/app/helpers/utils/conversion-util.js +++ b/ui/app/helpers/utils/conversion-util.js @@ -25,7 +25,7 @@ import BigNumber from 'bignumber.js' import ethUtil, { stripHexPrefix } from 'ethereumjs-util' -const BN = ethUtil.BN +const { BN } = ethUtil // Big Number Constants const BIG_NUMBER_WEI_MULTIPLIER = new BigNumber('1000000000000000000') @@ -99,7 +99,7 @@ const converter = ({ } if (fromCurrency !== toCurrency) { - if (conversionRate == null) { + 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) diff --git a/ui/app/helpers/utils/conversion-util.test.js b/ui/app/helpers/utils/conversion-util.test.js index 719f7b6d9..9c570f95d 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 { addCurrencies, conversionUtil } from './conversion-util' import BigNumber from 'bignumber.js' +import { addCurrencies, conversionUtil } from './conversion-util' describe('conversion utils', function () { describe('addCurrencies()', function () { diff --git a/ui/app/helpers/utils/conversions.util.js b/ui/app/helpers/utils/conversions.util.js index 5e1c21ff7..0cde0d0ac 100644 --- a/ui/app/helpers/utils/conversions.util.js +++ b/ui/app/helpers/utils/conversions.util.js @@ -129,3 +129,12 @@ export function hexWEIToDecGWEI (decGWEI) { toDenomination: 'GWEI', }) } + +export function decETHToDecWEI (decEth) { + return conversionUtil(decEth, { + fromNumericBase: 'dec', + toNumericBase: 'dec', + fromDenomination: 'ETH', + toDenomination: 'WEI', + }) +} diff --git a/ui/app/helpers/utils/conversions.util.test.js b/ui/app/helpers/utils/conversions.util.test.js new file mode 100644 index 000000000..f4c08cc74 --- /dev/null +++ b/ui/app/helpers/utils/conversions.util.test.js @@ -0,0 +1,29 @@ +import assert from 'assert' +import * as utils from './conversions.util' + +describe('decETHToDecWEI', function () { + it('should correctly convert 1 ETH to WEI', function () { + const weiValue = utils.decETHToDecWEI('1') + assert.equal(weiValue, '1000000000000000000') + }) + + it('should correctly convert 0.000000000000000001 ETH to WEI', function () { + const weiValue = utils.decETHToDecWEI('0.000000000000000001') + assert.equal(weiValue, '1') + }) + + it('should correctly convert 1000000.000000000000000001 ETH to WEI', function () { + const weiValue = utils.decETHToDecWEI('1000000.000000000000000001') + assert.equal(weiValue, '1000000000000000000000001') + }) + + it('should correctly convert 9876.543210 ETH to WEI', function () { + const weiValue = utils.decETHToDecWEI('9876.543210') + assert.equal(weiValue, '9876543210000000000000') + }) + + it('should correctly convert 1.0000000000000000 ETH to WEI', function () { + const weiValue = utils.decETHToDecWEI('1.0000000000000000') + assert.equal(weiValue, '1000000000000000000') + }) +}) diff --git a/ui/app/helpers/utils/fetch-with-cache.js b/ui/app/helpers/utils/fetch-with-cache.js index 1b9693d81..470f2a8d6 100644 --- a/ui/app/helpers/utils/fetch-with-cache.js +++ b/ui/app/helpers/utils/fetch-with-cache.js @@ -24,30 +24,29 @@ const fetchWithCache = async (url, fetchOptions = {}, { cacheRefreshTime = 36000 const { cachedResponse, cachedTime } = cachedFetch[url] || {} if (cachedResponse && currentTime - cachedTime < cacheRefreshTime) { return cachedResponse - } else { - fetchOptions.headers.set('Content-Type', 'application/json') - const _fetch = timeout ? - fetchWithTimeout({ timeout }) : - window.fetch - const response = await _fetch(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 cacheEntry = { - cachedResponse: responseJson, - cachedTime: currentTime, - } - cachedFetch[url] = cacheEntry - saveLocalStorageData(cachedFetch, 'cachedFetch') - return responseJson } + fetchOptions.headers.set('Content-Type', 'application/json') + const _fetch = timeout + ? fetchWithTimeout({ timeout }) + : window.fetch + const response = await _fetch(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 cacheEntry = { + cachedResponse: responseJson, + cachedTime: currentTime, + } + cachedFetch[url] = cacheEntry + saveLocalStorageData(cachedFetch, 'cachedFetch') + return responseJson } export default fetchWithCache diff --git a/ui/app/helpers/utils/formatters.js b/ui/app/helpers/utils/formatters.js index 106a2520d..d722ef09b 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/gas-time-estimates.util.js b/ui/app/helpers/utils/gas-time-estimates.util.js index 7e143a028..5aadacf3a 100644 --- a/ui/app/helpers/utils/gas-time-estimates.util.js +++ b/ui/app/helpers/utils/gas-time-estimates.util.js @@ -47,8 +47,8 @@ export function formatTimeEstimate (totalSeconds, greaterThanMax, lessThanMin) { symbol = '> ' } - const formattedMin = `${minutes ? minutes + ' min' : ''}` - const formattedSec = `${seconds ? seconds + ' sec' : ''}` + const formattedMin = `${minutes ? `${minutes} min` : ''}` + const formattedSec = `${seconds ? `${seconds} sec` : ''}` const formattedCombined = formattedMin && formattedSec ? `${symbol}${formattedMin} ${formattedSec}` : symbol + (formattedMin || formattedSec) diff --git a/ui/app/helpers/utils/i18n-helper.js b/ui/app/helpers/utils/i18n-helper.js index 7fccc92cb..198e025d5 100644 --- a/ui/app/helpers/utils/i18n-helper.js +++ b/ui/app/helpers/utils/i18n-helper.js @@ -48,15 +48,18 @@ export const getMessage = (localeCode, localeMessages, key, substitutions) => { // perform substitutions if (hasSubstitutions) { - const parts = phrase.split(/(\$\d)/g) + const parts = phrase.split(/(\$\d)/ug) const substitutedParts = parts.map((part) => { - const subMatch = part.match(/\$(\d)/) + const subMatch = part.match(/\$(\d)/u) if (!subMatch) { return part } const substituteIndex = Number(subMatch[1]) - 1 - if (substitutions[substituteIndex] == null && !missingSubstitutionErrors[localeCode]?.[key]) { + if ( + (substitutions[substituteIndex] === null || substitutions[substituteIndex] === undefined) && + !missingSubstitutionErrors[localeCode]?.[key] + ) { if (!missingSubstitutionErrors[localeCode]) { missingSubstitutionErrors[localeCode] = {} } diff --git a/ui/app/helpers/utils/i18n-helper.test.js b/ui/app/helpers/utils/i18n-helper.test.js index 4531865ab..4e41f8c20 100644 --- a/ui/app/helpers/utils/i18n-helper.test.js +++ b/ui/app/helpers/utils/i18n-helper.test.js @@ -1,7 +1,7 @@ -import { getMessage } from './i18n-helper' +import assert from 'assert' import React from 'react' import { shallow } from 'enzyme' -import assert from 'assert' +import { getMessage } from './i18n-helper' describe('i18n helper', function () { const TEST_LOCALE_CODE = 'TEST_LOCALE_CODE' @@ -118,42 +118,42 @@ describe('i18n helper', function () { }) 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.equal(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.equal(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, [ TEST_SUBSTITUTION_1, TEST_SUBSTITUTION_2, TEST_SUBSTITUTION_3, TEST_SUBSTITUTION_4, TEST_SUBSTITUTION_5 ]) + const result = t(TEST_KEY_4, [TEST_SUBSTITUTION_1, TEST_SUBSTITUTION_2, TEST_SUBSTITUTION_3, TEST_SUBSTITUTION_4, TEST_SUBSTITUTION_5]) assert.equal(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 ]) + const result = t(TEST_KEY_4, [0, -0, '', false, NaN]) assert.equal(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 ]) + const result = t(TEST_KEY_5, [null, TEST_SUBSTITUTION_2]) assert.equal(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.equal(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 ]) + const result = t(TEST_KEY_7, [TEST_SUBSTITUTION_7_1, TEST_SUBSTITUTION_7_2]) assert.equal(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, [ TEST_SUBSTITUTION_1, TEST_SUBSTITUTION_8_1, TEST_SUBSTITUTION_2, TEST_SUBSTITUTION_8_2 ]) + const result = t(TEST_KEY_8, [TEST_SUBSTITUTION_1, TEST_SUBSTITUTION_8_1, TEST_SUBSTITUTION_2, TEST_SUBSTITUTION_8_2]) assert.equal(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/metametrics.util.js b/ui/app/helpers/utils/metametrics.util.js index 0ffe856bf..41a4bb22d 100644 --- a/ui/app/helpers/utils/metametrics.util.js +++ b/ui/app/helpers/utils/metametrics.util.js @@ -52,6 +52,7 @@ const customVariableNameIdMap = { [METAMETRICS_CUSTOM_GAS_CHANGED]: 1, [METAMETRICS_CUSTOM_ASSET_SELECTED]: 2, } + /** ********************************************************** **/ const METAMETRICS_CUSTOM_NETWORK = 'network' @@ -157,26 +158,32 @@ function composeUrl (config) { const urlref = previousPath && composeUrlRefParamAddition(previousPath, confirmTransactionOrigin) - const dimensions = !pageOpts.hideDimensions ? composeCustomDimensionParamAddition({ - network, - environmentType, - activeCurrency, - accountType, - version, - numberOfTokens: (customVariables && customVariables.numberOfTokens) || numberOfTokens, - numberOfAccounts: (customVariables && customVariables.numberOfAccounts) || numberOfAccounts, - }) : '' + const dimensions = pageOpts.hideDimensions + ? '' + : ( + composeCustomDimensionParamAddition({ + network, + environmentType, + activeCurrency, + accountType, + version, + numberOfTokens: (customVariables && customVariables.numberOfTokens) || numberOfTokens, + numberOfAccounts: (customVariables && customVariables.numberOfAccounts) || numberOfAccounts, + }) + ) const url = currentPath ? `&url=${encodeURIComponent(`${METAMETRICS_TRACKING_URL}${currentPath}`)}` : '' const _id = metaMetricsId && !excludeMetaMetricsId ? `&_id=${metaMetricsId.slice(2, 18)}` : '' const rand = `&rand=${String(Math.random()).slice(2)}` const pv_id = currentPath ? `&pv_id=${ethUtil.bufferToHex(ethUtil.sha3(currentPath)).slice(2, 8)}` : '' - const uid = metaMetricsId && !excludeMetaMetricsId - ? `&uid=${metaMetricsId.slice(2, 18)}` - : excludeMetaMetricsId - ? '&uid=0000000000000000' - : '' - return [ base, e_c, e_a, e_n, cvar, action_name, urlref, dimensions, url, _id, rand, pv_id, uid, new_visit ].join('') + let uid = '' + if (excludeMetaMetricsId) { + uid = '&uid=0000000000000000' + } else if (metaMetricsId) { + uid = `&uid=${metaMetricsId.slice(2, 18)}` + } + + return [base, e_c, e_a, e_n, cvar, action_name, urlref, dimensions, url, _id, rand, pv_id, uid, new_visit].join('') } export function sendMetaMetricsEvent (config) { @@ -203,9 +210,8 @@ export function verifyUserPermission (config, props) { return true } else if (allowSendMetrics && eventOpts.name === 'send') { return true - } else { - return false } + return false } const trackableSendCounts = { diff --git a/ui/app/helpers/utils/switch-direction.js b/ui/app/helpers/utils/switch-direction.js index 2ccbfbaf0..81170f43c 100644 --- a/ui/app/helpers/utils/switch-direction.js +++ b/ui/app/helpers/utils/switch-direction.js @@ -1,9 +1,11 @@ /** * Switch the CSS stylesheet used between 'rtl' and 'ltr' - * @param {('ltr' | 'rtl')} direction - Text direction, either left-to-right (ltr) or right-to-left (rtl) + * @param {('ltr' | 'rtl' | 'auto')} direction - Text direction, either left-to-right (ltr) or right-to-left (rtl) + * @return {Promise} */ const switchDirection = async (direction) => { if (direction === 'auto') { + // eslint-disable-next-line no-param-reassign direction = 'ltr' } let updatedLink @@ -25,6 +27,8 @@ const switchDirection = async (direction) => { updatedLink.onerror = () => reject(new Error(`Failed to load '${direction}' stylesheet`)) }) } + + return undefined } export default switchDirection diff --git a/ui/app/helpers/utils/token-util.js b/ui/app/helpers/utils/token-util.js index eb427fe0b..6d8516ba8 100644 --- a/ui/app/helpers/utils/token-util.js +++ b/ui/app/helpers/utils/token-util.js @@ -1,7 +1,7 @@ import log from 'loglevel' -import * as util from './util' import BigNumber from 'bignumber.js' import contractMap from 'eth-contract-metadata' +import * as util from './util' import { conversionUtil, multiplyCurrencies } from './conversion-util' import { formatCurrency } from './confirm-tx.util' @@ -23,6 +23,7 @@ async function getSymbolFromContract (tokenAddress) { return result[0] } catch (error) { log.warn(`symbol() call for token at address ${tokenAddress} resulted in error:`, error) + return undefined } } @@ -35,6 +36,7 @@ async function getDecimalsFromContract (tokenAddress) { return decimalsBN && decimalsBN.toString() } catch (error) { log.warn(`decimals() call for token at address ${tokenAddress} resulted in error:`, error) + return undefined } } diff --git a/ui/app/helpers/utils/transactions.util.js b/ui/app/helpers/utils/transactions.util.js index 5ea8daeab..3c6481c80 100644 --- a/ui/app/helpers/utils/transactions.util.js +++ b/ui/app/helpers/utils/transactions.util.js @@ -2,14 +2,13 @@ import ethUtil from 'ethereumjs-util' import MethodRegistry from 'eth-method-registry' import abi from 'human-standard-token-abi' import abiDecoder from 'abi-decoder' +import log from 'loglevel' import { TRANSACTION_TYPE_CANCEL, TRANSACTION_STATUS_CONFIRMED, } from '../../../../app/scripts/controllers/transactions/enums' import { MESSAGE_TYPE } from '../../../../app/scripts/lib/enums' import { getEtherscanNetworkPrefix } from '../../../lib/etherscan-prefix-for-network' -import fetchWithCache from './fetch-with-cache' - import { TOKEN_METHOD_TRANSFER, TOKEN_METHOD_APPROVE, @@ -26,8 +25,8 @@ import { CANCEL_ATTEMPT_ACTION_KEY, DEPOSIT_TRANSACTION_KEY, } from '../constants/transactions' +import fetchWithCache from './fetch-with-cache' -import log from 'loglevel' import { addCurrencies } from './conversion-util' abiDecoder.addABI(abi) @@ -46,9 +45,8 @@ async function getMethodFrom4Byte (fourBytePrefix) { if (fourByteResponse.count === 1) { return fourByteResponse.results[0].text_signature - } else { - return null } + return null } let registry @@ -142,9 +140,8 @@ export function getTransactionActionKey (transaction) { return DECRYPT_REQUEST_KEY } else if (type === MESSAGE_TYPE.ETH_GET_ENCRYPTION_PUBLIC_KEY) { return ENCRYPTION_PUBLIC_KEY_REQUEST_KEY - } else { - return SIGNATURE_REQUEST_KEY } + return SIGNATURE_REQUEST_KEY } if (isConfirmDeployContract(transaction)) { @@ -181,12 +178,12 @@ export function getLatestSubmittedTxWithNonce (transactions = [], nonce = '0x0') const { submittedTime, txParams: { nonce: currentNonce } = {} } = current if (currentNonce === nonce) { - return acc.submittedTime - ? submittedTime > acc.submittedTime ? current : acc - : current - } else { - return acc + if (!acc.submittedTime) { + return current + } + return submittedTime > acc.submittedTime ? current : acc } + return acc }, {}) } @@ -237,7 +234,7 @@ export function getStatusKey (transaction) { */ export function getBlockExplorerUrlForTx (networkId, hash, rpcPrefs = {}) { if (rpcPrefs.blockExplorerUrl) { - return `${rpcPrefs.blockExplorerUrl.replace(/\/+$/, '')}/tx/${hash}` + return `${rpcPrefs.blockExplorerUrl.replace(/\/+$/u, '')}/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 f69e41112..ab8b8ba7b 100644 --- a/ui/app/helpers/utils/transactions.util.test.js +++ b/ui/app/helpers/utils/transactions.util.test.js @@ -1,5 +1,5 @@ -import * as utils from './transactions.util' import assert from 'assert' +import * as utils from './transactions.util' describe('Transactions utils', function () { describe('getTokenData', function () { diff --git a/ui/app/helpers/utils/util.js b/ui/app/helpers/utils/util.js index a6726cdba..3382104fd 100644 --- a/ui/app/helpers/utils/util.js +++ b/ui/app/helpers/utils/util.js @@ -1,7 +1,8 @@ +import punycode from 'punycode' import abi from 'human-standard-token-abi' +import BigNumber from 'bignumber.js' import ethUtil from 'ethereumjs-util' import { DateTime } from 'luxon' -import punycode from 'punycode' // formatData :: ( date: ) -> String export function formatDate (date, format = 'M/d/y \'at\' T') { @@ -58,7 +59,7 @@ export function addressSummary (address, firstSegLength = 10, lastSegLength = 4, if (!includeHex) { checked = ethUtil.stripHexPrefix(checked) } - return checked ? checked.slice(0, firstSegLength) + '...' + checked.slice(checked.length - lastSegLength) : '...' + return checked ? `${checked.slice(0, firstSegLength)}...${checked.slice(checked.length - lastSegLength)}` : '...' } export function isValidAddress (address) { @@ -75,7 +76,7 @@ export function isValidDomainName (address) { // Checks that the domain consists of at least one valid domain pieces separated by periods, followed by a tld // Each piece of domain name has only the characters a-z, 0-9, and a hyphen (but not at the start or end of chunk) // 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]$/) + .match(/^(?:[a-z0-9](?:[-a-z0-9]*[a-z0-9])?\.)+[a-z0-9][-a-z0-9]*[a-z0-9]$/u) return match !== null } @@ -102,10 +103,10 @@ export function parseBalance (balance) { let afterDecimal const wei = numericBalance(balance) const weiString = wei.toString() - const trailingZeros = /0+$/ + const trailingZeros = /0+$/u const beforeDecimal = weiString.length > 18 ? weiString.slice(0, weiString.length - 18) : '0' - afterDecimal = ('000000000000000000' + wei).slice(-18).replace(trailingZeros, '') + afterDecimal = (`000000000000000000${wei}`).slice(-18).replace(trailingZeros, '') if (afterDecimal === '') { afterDecimal = '0' } @@ -122,18 +123,18 @@ export function formatBalance (balance, decimalsToKeep, needsParse = true, ticke if (decimalsToKeep === undefined) { if (beforeDecimal === '0') { if (afterDecimal !== '0') { - const sigFigs = afterDecimal.match(/^0*(.{2})/) // default: grabs 2 most significant digits + const sigFigs = afterDecimal.match(/^0*(.{2})/u) // default: grabs 2 most significant digits if (sigFigs) { 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') - formatted = beforeDecimal + '.' + afterDecimal.slice(0, decimalsToKeep) + ` ${ticker}` + formatted = `${beforeDecimal}.${afterDecimal.slice(0, decimalsToKeep)} ${ticker}` } return formatted } @@ -176,12 +177,10 @@ export function shortenBalance (balance, decimalsToKeep = 1) { const stringBalance = convertedBalance.toString() if (stringBalance.split('.')[1].length > 3) { return convertedBalance.toFixed(3) - } else { - return stringBalance } - } else { - return convertedBalance.toFixed(decimalsToKeep) + return stringBalance } + return convertedBalance.toFixed(decimalsToKeep) } // Takes a BN and an ethereum currency name, @@ -189,8 +188,9 @@ export function shortenBalance (balance, decimalsToKeep = 1) { export function normalizeToWei (amount, currency) { try { return amount.mul(bnTable.wei).div(bnTable[currency]) - } catch (e) {} - return amount + } catch (e) { + return amount + } } export function normalizeEthStringToWei (str) { @@ -218,7 +218,7 @@ export function normalizeNumberToWei (n, currency) { } export function isHex (str) { - return Boolean(str.match(/^(0x)?[0-9a-fA-F]+$/)) + return Boolean(str.match(/^(0x)?[0-9a-fA-F]+$/u)) } export function getContractAtAddress (tokenAddress) { @@ -240,6 +240,7 @@ export function getRandomFileName () { } export function exportAsFile (filename, data, type = 'text/csv') { + // eslint-disable-next-line no-param-reassign filename = filename || getRandomFileName() // source: https://stackoverflow.com/a/33542499 by Ludovic Feltz const blob = new window.Blob([data], { type }) @@ -353,3 +354,18 @@ export function checkExistingAddresses (address, list = []) { return list.some(matchesAddress) } + +/** + * Given a number and specified precision, returns that number in base 10 with a maximum of precision + * significant digits, but without any trailing zeros after the decimal point To be used when wishing + * to display only as much digits to the user as necessary + * + * @param {string | number | BigNumber} n - The number to format + * @param {number} precision - The maximum number of significant digits in the return value + * @returns {string} The number in decimal form, with <= precision significant digits and no decimal trailing zeros + */ +export function toPrecisionWithoutTrailingZeros (n, precision) { + return (new BigNumber(n)) + .toPrecision(precision) + .replace(/(\.[0-9]*[1-9])0*|(\.0*)/u, '$1') +} diff --git a/ui/app/helpers/utils/util.test.js b/ui/app/helpers/utils/util.test.js index ef1f5f153..0a930e413 100644 --- a/ui/app/helpers/utils/util.test.js +++ b/ui/app/helpers/utils/util.test.js @@ -307,7 +307,7 @@ describe('util', function () { describe('#getRandomFileName', function () { it('should only return a string containing alphanumeric characters', function () { const result = util.getRandomFileName() - assert(result.match(/^[a-zA-Z0-9]*$/g)) + assert(result.match(/^[a-zA-Z0-9]*$/ug)) }) // 50 samples @@ -348,4 +348,48 @@ describe('util', function () { assert(util.checkExistingAddresses('b', tokenList) === false) }) }) + + describe('toPrecisionWithoutTrailingZeros', function () { + const testData = [ + { args: ['0', 9], result: '0' }, + { args: [0, 9], result: '0' }, + { args: ['0.0', 9], result: '0' }, + { args: ['0.000000000000', 9], result: '0' }, + { args: ['1', 9], result: '1' }, + { args: [1], result: '1' }, + { args: ['1.0', 9], result: '1' }, + { args: ['1.000000000', 9], result: '1' }, + { args: ['000000001', 9], result: '1' }, + { args: ['000000001.0', 9], result: '1' }, + { args: ['100000000', 9], result: '100000000' }, + { args: ['100000000.00001', 9], result: '100000000' }, + { args: ['100.00001', 9], result: '100.00001' }, + { args: ['100.00001000', 9], result: '100.00001' }, + { args: ['100.000010001', 9], result: '100.00001' }, + { args: ['10.010101', 9], result: '10.010101' }, + { args: ['0.1', 5], result: '0.1' }, + { args: ['0.10', 5], result: '0.1' }, + { args: ['0.1010', 5], result: '0.101' }, + { args: ['0.01001', 5], result: '0.01001' }, + { args: ['0.010010', 5], result: '0.01001' }, + { args: ['0.010011', 5], result: '0.010011' }, + { args: ['1.01005', 5], result: '1.0101' }, + { args: ['1.000049', 5], result: '1' }, + { args: ['1.00005', 5], result: '1.0001' }, + { args: ['0.0000123456789', 9], result: '0.0000123456789' }, + { args: ['1.0000123456789', 10], result: '1.000012346' }, + { args: ['10000.0000012345679', 10], result: '10000' }, + { args: ['1000000000000', 10], result: '1e+12' }, + { args: ['1000050000000', 10], result: '1.00005e+12' }, + { 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.equal(util.toPrecisionWithoutTrailingZeros(...args), result) + }) + }) + }) }) diff --git a/ui/app/hooks/tests/useCancelTransaction.test.js b/ui/app/hooks/tests/useCancelTransaction.test.js index 7e887486e..a355ee5e5 100644 --- a/ui/app/hooks/tests/useCancelTransaction.test.js +++ b/ui/app/hooks/tests/useCancelTransaction.test.js @@ -1,5 +1,5 @@ -import * as reactRedux from 'react-redux' 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' @@ -8,7 +8,6 @@ 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() @@ -32,6 +31,7 @@ describe('useCancelTransaction', function () { balance: '0x3', } } + return undefined }) }) transactions.forEach((transactionGroup) => { @@ -45,7 +45,7 @@ describe('useCancelTransaction', function () { it(`should return a function that kicks off cancellation for id ${transactionId}`, function () { const { result } = renderHook(() => useCancelTransaction(transactionGroup)) assert.equal(typeof result.current[1], 'function') - result.current[1]({ preventDefault: () => {}, stopPropagation: () => {} }) + result.current[1]({ preventDefault: () => undefined, stopPropagation: () => undefined }) assert.equal( dispatch.calledWith( showModal({ @@ -63,7 +63,6 @@ describe('useCancelTransaction', function () { }) }) - describe('when account has sufficient balance to cover gas', function () { before(function () { useSelector = sinon.stub(reactRedux, 'useSelector') @@ -75,6 +74,7 @@ describe('useCancelTransaction', function () { balance: '0x9C2007651B2500000', } } + return undefined }) }) transactions.forEach((transactionGroup) => { @@ -88,7 +88,7 @@ describe('useCancelTransaction', function () { it(`should return a function that kicks off cancellation for id ${transactionId}`, function () { const { result } = renderHook(() => useCancelTransaction(transactionGroup)) assert.equal(typeof result.current[1], 'function') - result.current[1]({ preventDefault: () => {}, stopPropagation: () => {} }) + result.current[1]({ preventDefault: () => undefined, stopPropagation: () => undefined }) assert.equal( dispatch.calledWith( showModal({ @@ -106,7 +106,6 @@ describe('useCancelTransaction', function () { }) }) - after(function () { sinon.restore() }) diff --git a/ui/app/hooks/tests/useCurrencyDisplay.test.js b/ui/app/hooks/tests/useCurrencyDisplay.test.js index 793af907f..8b3f6910a 100644 --- a/ui/app/hooks/tests/useCurrencyDisplay.test.js +++ b/ui/app/hooks/tests/useCurrencyDisplay.test.js @@ -1,8 +1,8 @@ import assert from 'assert' import { renderHook } from '@testing-library/react-hooks' import * as reactRedux from 'react-redux' -import { useCurrencyDisplay } from '../useCurrencyDisplay' import sinon from 'sinon' +import { useCurrencyDisplay } from '../useCurrencyDisplay' import { getCurrentCurrency, getNativeCurrency, getConversionRate } from '../../selectors' const tests = [ @@ -95,7 +95,6 @@ const tests = [ }, ] - describe('useCurrencyDisplay', function () { tests.forEach(({ input: { value, ...restProps }, result }) => { describe(`when input is { value: ${value}, decimals: ${restProps.numberOfDecimals}, denomation: ${restProps.denomination} }`, function () { @@ -108,9 +107,10 @@ describe('useCurrencyDisplay', function () { } else if (selector === getConversionRate) { return 280.45 } + return undefined }) const hookReturn = renderHook(() => useCurrencyDisplay(value, restProps)) - const [ displayValue, parts ] = hookReturn.result.current + const [displayValue, parts] = hookReturn.result.current stub.restore() it(`should return ${result.displayValue} as displayValue`, function () { assert.equal(displayValue, result.displayValue) diff --git a/ui/app/hooks/tests/useRetryTransaction.test.js b/ui/app/hooks/tests/useRetryTransaction.test.js index d6c55d0f8..b922bd92c 100644 --- a/ui/app/hooks/tests/useRetryTransaction.test.js +++ b/ui/app/hooks/tests/useRetryTransaction.test.js @@ -1,5 +1,5 @@ -import * as reactRedux from 'react-redux' 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' @@ -12,7 +12,7 @@ describe('useRetryTransaction', function () { describe('when transaction meets retry enabled criteria', function () { const dispatch = sinon.spy(() => Promise.resolve({ blockTime: 0 })) const trackEvent = sinon.spy() - const event = { preventDefault: () => {}, stopPropagation: () => {} } + const event = { preventDefault: () => undefined, stopPropagation: () => undefined } before(function () { sinon.stub(reactRedux, 'useDispatch').returns(dispatch) diff --git a/ui/app/hooks/tests/useTokenData.test.js b/ui/app/hooks/tests/useTokenData.test.js index 9bc507de4..10482b63b 100644 --- a/ui/app/hooks/tests/useTokenData.test.js +++ b/ui/app/hooks/tests/useTokenData.test.js @@ -1,6 +1,6 @@ -import { useTokenData } from '../useTokenData' import assert from 'assert' import { renderHook } from '@testing-library/react-hooks' +import { useTokenData } from '../useTokenData' const tests = [ { @@ -65,9 +65,9 @@ const tests = [ describe('useTokenData', function () { tests.forEach((test) => { - const testTitle = test.tokenData !== null - ? `should return properly decoded data with _value ${test.tokenData.params[1].value}` - : `should return null when no data provided` + const testTitle = test.tokenData === null + ? `should return null when no data provided` + : `should return properly decoded data with _value ${test.tokenData.params[1].value}` it(testTitle, function () { const { result } = renderHook(() => useTokenData(test.data)) assert.deepEqual(result.current, test.tokenData) diff --git a/ui/app/hooks/tests/useTokenDisplayValue.test.js b/ui/app/hooks/tests/useTokenDisplayValue.test.js index bb8464f8a..ed0c81e4f 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 sinon from 'sinon' const tests = [ { @@ -118,7 +118,6 @@ const tests = [ }, ] - describe('useTokenDisplayValue', function () { tests.forEach((test, idx) => { describe(`when input is decimals: ${test.token.decimals} and value: ${test.tokenValue}`, function () { diff --git a/ui/app/hooks/tests/useTransactionDisplayData.test.js b/ui/app/hooks/tests/useTransactionDisplayData.test.js index 2cae72bbf..a8eb15148 100644 --- a/ui/app/hooks/tests/useTransactionDisplayData.test.js +++ b/ui/app/hooks/tests/useTransactionDisplayData.test.js @@ -1,5 +1,5 @@ -import * as reactRedux from 'react-redux' 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' @@ -11,9 +11,9 @@ import * as i18nhooks from '../useI18nContext' import { getMessage } from '../../helpers/utils/i18n-helper' import messages from '../../../../app/_locales/en/messages.json' - const expectedResults = [ - { title: 'Send ETH', + { + title: 'Send ETH', category: 'send', subtitle: 'To: 0xffe5...1a97', subtitleContainsOrigin: false, @@ -23,8 +23,10 @@ const expectedResults = [ recipientAddress: '0xffe5bc4e8f1f969934d773fa67da095d2e491a97', secondaryCurrency: '-1 ETH', isPending: false, - status: 'confirmed' }, - { title: 'Send ETH', + status: 'confirmed', + }, + { + title: 'Send ETH', category: 'send', subtitle: 'To: 0x0ccc...8848', subtitleContainsOrigin: false, @@ -34,8 +36,10 @@ const expectedResults = [ recipientAddress: '0x0ccc8aeeaf5ce790f3b448325981a143fdef8848', secondaryCurrency: '-2 ETH', isPending: false, - status: 'confirmed' }, - { title: 'Send ETH', + status: 'confirmed', + }, + { + title: 'Send ETH', category: 'send', subtitle: 'To: 0xffe5...1a97', subtitleContainsOrigin: false, @@ -45,8 +49,10 @@ const expectedResults = [ recipientAddress: '0xffe5bc4e8f1f969934d773fa67da095d2e491a97', secondaryCurrency: '-2 ETH', isPending: false, - status: 'confirmed' }, - { title: 'Receive', + status: 'confirmed', + }, + { + title: 'Receive', category: 'receive', subtitle: 'From: 0x31b9...4523', subtitleContainsOrigin: false, @@ -56,8 +62,10 @@ const expectedResults = [ recipientAddress: '0x9eca64466f257793eaa52fcfff5066894b76a149', secondaryCurrency: '18.75 ETH', isPending: false, - status: 'confirmed' }, - { title: 'Receive', + status: 'confirmed', + }, + { + title: 'Receive', category: 'receive', subtitle: 'From: 0x9eca...a149', subtitleContainsOrigin: false, @@ -67,8 +75,10 @@ const expectedResults = [ recipientAddress: '0x9eca64466f257793eaa52fcfff5066894b76a149', secondaryCurrency: '0 ETH', isPending: false, - status: 'confirmed' }, - { title: 'Receive', + status: 'confirmed', + }, + { + title: 'Receive', category: 'receive', subtitle: 'From: 0xee01...febb', subtitleContainsOrigin: false, @@ -78,7 +88,8 @@ const expectedResults = [ recipientAddress: '0x9eca64466f257793eaa52fcfff5066894b76a149', secondaryCurrency: '1 ETH', isPending: false, - status: 'confirmed' }, + status: 'confirmed', + }, ] let useSelector, useI18nContext, useTokenFiatAmount @@ -105,9 +116,8 @@ describe('useTransactionDisplayData', function () { return 'ETH' } else if (selector === getCurrentCurrency) { return 'ETH' - } else { - return null } + return null }) }) transactions.forEach((transactionGroup, idx) => { diff --git a/ui/app/hooks/tests/useUserPreferencedCurrency.test.js b/ui/app/hooks/tests/useUserPreferencedCurrency.test.js index 61aba3cb5..b5d7b47e9 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 { useUserPreferencedCurrency } from '../useUserPreferencedCurrency' import * as reactRedux from 'react-redux' -import { getPreferences, getShouldShowFiat } from '../../selectors' import sinon from 'sinon' +import { useUserPreferencedCurrency } from '../useUserPreferencedCurrency' +import { getPreferences, getShouldShowFiat } from '../../selectors' const tests = [ { @@ -117,13 +117,11 @@ function getFakeUseSelector (state) { return state } else if (selector === getShouldShowFiat) { return state.showFiat - } else { - 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 () { diff --git a/ui/app/hooks/useCancelTransaction.js b/ui/app/hooks/useCancelTransaction.js index 4dd0cc916..547697360 100644 --- a/ui/app/hooks/useCancelTransaction.js +++ b/ui/app/hooks/useCancelTransaction.js @@ -5,7 +5,6 @@ import { isBalanceSufficient } from '../pages/send/send.utils' import { getHexGasTotal, increaseLastGasPrice } from '../helpers/utils/confirm-tx.util' import { getConversionRate, getSelectedAccount } from '../selectors' - /** * Determine whether a transaction can be cancelled and provide a method to * kick off the process of cancellation. @@ -19,7 +18,7 @@ import { getConversionRate, getSelectedAccount } from '../selectors' export function useCancelTransaction (transactionGroup) { const { primaryTransaction, initialTransaction } = transactionGroup const gasPrice = primaryTransaction.txParams?.gasPrice - const id = initialTransaction.id + const { id } = initialTransaction const dispatch = useDispatch() const selectedAccount = useSelector(getSelectedAccount) const conversionRate = useSelector(getConversionRate) @@ -29,7 +28,6 @@ export function useCancelTransaction (transactionGroup) { return dispatch(showModal({ name: 'CANCEL_TRANSACTION', transactionId: id, originalGasPrice: gasPrice })) }, [dispatch, id, gasPrice]) - const hasEnoughCancelGas = primaryTransaction.txParams && isBalanceSufficient({ amount: '0x0', gasTotal: getHexGasTotal({ diff --git a/ui/app/hooks/useCurrencyDisplay.js b/ui/app/hooks/useCurrencyDisplay.js index 17568b874..4e2c99e3f 100644 --- a/ui/app/hooks/useCurrencyDisplay.js +++ b/ui/app/hooks/useCurrencyDisplay.js @@ -61,6 +61,5 @@ export function useCurrencyDisplay (inputValue, { displayValue, prefix, numberOf suffix = opts.suffix || toCurrency.toUpperCase() } - - return [`${prefix || ''}${value}${suffix ? ' ' + suffix : ''}`, { prefix, value, suffix }] + return [`${prefix || ''}${value}${suffix ? ` ${suffix}` : ''}`, { prefix, value, suffix }] } diff --git a/ui/app/hooks/useMetricEvent.js b/ui/app/hooks/useMetricEvent.js index a5a883b5f..a701bd933 100644 --- a/ui/app/hooks/useMetricEvent.js +++ b/ui/app/hooks/useMetricEvent.js @@ -1,7 +1,6 @@ import { useContext, useCallback } from 'react' import { MetaMetricsContext } from '../contexts/metametrics' - export function useMetricEvent (config = {}, overrides = {}) { const metricsEvent = useContext(MetaMetricsContext) const trackEvent = useCallback(() => metricsEvent(config, overrides), [config, metricsEvent, overrides]) diff --git a/ui/app/hooks/useRetryTransaction.js b/ui/app/hooks/useRetryTransaction.js index 9b0a9e5f5..1f3ffe701 100644 --- a/ui/app/hooks/useRetryTransaction.js +++ b/ui/app/hooks/useRetryTransaction.js @@ -10,7 +10,6 @@ import { import { increaseLastGasPrice } from '../helpers/utils/confirm-tx.util' import { useMetricEvent } from './useMetricEvent' - /** * Provides a reusable hook that, given a transactionGroup, will return * a method for beginning the retry process diff --git a/ui/app/hooks/useTimeout.js b/ui/app/hooks/useTimeout.js index 534c68216..244e9a34c 100644 --- a/ui/app/hooks/useTimeout.js +++ b/ui/app/hooks/useTimeout.js @@ -7,7 +7,7 @@ import { useState, useEffect, useRef, useCallback } from 'react' * @param {number} delay - delay in ms * @param {boolean} [immediate] - determines whether the timeout is invoked immediately * - * @return {Function} + * @return {Function|undefined} */ export function useTimeout (cb, delay, immediate = true) { const saveCb = useRef() @@ -19,7 +19,7 @@ export function useTimeout (cb, delay, immediate = true) { useEffect(() => { if (timeoutId !== 'start') { - return + return undefined } const id = setTimeout(() => { diff --git a/ui/app/hooks/useTokenDisplayValue.js b/ui/app/hooks/useTokenDisplayValue.js index 107a2c11e..b7d92af7c 100644 --- a/ui/app/hooks/useTokenDisplayValue.js +++ b/ui/app/hooks/useTokenDisplayValue.js @@ -1,5 +1,5 @@ -import { getTokenValue, calcTokenAmount } from '../helpers/utils/token-util' import { useMemo } from 'react' +import { getTokenValue, calcTokenAmount } from '../helpers/utils/token-util' import { useTokenData } from './useTokenData' /** diff --git a/ui/app/hooks/useTokenTracker.js b/ui/app/hooks/useTokenTracker.js index 406eade3f..55a92273b 100644 --- a/ui/app/hooks/useTokenTracker.js +++ b/ui/app/hooks/useTokenTracker.js @@ -3,7 +3,6 @@ import TokenTracker from '@metamask/eth-token-tracker' import { useSelector } from 'react-redux' import { getCurrentNetwork, getSelectedAddress } from '../selectors' - export function useTokenTracker (tokens) { const network = useSelector(getCurrentNetwork) const userAddress = useSelector(getSelectedAddress) @@ -13,14 +12,14 @@ export function useTokenTracker (tokens) { const [error, setError] = useState(null) const tokenTracker = useRef(null) - const updateBalances = useCallback((tokensWithBalances) => { - setTokensWithBalances(tokensWithBalances) + const updateBalances = useCallback((tokenWithBalances) => { + setTokensWithBalances(tokenWithBalances) setLoading(false) setError(null) }, []) - const showError = useCallback((error) => { - setError(error) + const showError = useCallback((err) => { + setError(err) setLoading(false) }, []) @@ -57,7 +56,6 @@ export function useTokenTracker (tokens) { return teardownTracker }, [teardownTracker]) - // Effect to set loading state and initialize tracker when values change useEffect(() => { // This effect will only run initially and when: diff --git a/ui/app/hooks/useTransactionDisplayData.js b/ui/app/hooks/useTransactionDisplayData.js index 52d161e7d..3793299f5 100644 --- a/ui/app/hooks/useTransactionDisplayData.js +++ b/ui/app/hooks/useTransactionDisplayData.js @@ -2,11 +2,8 @@ import { useSelector } from 'react-redux' import { getKnownMethodData } from '../selectors/selectors' import { getTransactionActionKey, getStatusKey } from '../helpers/utils/transactions.util' import { camelCaseToCapitalize } from '../helpers/utils/common.util' -import { useI18nContext } from './useI18nContext' -import { useTokenFiatAmount } from './useTokenFiatAmount' import { PRIMARY, SECONDARY } from '../helpers/constants/common' import { getTokenToAddress } from '../helpers/utils/token-util' -import { useUserPreferencedCurrency } from './useUserPreferencedCurrency' import { formatDateWithYearContext, shortenAddress, stripHttpSchemes } from '../helpers/utils/util' import { CONTRACT_INTERACTION_KEY, @@ -24,10 +21,13 @@ import { PENDING_STATUS_HASH, TOKEN_CATEGORY_HASH, } from '../helpers/constants/transactions' +import { getTokens } from '../ducks/metamask/metamask' +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 { getTokens } from '../ducks/metamask/metamask' /** * @typedef {Object} TransactionDisplayData @@ -84,7 +84,7 @@ export function useTransactionDisplayData (transactionGroup) { // transfers, we pass an additional argument to these hooks that will be // false for non-token transactions. This additional argument forces the // hook to return null - const token = isTokenCategory && knownTokens.find((token) => token.address === recipientAddress) + const token = isTokenCategory && 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) @@ -99,7 +99,7 @@ export function useTransactionDisplayData (transactionGroup) { // 3. Deposit // 4. Site interaction // 5. Approval - if (transactionCategory == null) { + if (transactionCategory === null || transactionCategory === undefined) { category = TRANSACTION_CATEGORY_SIGNATURE_REQUEST title = t('signatureRequest') subtitle = origin diff --git a/ui/app/hooks/useTransactionTimeRemaining.js b/ui/app/hooks/useTransactionTimeRemaining.js index a37a29ae6..10ac8545f 100644 --- a/ui/app/hooks/useTransactionTimeRemaining.js +++ b/ui/app/hooks/useTransactionTimeRemaining.js @@ -1,9 +1,9 @@ -import { getEstimatedGasPrices, getEstimatedGasTimes, getFeatureFlags, getIsMainnet } from '../selectors' -import { hexWEIToDecGWEI } from '../helpers/utils/conversions.util' import { useSelector } from 'react-redux' import { useRef, useEffect, useState, useMemo } from 'react' import { isEqual } from 'lodash' import { captureException } from '@sentry/browser' +import { hexWEIToDecGWEI } from '../helpers/utils/conversions.util' +import { getEstimatedGasPrices, getEstimatedGasTimes, getFeatureFlags, getIsMainnet } from '../selectors' import { getRawTimeEstimateData } from '../helpers/utils/gas-time-estimates.util' import { getCurrentLocale } from '../ducks/metamask/metamask' @@ -64,7 +64,7 @@ export function useTransactionTimeRemaining ( captureException(error) return NaN } - }, [ currentGasPrice, gasPrices, estimatedTimes ]) + }, [currentGasPrice, gasPrices, estimatedTimes]) useEffect(() => { if ( @@ -85,6 +85,7 @@ export function useTransactionTimeRemaining ( }, 10000) return () => clearInterval(interval.current) } + return undefined }, [ isMainNet, transactionTimeFeatureActive, diff --git a/ui/app/hooks/useUserPreferencedCurrency.js b/ui/app/hooks/useUserPreferencedCurrency.js index d8d3a1759..986ef6dd7 100644 --- a/ui/app/hooks/useUserPreferencedCurrency.js +++ b/ui/app/hooks/useUserPreferencedCurrency.js @@ -1,5 +1,5 @@ -import { getPreferences, getShouldShowFiat, getNativeCurrency } from '../selectors' import { useSelector } from 'react-redux' +import { getPreferences, getShouldShowFiat, getNativeCurrency } from '../selectors' import { PRIMARY, SECONDARY, ETH } from '../helpers/constants/common' /** diff --git a/ui/app/pages/add-token/add-token.component.js b/ui/app/pages/add-token/add-token.component.js index 158f96a92..48e306fc8 100644 --- a/ui/app/pages/add-token/add-token.component.js +++ b/ui/app/pages/add-token/add-token.component.js @@ -5,10 +5,10 @@ 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 TokenList from './token-list' -import TokenSearch from './token-search' import PageContainer from '../../components/ui/page-container' import { Tabs, Tab } from '../../components/ui/tabs' +import TokenList from './token-list' +import TokenSearch from './token-search' const emptyAddr = '0x0000000000000000000000000000000000000000' diff --git a/ui/app/pages/add-token/add-token.container.js b/ui/app/pages/add-token/add-token.container.js index 2e7354b23..9f3f6d21e 100644 --- a/ui/app/pages/add-token/add-token.container.js +++ b/ui/app/pages/add-token/add-token.container.js @@ -1,8 +1,8 @@ import { connect } from 'react-redux' -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 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 fa9e4bd19..8138845e7 100644 --- a/ui/app/pages/add-token/tests/add-token.test.js +++ b/ui/app/pages/add-token/tests/add-token.test.js @@ -1,10 +1,10 @@ +import assert from 'assert' import React from 'react' import { Provider } from 'react-redux' -import assert from 'assert' import sinon from 'sinon' import configureMockStore from 'redux-mock-store' import { mountWithRouter } from '../../../../../test/lib/render-helpers' -import AddToken from '../index' +import AddToken from '..' describe('Add Token', function () { let wrapper @@ -19,7 +19,7 @@ describe('Add Token', function () { const props = { history: { - push: sinon.stub().callsFake(() => {}), + push: sinon.stub().callsFake(() => undefined), }, setPendingTokens: sinon.spy(), clearPendingTokens: sinon.spy(), @@ -58,7 +58,6 @@ describe('Add Token', function () { assert.equal(wrapper.find('AddToken').instance().state.customAddress, tokenAddress) }) - it('edits token symbol', function () { const tokenSymbol = 'META' const event = { target: { value: tokenSymbol } } diff --git a/ui/app/pages/add-token/token-list/token-list-placeholder/index.scss b/ui/app/pages/add-token/token-list/token-list-placeholder/index.scss index a823b6aae..aa6d0a0e9 100644 --- a/ui/app/pages/add-token/token-list/token-list-placeholder/index.scss +++ b/ui/app/pages/add-token/token-list/token-list-placeholder/index.scss @@ -18,8 +18,6 @@ } &__link { - @extend %link; - margin-top: 0.5rem; } } 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 20f550927..ae14581e8 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,5 +1,6 @@ import React, { Component } from 'react' import PropTypes from 'prop-types' +import Button from '../../../../components/ui/button' export default class TokenListPlaceholder extends Component { static contextTypes = { @@ -13,14 +14,15 @@ export default class TokenListPlaceholder extends Component {
{ this.context.t('addAcquiredTokens') }
- { this.context.t('learnMore') } - +
) } 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 82aaae3fc..460c7f15f 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 @@ -6,7 +6,7 @@ import InputAdornment from '@material-ui/core/InputAdornment' import TextField from '../../../components/ui/text-field' const contractList = Object.entries(contractMap) - .map(([address, tokenData]) => Object.assign({}, tokenData, { address })) + .map(([address, tokenData]) => ({ ...tokenData, address })) .filter((tokenData) => Boolean(tokenData.erc20)) const fuse = new Fuse(contractList, { diff --git a/ui/app/pages/asset/asset.js b/ui/app/pages/asset/asset.js index 7cdc08ec7..fa9479eb0 100644 --- a/ui/app/pages/asset/asset.js +++ b/ui/app/pages/asset/asset.js @@ -12,7 +12,7 @@ const Asset = () => { const tokens = useSelector(getTokens) const { asset } = useParams() - const token = tokens.find((token) => token.address === asset) + const token = tokens.find(({ address }) => address === asset) let content if (token) { 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 876fbd761..28b04ba40 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 @@ -92,7 +92,7 @@ export default class ConfirmAddSuggestedToken extends Component {
{ Object.entries(pendingTokens) - .map(([ address, token ]) => { + .map(([address, token]) => { const { name, symbol, image } = token return ( 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 1b84279b1..319d1ed82 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,9 +1,9 @@ import { connect } from 'react-redux' import { compose } from 'redux' -import ConfirmAddSuggestedToken from './confirm-add-suggested-token.component' 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 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 2f98242eb..f79d962eb 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 @@ -58,7 +58,7 @@ export default class ConfirmAddToken extends Component {
{ Object.entries(pendingTokens) - .map(([ address, token ]) => { + .map(([address, token]) => { const { name, symbol } = token return ( 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 d04f15917..8c09ad837 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,8 +1,8 @@ import { connect } from 'react-redux' -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 diff --git a/ui/app/pages/confirm-approve/confirm-approve-content/index.scss b/ui/app/pages/confirm-approve/confirm-approve-content/index.scss index 70771fcaf..d6a5d71c9 100644 --- a/ui/app/pages/confirm-approve/confirm-approve-content/index.scss +++ b/ui/app/pages/confirm-approve/confirm-approve-content/index.scss @@ -4,7 +4,6 @@ align-items: center; width: 100%; height: 100%; - font-family: Roboto; font-style: normal; &__identicon-wrapper { @@ -21,7 +20,6 @@ flex-flow: column; align-items: center; width: 390px; - font-family: Roboto; font-style: normal; padding-left: 24px; padding-right: 24px; diff --git a/ui/app/pages/confirm-approve/confirm-approve.js b/ui/app/pages/confirm-approve/confirm-approve.js index b5c34c390..5bd634113 100644 --- a/ui/app/pages/confirm-approve/confirm-approve.js +++ b/ui/app/pages/confirm-approve/confirm-approve.js @@ -2,8 +2,6 @@ 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 ConfirmApproveContent from './confirm-approve-content' -import { getCustomTxParamsData } from './confirm-approve.util' import { showModal } from '../../store/actions' import { getTokenData, @@ -21,6 +19,8 @@ import { } from '../../selectors/confirm-transaction' import { getCurrentCurrency, getDomainMetadata } from '../../selectors/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() @@ -107,6 +107,7 @@ export default function ConfirmApprove () { showCustomizeGasModal={() => dispatch(showModal({ name: 'CUSTOMIZE_GAS', txData }))} showEditApprovalPermissionModal={ ({ + /* eslint-disable no-shadow */ customTokenAmount, decimals, origin, @@ -114,6 +115,7 @@ export default function ConfirmApprove () { tokenAmount, tokenBalance, tokenSymbol, + /* eslint-enable no-shadow */ }) => dispatch( showModal({ name: 'EDIT_APPROVAL_PERMISSION', diff --git a/ui/app/pages/confirm-approve/confirm-approve.util.js b/ui/app/pages/confirm-approve/confirm-approve.util.js index 0318c6bed..02ae4fe1e 100644 --- a/ui/app/pages/confirm-approve/confirm-approve.util.js +++ b/ui/app/pages/confirm-approve/confirm-approve.util.js @@ -1,5 +1,5 @@ import { decimalToHex } from '../../helpers/utils/conversions.util' -import { calcTokenValue } from '../../helpers/utils/token-util.js' +import { calcTokenValue } from '../../helpers/utils/token-util' import { getTokenData } from '../../helpers/utils/transactions.util' export function getCustomTxParamsData (data, { customPermissionAmount, decimals }) { 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 a95e6d4cd..57310d7b2 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 @@ -3,10 +3,10 @@ import PropTypes from 'prop-types' import copyToClipboard from 'copy-to-clipboard' import classnames from 'classnames' -import AccountListItem from '../send/account-list-item/account-list-item.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-v2' +import Tooltip from '../../components/ui/tooltip' import Copy from '../../components/ui/icon/copy-icon.component' import { ENVIRONMENT_TYPE_NOTIFICATION } from '../../../../app/scripts/lib/enums' @@ -119,7 +119,6 @@ export default class ConfirmDecryptMessage extends Component {
@@ -221,7 +220,7 @@ export default class ConfirmDecryptMessage extends Component { className="request-decrypt-message__message-text" > { !hasDecrypted && !hasError ? txData.msgParams.data : rawMessage } - { !hasError ? '' : errorMessage } + { hasError ? errorMessage : '' }
{ decryptMessageInline(txData, event).then((result) => { - if (!result.error) { - this.setState({ hasDecrypted: true, rawMessage: result.rawData }) - } else { + if (result.error) { this.setState({ hasError: true, errorMessage: this.context.t('decryptInlineError', [result.error]) }) + } else { + this.setState({ hasDecrypted: true, rawMessage: result.rawData }) } }) }} 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 e068b403f..57d00021a 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 @@ -13,11 +13,12 @@ import { conversionRateSelector, } from '../../selectors' import { clearConfirmTransaction } from '../../ducks/confirm-transaction/confirm-transaction.duck' -import ConfirmDecryptMessage from './confirm-decrypt-message.component' import { getMostRecentOverviewPage } from '../../ducks/history/history' +import ConfirmDecryptMessage from './confirm-decrypt-message.component' function mapStateToProps (state) { - const { confirmTransaction, + const { + confirmTransaction, metamask: { domainMetadata = {} }, } = state @@ -30,7 +31,7 @@ function mapStateToProps (state) { const fromAccount = getTargetAccountWithSendEtherInfo(state, from) return { - txData: txData, + txData, domainMetadata, fromAccount, requester: null, diff --git a/ui/app/css/itcss/components/request-decrypt-message.scss b/ui/app/pages/confirm-decrypt-message/confirm-decrypt-message.scss similarity index 97% rename from ui/app/css/itcss/components/request-decrypt-message.scss rename to ui/app/pages/confirm-decrypt-message/confirm-decrypt-message.scss index 7387e944a..fd2ee53a8 100644 --- a/ui/app/css/itcss/components/request-decrypt-message.scss +++ b/ui/app/pages/confirm-decrypt-message/confirm-decrypt-message.scss @@ -8,7 +8,6 @@ flex-flow: column nowrap; z-index: 25; align-items: center; - font-family: Roboto; position: relative; height: 100%; @@ -63,7 +62,6 @@ &__header__text { color: #5b5d67; - font-family: Roboto; font-size: 22px; line-height: 29px; z-index: 3; @@ -105,7 +103,6 @@ &__account-item { height: 22px; background-color: $white; - font-family: Roboto; line-height: 16px; font-size: 12px; width: 124px; @@ -156,7 +153,6 @@ } &__notice { - font-family: "Avenir Next"; font-size: 14px; line-height: 19px; text-align: center; 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 5ef485c72..3dbba9b8f 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,7 +1,7 @@ import React, { Component } from 'react' import PropTypes from 'prop-types' -import AccountListItem from '../send/account-list-item/account-list-item.component' +import AccountListItem from '../../components/app/account-list-item' import Button from '../../components/ui/button' import Identicon from '../../components/ui/identicon' @@ -99,7 +99,6 @@ export default class ConfirmEncryptionPublicKey extends Component {
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 8d91540e5..7a0b2c37f 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 @@ -14,11 +14,12 @@ import { } from '../../selectors' import { clearConfirmTransaction } from '../../ducks/confirm-transaction/confirm-transaction.duck' -import ConfirmEncryptionPublicKey from './confirm-encryption-public-key.component' import { getMostRecentOverviewPage } from '../../ducks/history/history' +import ConfirmEncryptionPublicKey from './confirm-encryption-public-key.component' function mapStateToProps (state) { - const { confirmTransaction, + const { + confirmTransaction, metamask: { domainMetadata = {} }, } = state @@ -31,8 +32,8 @@ function mapStateToProps (state) { const fromAccount = getTargetAccountWithSendEtherInfo(state, from) return { - txData: txData, - domainMetadata: domainMetadata, + txData, + domainMetadata, fromAccount, requester: null, requesterAddress: null, diff --git a/ui/app/css/itcss/components/request-encryption-public-key.scss b/ui/app/pages/confirm-encryption-public-key/confirm-encryption-public-key.scss similarity index 97% rename from ui/app/css/itcss/components/request-encryption-public-key.scss rename to ui/app/pages/confirm-encryption-public-key/confirm-encryption-public-key.scss index a4d601267..8860ca5d8 100644 --- a/ui/app/css/itcss/components/request-encryption-public-key.scss +++ b/ui/app/pages/confirm-encryption-public-key/confirm-encryption-public-key.scss @@ -8,7 +8,6 @@ flex-flow: column nowrap; z-index: 25; align-items: center; - font-family: Roboto; position: relative; height: 100%; @@ -63,7 +62,6 @@ &__header__text { color: #5b5d67; - font-family: Roboto; font-size: 22px; line-height: 29px; z-index: 3; @@ -105,7 +103,6 @@ &__account-item { height: 22px; background-color: $white; - font-family: Roboto; line-height: 16px; font-size: 12px; width: 124px; @@ -156,7 +153,6 @@ } &__notice { - font-family: "Avenir Next"; font-size: 14px; line-height: 19px; text-align: center; 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 ba0517ab0..330f614a8 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,11 +1,11 @@ import { connect } from 'react-redux' import { compose } from 'redux' import { withRouter } from 'react-router-dom' -import ConfirmSendToken from './confirm-send-token.component' import { clearConfirmTransaction } from '../../ducks/confirm-transaction/confirm-transaction.duck' import { updateSend, showSendTokenPage } from '../../store/actions' import { conversionUtil } from '../../helpers/utils/conversion-util' import { sendTokenTokenAmountAndToAddressSelector } from '../../selectors' +import ConfirmSendToken from './confirm-send-token.component' const mapStateToProps = (state) => { const { tokenAmount } = sendTokenTokenAmountAndToAddressSelector(state) 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 8aea19663..ca690a61a 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 @@ -89,12 +89,11 @@ export default class ConfirmTokenTransactionBase extends Component { if (typeof contractExchangeRate === 'undefined') { return formatCurrency(fiatTransactionTotal, currentCurrency) - } else { - const fiatTransactionAmount = this.getFiatTransactionAmount() - const fiatTotal = addFiat(fiatTransactionAmount, fiatTransactionTotal) - const roundedFiatTotal = roundExponential(fiatTotal) - return formatCurrency(roundedFiatTotal, currentCurrency) } + const fiatTransactionAmount = this.getFiatTransactionAmount() + const fiatTotal = addFiat(fiatTransactionAmount, fiatTransactionTotal) + const roundedFiatTotal = roundExponential(fiatTotal) + return formatCurrency(roundedFiatTotal, currentCurrency) } render () { 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 0faf6b471..8583ea238 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,7 +1,6 @@ import { connect } from 'react-redux' import { compose } from 'redux' import { withRouter } from 'react-router-dom' -import ConfirmTokenTransactionBase from './confirm-token-transaction-base.component' import { contractExchangeRateSelector, transactionFeeSelector, @@ -15,7 +14,7 @@ import { getTokenToAddress, getTokenValue, } from '../../helpers/utils/token-util' - +import ConfirmTokenTransactionBase from './confirm-token-transaction-base.component' const mapStateToProps = (state, ownProps) => { const { match: { params = {} } } = ownProps 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 3b6a7ef9a..4c9ab94e1 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 @@ -731,7 +731,7 @@ export function getMethodName (camelCase) { } return camelCase - .replace(/([a-z])([A-Z])/g, '$1 $2') - .replace(/([A-Z])([a-z])/g, ' $1$2') - .replace(/ +/g, ' ') + .replace(/([a-z])([A-Z])/ug, '$1 $2') + .replace(/([A-Z])([a-z])/ug, ' $1$2') + .replace(/ +/ug, ' ') } 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 096593792..08b0f4581 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 @@ -2,7 +2,6 @@ import { connect } from 'react-redux' import { compose } from 'redux' import { withRouter } from 'react-router-dom' import contractMap from 'eth-contract-metadata' -import ConfirmTransactionBase from './confirm-transaction-base.component' import { clearConfirmTransaction, } from '../../ducks/confirm-transaction/confirm-transaction.duck' @@ -38,6 +37,7 @@ import { transactionFeeSelector, } from '../../selectors' import { getMostRecentOverviewPage } from '../../ducks/history/history' +import ConfirmTransactionBase from './confirm-transaction-base.component' const casedContractMap = Object.keys(contractMap).reduce((acc, base) => { return { @@ -93,13 +93,10 @@ const mapStateToProps = (state, ownProps) => { const { balance } = accounts[fromAddress] const { name: fromName } = identities[fromAddress] const toAddress = propsToAddress || txParamsToAddress - const toName = identities[toAddress] - ? identities[toAddress].name - : ( - casedContractMap[toAddress] - ? casedContractMap[toAddress].name - : shortenAddress(checksumAddress(toAddress)) - ) + + const toName = identities[toAddress]?.name || + casedContractMap[toAddress]?.name || + shortenAddress(checksumAddress(toAddress)) const checksummedAddress = checksumAddress(toAddress) const addressBookObject = addressBook[checksummedAddress] 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 11daa6cc6..dd6970d87 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,11 +1,11 @@ import { connect } from 'react-redux' -import ConfirmTransactionSwitch from './confirm-transaction-switch.component' import { unconfirmedTransactionsListSelector } from '../../selectors' +import ConfirmTransactionSwitch from './confirm-transaction-switch.component' const mapStateToProps = (state, ownProps) => { const { metamask: { unapprovedTxs } } = state const { match: { params = {}, url } } = ownProps - const urlId = url && url.match(/\d+/) && url.match(/\d+/)[0] + const urlId = url && url.match(/\d+/u) && url.match(/\d+/u)[0] const { id: paramsId } = params const transactionId = paramsId || urlId diff --git a/ui/app/pages/confirm-transaction/conf-tx.js b/ui/app/pages/confirm-transaction/conf-tx.js index 40df45a8f..f9dbde2a5 100644 --- a/ui/app/pages/confirm-transaction/conf-tx.js +++ b/ui/app/pages/confirm-transaction/conf-tx.js @@ -3,9 +3,9 @@ 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 log from 'loglevel' import SignatureRequest from '../../components/app/signature-request' import SignatureRequestOriginal from '../../components/app/signature-request-original' import Loading from '../../components/ui/loading-screen' @@ -105,7 +105,7 @@ class ConfirmTxScreen extends Component { log.info(`rendering a combined ${unconfTxList.length} unconf msgs & txs`) return transactionId - ? unconfTxList.find(({ id }) => id + '' === transactionId) + ? unconfTxList.find(({ id }) => `${id}` === transactionId) : unconfTxList[index] } @@ -195,7 +195,7 @@ class ConfirmTxScreen extends Component { 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) diff --git a/ui/app/pages/confirm-transaction/confirm-transaction.component.js b/ui/app/pages/confirm-transaction/confirm-transaction.component.js index 47f2b27d9..087b8e8b4 100644 --- a/ui/app/pages/confirm-transaction/confirm-transaction.component.js +++ b/ui/app/pages/confirm-transaction/confirm-transaction.component.js @@ -9,7 +9,6 @@ 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 ConfTx from './conf-tx' import ConfirmDecryptMessage from '../confirm-decrypt-message' import ConfirmEncryptionPublicKey from '../confirm-encryption-public-key' @@ -25,6 +24,7 @@ import { DECRYPT_MESSAGE_REQUEST_PATH, ENCRYPTION_PUBLIC_KEY_REQUEST_PATH, } from '../../helpers/constants/routes' +import ConfTx from './conf-tx' export default class ConfirmTransaction extends Component { static contextTypes = { @@ -95,13 +95,10 @@ export default class ConfirmTransaction extends Component { clearConfirmTransaction() getContractMethodData(data) setTransactionToConfirm(paramsTransactionId) - return } else if (prevProps.transactionId && !transactionId && !totalUnapprovedCount) { history.replace(mostRecentOverviewPage) - return } else if (prevProps.transactionId && transactionId && prevProps.transactionId !== transactionId) { history.replace(mostRecentOverviewPage) - return } } diff --git a/ui/app/pages/confirm-transaction/confirm-transaction.container.js b/ui/app/pages/confirm-transaction/confirm-transaction.container.js index b0bfccfb8..6ee2579ff 100644 --- a/ui/app/pages/confirm-transaction/confirm-transaction.container.js +++ b/ui/app/pages/confirm-transaction/confirm-transaction.container.js @@ -16,9 +16,9 @@ import { getContractMethodData, getTokenParams, } from '../../store/actions' -import ConfirmTransaction from './confirm-transaction.component' import { unconfirmedTransactionsListSelector } from '../../selectors' import { getMostRecentOverviewPage } from '../../ducks/history/history' +import ConfirmTransaction from './confirm-transaction.component' const mapStateToProps = (state, ownProps) => { const { diff --git a/ui/app/pages/connected-accounts/connected-accounts.container.js b/ui/app/pages/connected-accounts/connected-accounts.container.js index 1bb5ba84a..0fe24583a 100644 --- a/ui/app/pages/connected-accounts/connected-accounts.container.js +++ b/ui/app/pages/connected-accounts/connected-accounts.container.js @@ -1,5 +1,4 @@ import { connect } from 'react-redux' -import ConnectedAccounts from './connected-accounts.component' import { getAccountToConnectToActiveTab, getOrderedConnectedAccountsForActiveTab, @@ -9,6 +8,7 @@ import { 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' const mapStateToProps = (state) => { const { activeTab } = state diff --git a/ui/app/pages/connected-sites/connected-sites.container.js b/ui/app/pages/connected-sites/connected-sites.container.js index 4526eeec7..f34558741 100644 --- a/ui/app/pages/connected-sites/connected-sites.container.js +++ b/ui/app/pages/connected-sites/connected-sites.container.js @@ -1,5 +1,4 @@ import { connect } from 'react-redux' -import ConnectedSites from './connected-sites.component' import { getOpenMetamaskTabsIds, requestAccountsPermissionWithId, @@ -17,6 +16,7 @@ import { } 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 @@ -76,6 +76,7 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => { const { disconnectAccount, disconnectAllAccounts, + // eslint-disable-next-line no-shadow requestAccountsPermissionWithId, } = dispatchProps const { history } = ownProps 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 933a26b5d..f1f54ddbc 100644 --- a/ui/app/pages/create-account/connect-hardware/account-list.js +++ b/ui/app/pages/create-account/connect-hardware/account-list.js @@ -1,7 +1,7 @@ import PropTypes from 'prop-types' import React, { Component } from 'react' import Select from 'react-select' -import genAccountLink from '../../../../lib/account-link.js' +import getAccountLink from '../../../../lib/account-link' import Button from '../../../components/ui/button' class AccountList extends Component { @@ -101,7 +101,7 @@ class AccountList extends Component {
{ + for (const device of ['trezor', 'ledger']) { 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]) } - }) + } } connectToHardwareWallet = (device) => { if (this.state.accounts.length) { - return null + return } // Default values @@ -99,7 +98,6 @@ class ConnectHardwareForm extends Component { newState.selectedAccount = null } - // Map accounts with balances newState.accounts = accounts.map((account) => { const normalizedAddress = account.address.toLowerCase() @@ -148,7 +146,7 @@ class ConnectHardwareForm extends Component { eventOpts: { category: 'Accounts', action: 'Connected Hardware Wallet', - name: 'Connected Account with: ' + device, + name: `Connected Account with: ${device}`, }, }) history.push(mostRecentOverviewPage) diff --git a/ui/app/css/itcss/components/new-account.scss b/ui/app/pages/create-account/connect-hardware/index.scss similarity index 58% rename from ui/app/css/itcss/components/new-account.scss rename to ui/app/pages/create-account/connect-hardware/index.scss index 77fd07afa..887fd7ec9 100644 --- a/ui/app/css/itcss/components/new-account.scss +++ b/ui/app/pages/create-account/connect-hardware/index.scss @@ -1,170 +1,3 @@ -.new-account { - width: 375px; - background-color: #fff; - box-shadow: 0 0 7px 0 rgba(0, 0, 0, 0.08); - z-index: 25; - height: unset; - overflow: auto; - scrollbar-width: none; - - &::-webkit-scrollbar { - display: none; - } - - @media screen and (min-width: 576px) { - position: absolute; - } - - &__header { - display: flex; - flex-flow: column; - border-bottom: 1px solid $geyser; - } - - &__title { - color: $tundora; - font-family: Roboto; - font-size: 32px; - font-weight: 500; - line-height: 43px; - margin-top: 22px; - margin-left: 29px; - } - - &__tabs { - margin-left: 22px; - display: flex; - margin-top: 10px; - - &__tab { - height: 54px; - padding: 15px 10px; - color: $dusty-gray; - font-family: Roboto; - font-size: 18px; - line-height: 24px; - text-align: center; - cursor: pointer; - } - - &__tab:hover { - color: $black; - border-bottom: none; - } - - &__selected { - color: $primary-blue; - border-bottom: 3px solid $primary-blue; - cursor: initial; - pointer-events: none; - } - } -} - -.new-account-import-disclaimer { - width: 120%; - background-color: #f4f9fc; - display: inline-block; - align-items: center; - padding: 20px 30px 20px; - font-size: 12px; - line-height: 1.5; -} - -.new-account-import-form { - display: flex; - flex-flow: column; - align-items: center; - padding: 0 30px 30px; - - &__select-section { - display: flex; - justify-content: space-between; - align-items: center; - margin-top: 29px; - width: 100%; - } - - &__select-label { - color: $scorpion; - font-family: Roboto; - font-size: 16px; - line-height: 21px; - } - - &__select { - height: 54px; - width: 210px; - border: 1px solid #d2d8dd; - border-radius: 4px; - background-color: #fff; - display: flex; - align-items: center; - - .Select-control, - .Select-control:hover { - height: 100%; - border: none; - box-shadow: none; - - .Select-value { - display: flex; - align-items: center; - } - } - } - - &__private-key-password-container { - display: flex; - flex-flow: column; - align-items: center; - width: 100%; - } - - &__instruction { - color: $scorpion; - font-family: Roboto; - font-size: 16px; - line-height: 21px; - align-self: flex-start; - } - - &__private-key { - display: flex; - flex-flow: column; - align-items: flex-start; - margin-top: 34px; - } - - &__input-password { - height: 54px; - width: 315px; - border: 1px solid $geyser; - border-radius: 4px; - background-color: $white; - margin-top: 16px; - color: $scorpion; - font-family: Roboto; - font-size: 16px; - padding: 0 20px; - } - - &__json { - display: flex; - flex-flow: column; - align-items: center; - margin-top: 29px; - width: 100%; - } - - &__buttons { - margin-top: 39px; - display: flex; - width: 100%; - justify-content: space-between; - } -} - .hw-tutorial { width: 375px; border-top: 1px solid #d2d8dd; @@ -364,7 +197,6 @@ margin-bottom: 23px; align-self: flex-start; color: $scorpion; - font-family: Roboto; font-size: 16px; line-height: 21px; font-weight: bold; @@ -376,7 +208,6 @@ margin-bottom: 23px; align-self: flex-end; color: $scorpion; - font-family: Roboto; font-size: 16px; line-height: 21px; font-weight: normal; @@ -461,7 +292,6 @@ margin-left: 16px; padding: 0; text-transform: uppercase; - font-family: Roboto; } } @@ -511,44 +341,3 @@ cursor: pointer; } } - -.new-account-create-form { - display: flex; - flex-flow: column; - align-items: center; - padding: 30px; - - &__input-label { - color: $scorpion; - font-family: Roboto; - font-size: 16px; - line-height: 21px; - align-self: flex-start; - } - - &__input { - height: 54px; - width: 315.84px; - border: 1px solid $geyser; - border-radius: 4px; - background-color: $white; - color: $scorpion; - font-family: Roboto; - font-size: 16px; - line-height: 21px; - margin-top: 15px; - padding: 0 20px; - } - - &__buttons { - margin-top: 39px; - display: flex; - width: 100%; - justify-content: space-between; - } - - &__button { - width: 150px; - min-width: initial; - } -} 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 5c16bd452..02c26c95e 100644 --- a/ui/app/pages/create-account/connect-hardware/select-hardware.js +++ b/ui/app/pages/create-account/connect-hardware/select-hardware.js @@ -133,7 +133,6 @@ export default class SelectHardware extends Component { ) } - scrollToTutorial = () => { if (this.referenceNode) { this.referenceNode.scrollIntoView({ behavior: 'smooth' }) diff --git a/ui/app/pages/create-account/create-account.component.js b/ui/app/pages/create-account/create-account.component.js index 2389650e7..2ff859144 100644 --- a/ui/app/pages/create-account/create-account.component.js +++ b/ui/app/pages/create-account/create-account.component.js @@ -2,14 +2,14 @@ import React, { Component } from 'react' import { Switch, Route, matchPath } from 'react-router-dom' import PropTypes from 'prop-types' import classnames from 'classnames' -import NewAccountCreateForm from './new-account.container' -import NewAccountImportForm from './import-account' -import ConnectHardwareForm from './connect-hardware' 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' export default class CreateAccountPage extends Component { renderTabs () { diff --git a/ui/app/pages/create-account/import-account/index.js b/ui/app/pages/create-account/import-account/index.js index 13d26f8f0..dee390024 100644 --- a/ui/app/pages/create-account/import-account/index.js +++ b/ui/app/pages/create-account/import-account/index.js @@ -3,9 +3,8 @@ import PropTypes from 'prop-types' import Select from 'react-select' // Subviews -import JsonImportView from './json.js' - -import PrivateKeyImportView from './private-key.js' +import JsonImportView from './json' +import PrivateKeyImportView from './private-key' export default class AccountImportSubview extends Component { static contextTypes = { @@ -67,10 +66,10 @@ export default class AccountImportSubview extends Component { name="import-type-select" clearable={false} value={type || menuItems[0]} - options={menuItems.map((type) => { + options={menuItems.map((text) => { return { - value: type, - label: type, + value: text, + label: text, } })} onChange={(opt) => { diff --git a/ui/app/pages/create-account/import-account/index.scss b/ui/app/pages/create-account/import-account/index.scss new file mode 100644 index 000000000..8ad30cc13 --- /dev/null +++ b/ui/app/pages/create-account/import-account/index.scss @@ -0,0 +1,100 @@ +.new-account-import-disclaimer { + width: 120%; + background-color: #f4f9fc; + display: inline-block; + align-items: center; + padding: 20px 30px 20px; + font-size: 12px; + line-height: 1.5; +} + +.new-account-import-form { + display: flex; + flex-flow: column; + align-items: center; + padding: 0 30px 30px; + + &__select-section { + display: flex; + justify-content: space-between; + align-items: center; + margin-top: 29px; + width: 100%; + } + + &__select-label { + color: $scorpion; + font-size: 16px; + line-height: 21px; + } + + &__select { + height: 54px; + width: 210px; + border: 1px solid #d2d8dd; + border-radius: 4px; + background-color: #fff; + display: flex; + align-items: center; + + .Select-control, + .Select-control:hover { + height: 100%; + border: none; + box-shadow: none; + + .Select-value { + display: flex; + align-items: center; + } + } + } + + &__private-key-password-container { + display: flex; + flex-flow: column; + align-items: center; + width: 100%; + } + + &__instruction { + color: $scorpion; + font-size: 16px; + line-height: 21px; + align-self: flex-start; + } + + &__private-key { + display: flex; + flex-flow: column; + align-items: flex-start; + margin-top: 34px; + } + + &__input-password { + height: 54px; + width: 315px; + border: 1px solid $geyser; + border-radius: 4px; + background-color: $white; + margin-top: 16px; + color: $scorpion; + font-size: 16px; + padding: 0 20px; + } + + &__json { + display: flex; + flex-flow: column; + align-items: center; + margin-top: 29px; + width: 100%; + } + + &__buttons { + margin-top: 39px; + display: flex; + width: 100%; + justify-content: space-between; + } +} diff --git a/ui/app/pages/create-account/import-account/json.js b/ui/app/pages/create-account/import-account/json.js index 304e52c50..1edaed355 100644 --- a/ui/app/pages/create-account/import-account/json.js +++ b/ui/app/pages/create-account/import-account/json.js @@ -3,8 +3,8 @@ import PropTypes from 'prop-types' import { withRouter } from 'react-router-dom' import { compose } from 'redux' import { connect } from 'react-redux' -import * as actions from '../../../store/actions' 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' @@ -101,12 +101,13 @@ class JsonImportSubview extends Component { if (!fileContents) { const message = this.context.t('needImportFile') - return displayWarning(message) + displayWarning(message) + return } const password = this.inputRef.current.value - importNewJsonAccount([ fileContents, password ]) + importNewJsonAccount([fileContents, password]) .then(({ selectedAddress }) => { if (selectedAddress) { history.push(mostRecentOverviewPage) 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 f23e7f418..cbc155f81 100644 --- a/ui/app/pages/create-account/import-account/private-key.js +++ b/ui/app/pages/create-account/import-account/private-key.js @@ -32,7 +32,7 @@ class PrivateKeyImportView extends Component { const privateKey = this.inputRef.current.value const { importNewAccount, history, displayWarning, mostRecentOverviewPage, setSelectedAddress, firstAddress } = this.props - importNewAccount('Private Key', [ privateKey ]) + importNewAccount('Private Key', [privateKey]) .then(({ selectedAddress }) => { if (selectedAddress) { this.context.metricsEvent({ @@ -131,7 +131,6 @@ export default compose( connect(mapStateToProps, mapDispatchToProps), )(PrivateKeyImportView) - function mapStateToProps (state) { return { error: state.appState.warning, @@ -142,8 +141,8 @@ function mapStateToProps (state) { function mapDispatchToProps (dispatch) { return { - importNewAccount: (strategy, [ privateKey ]) => { - return dispatch(actions.importNewAccount(strategy, [ privateKey ])) + 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.scss b/ui/app/pages/create-account/index.scss new file mode 100644 index 000000000..d6b1717e0 --- /dev/null +++ b/ui/app/pages/create-account/index.scss @@ -0,0 +1,103 @@ +@import 'connect-hardware/index'; +@import 'import-account/index'; + +.new-account { + width: 375px; + background-color: #fff; + box-shadow: 0 0 7px 0 rgba(0, 0, 0, 0.08); + z-index: 25; + height: unset; + overflow: auto; + scrollbar-width: none; + + &::-webkit-scrollbar { + display: none; + } + + @media screen and (min-width: 576px) { + position: absolute; + } + + &__header { + display: flex; + flex-flow: column; + border-bottom: 1px solid $geyser; + } + + &__title { + color: $tundora; + font-size: 32px; + font-weight: 500; + line-height: 43px; + margin-top: 22px; + margin-left: 29px; + } + + &__tabs { + margin-left: 22px; + display: flex; + margin-top: 10px; + + &__tab { + height: 54px; + padding: 15px 10px; + color: $dusty-gray; + font-size: 18px; + line-height: 24px; + text-align: center; + cursor: pointer; + } + + &__tab:hover { + color: $black; + border-bottom: none; + } + + &__selected { + color: $primary-blue; + border-bottom: 3px solid $primary-blue; + cursor: initial; + pointer-events: none; + } + } +} + + +.new-account-create-form { + display: flex; + flex-flow: column; + align-items: center; + padding: 30px; + + &__input-label { + color: $scorpion; + font-size: 16px; + line-height: 21px; + align-self: flex-start; + } + + &__input { + height: 54px; + width: 315.84px; + border: 1px solid $geyser; + border-radius: 4px; + background-color: $white; + color: $scorpion; + font-size: 16px; + line-height: 21px; + margin-top: 15px; + padding: 0 20px; + } + + &__buttons { + margin-top: 39px; + display: flex; + width: 100%; + justify-content: space-between; + } + + &__button { + width: 150px; + min-width: initial; + } +} diff --git a/ui/app/pages/create-account/new-account.container.js b/ui/app/pages/create-account/new-account.container.js index 14c33c2f4..d1680b4b3 100644 --- a/ui/app/pages/create-account/new-account.container.js +++ b/ui/app/pages/create-account/new-account.container.js @@ -1,7 +1,7 @@ import { connect } from 'react-redux' import * as actions from '../../store/actions' -import NewAccountCreateForm from './new-account.component' import { getMostRecentOverviewPage } from '../../ducks/history/history' +import NewAccountCreateForm from './new-account.component' const mapStateToProps = (state) => { const { metamask: { network, selectedAddress, identities = {} } } = state 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 b680057f1..f41aa2796 100644 --- a/ui/app/pages/create-account/tests/create-account.test.js +++ b/ui/app/pages/create-account/tests/create-account.test.js @@ -1,8 +1,8 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import sinon from 'sinon' import { mountWithRouter } from '../../../../../test/lib/render-helpers' -import CreateAccountPage from '../index' +import CreateAccountPage from '..' describe('Create Account Page', function () { let wrapper diff --git a/ui/app/pages/error/index.scss b/ui/app/pages/error/index.scss index cf0c2aeb4..14ec9da84 100644 --- a/ui/app/pages/error/index.scss +++ b/ui/app/pages/error/index.scss @@ -2,7 +2,6 @@ display: flex; flex-flow: column nowrap; align-items: center; - font-family: Roboto; font-style: normal; font-weight: normal; padding: 35px 10px 10px 10px; 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 5a746d89e..a159601da 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 NewAccount from './new-account' import MetaFoxLogo from '../../../components/ui/metafox-logo' -import ImportWithSeedPhrase from './import-with-seed-phrase' 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' export default class CreatePassword extends PureComponent { static propTypes = { 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 018666b13..62d2db4b5 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,10 +1,10 @@ import { connect } from 'react-redux' -import ImportWithSeedPhrase from './import-with-seed-phrase.component' import { setSeedPhraseBackedUp, initializeThreeBox, setCompletedOnboarding, } from '../../../../store/actions' +import ImportWithSeedPhrase from './import-with-seed-phrase.component' const mapDispatchToProps = (dispatch) => { return { 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 2156de687..95177e62a 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,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import { shallow } from 'enzyme' import sinon from 'sinon' import ImportWithSeedPhrase from '../import-with-seed-phrase.component' @@ -7,7 +7,7 @@ import ImportWithSeedPhrase from '../import-with-seed-phrase.component' function shallowRender (props = {}, context = {}) { return shallow(, { context: { - t: (str) => str + '_t', + t: (str) => `${str}_t`, metricsEvent: sinon.spy(), ...context, }, 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 a6510553d..aa2611fc6 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 @@ -56,22 +56,22 @@ export default class EndOfFlowScreen extends PureComponent { { t('endOfFlowMessage2') }
- { '• ' + t('endOfFlowMessage3') } + { `• ${t('endOfFlowMessage3')}` }
- { '• ' + t('endOfFlowMessage4') } + { `• ${t('endOfFlowMessage4')}` }
- { '• ' + t('endOfFlowMessage5') } + { `• ${t('endOfFlowMessage5')}` }
- { '• ' + t('endOfFlowMessage6') } + { `• ${t('endOfFlowMessage6')}` }
- { '• ' + t('endOfFlowMessage7') } + { `• ${t('endOfFlowMessage7')}` }
- { '*' + t('endOfFlowMessage8') }  + { `*${t('endOfFlowMessage8')}` }  { const { metamask: { completedOnboarding, isInitialized, isUnlocked, seedPhraseBackedUp } } = state diff --git a/ui/app/pages/first-time-flow/index.scss b/ui/app/pages/first-time-flow/index.scss index 3b7498b2b..19e769e10 100644 --- a/ui/app/pages/first-time-flow/index.scss +++ b/ui/app/pages/first-time-flow/index.scss @@ -72,7 +72,6 @@ /*rtl:ignore*/ direction: ltr; font-size: 1rem; - font-family: Roboto; border: 1px solid #cdcdcd; border-radius: 6px; background-color: #fff; @@ -149,7 +148,6 @@ } &__checkbox-label { - font-family: Roboto; font-style: normal; font-weight: normal; line-height: normal; diff --git a/ui/app/pages/first-time-flow/metametrics-opt-in/index.scss b/ui/app/pages/first-time-flow/metametrics-opt-in/index.scss index a5cb6e1da..18df92891 100644 --- a/ui/app/pages/first-time-flow/metametrics-opt-in/index.scss +++ b/ui/app/pages/first-time-flow/metametrics-opt-in/index.scss @@ -27,7 +27,6 @@ &__title { position: relative; margin-top: 20px; - font-family: Roboto; font-style: normal; font-weight: normal; line-height: normal; @@ -43,7 +42,6 @@ } &__description { - font-family: Roboto; font-style: normal; font-weight: normal; line-height: 21px; 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 e5d622ef2..a0b8fbcce 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 @@ -88,7 +88,7 @@ export default class MetaMetricsOptIn extends Component { onCancel={() => { setParticipateInMetaMetrics(false) .then(() => { - const promise = participateInMetaMetrics !== false + const promise = participateInMetaMetrics === true ? metricsEvent({ eventOpts: { category: 'Onboarding', @@ -110,7 +110,7 @@ export default class MetaMetricsOptIn extends Component { onSubmit={() => { setParticipateInMetaMetrics(true) .then(([_, metaMetricsId]) => { - const promise = participateInMetaMetrics !== true + const promise = participateInMetaMetrics === false ? metricsEvent({ eventOpts: { category: 'Onboarding', @@ -150,7 +150,7 @@ export default class MetaMetricsOptIn extends Component { target="_blank" rel="noopener noreferrer" >{ t('gdprMessagePrivacyPolicy') } - ]) + ]) }
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 7c54fd980..aeb323915 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,7 +1,7 @@ import { connect } from 'react-redux' -import MetaMetricsOptIn from './metametrics-opt-in.component' import { setParticipateInMetaMetrics } from '../../../store/actions' import { getFirstTimeFlowTypeRoute } from '../../../selectors' +import MetaMetricsOptIn from './metametrics-opt-in.component' const firstTimeFlowTypeNameMap = { create: 'Selected Create New Wallet', 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 c3b7f04fe..2f7ade5e5 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 React from 'react' 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 '../index' +import MetaMetricsOptIn from '..' describe('MetaMetricsOptIn', function () { it('opt out of MetaMetrics', function () { 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 7653f7852..18d8ba5da 100644 --- a/ui/app/pages/first-time-flow/onboarding-initiator-util.js +++ b/ui/app/pages/first-time-flow/onboarding-initiator-util.js @@ -3,6 +3,7 @@ import log from 'loglevel' const returnToOnboardingInitiatorTab = async (onboardingInitiator) => { const tab = await (new Promise((resolve) => { + // eslint-disable-next-line no-shadow extension.tabs.update(onboardingInitiator.tabId, { active: true }, (tab) => { if (tab) { resolve(tab) @@ -16,17 +17,18 @@ const returnToOnboardingInitiatorTab = async (onboardingInitiator) => { }) })) - if (!tab) { + if (tab) { + 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) - } else { - window.close() } } 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) 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 8847a0d01..318e4fcb5 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 @@ -173,10 +173,10 @@ export default class ConfirmSeedPhrase extends PureComponent { className="confirm-seed-phrase__seed-word--sorted" selected={isSelected} onClick={() => { - if (!isSelected) { - this.handleSelectSeedWord(index) - } else { + if (isSelected) { this.handleDeselectSeedWord(index) + } else { + this.handleSelectSeedWord(index) } }} word={word} @@ -247,7 +247,7 @@ export default class ConfirmSeedPhrase extends PureComponent { setDraggingSeedIndex={this.setDraggingSeedIndex} setHoveringIndex={this.setHoveringIndex} onDrop={this.onDrop} - droppable={!!word} + droppable={Boolean(word)} /> ) }) 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 176601e49..8fece3bba 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,10 +1,10 @@ import { connect } from 'react-redux' -import ConfirmSeedPhrase from './confirm-seed-phrase.component' import { setSeedPhraseBackedUp, initializeThreeBox, setCompletedOnboarding, } from '../../../../store/actions' +import ConfirmSeedPhrase from './confirm-seed-phrase.component' const mapDispatchToProps = (dispatch) => { return { 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 9eea945a5..66f227318 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 @@ -121,5 +121,3 @@ const collectDrop = (connect, monitor) => { } export default DropTarget(SEEDWORD, seedTarget, collectDrop)(DragSource(SEEDWORD, seedSource, collectDrag)(DraggableSeed)) - - 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 afcd771c4..0130e3a34 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 @@ -82,7 +82,8 @@ export default class RevealSeedPhrase extends PureComponent { className={classnames( 'reveal-seed-phrase__secret-words notranslate', { 'reveal-seed-phrase__secret-words--hidden': !isShowingSeedPhrase, - })} + }, + )} > { seedPhrase }
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 c1bf9109c..64289adc0 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,10 +1,10 @@ import { connect } from 'react-redux' -import RevealSeedPhrase from './reveal-seed-phrase.component' import { setCompletedOnboarding, setSeedPhraseBackedUp, } from '../../../../store/actions' import { getOnboardingInitiator } from '../../../../selectors' +import RevealSeedPhrase from './reveal-seed-phrase.component' const mapStateToProps = (state) => { return { 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 a9ac7b66c..152e24935 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,8 +1,8 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import sinon from 'sinon' import { mount } from 'enzyme' -import RevealSeedPhrase from '../index' +import RevealSeedPhrase from '..' describe('Reveal Seed Phrase', function () { let wrapper @@ -23,7 +23,7 @@ describe('Reveal Seed Phrase', function () { , { context: { t: (str) => str, - metricsEvent: () => {}, + metricsEvent: () => undefined, }, }, ) 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 67eccb34c..6e6201a03 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,17 +1,17 @@ import React, { PureComponent } from 'react' import PropTypes from 'prop-types' import { Switch, Route } from 'react-router-dom' -import RevealSeedPhrase from './reveal-seed-phrase' -import ConfirmSeedPhrase from './confirm-seed-phrase' +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 HTML5Backend from 'react-dnd-html5-backend' -import { DragDropContextProvider } from 'react-dnd' 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 = { @@ -30,10 +30,10 @@ export default class SeedPhrase extends PureComponent { if (!seedPhrase) { verifySeedPhrase() .then((verifiedSeedPhrase) => { - if (!verifiedSeedPhrase) { - history.push(DEFAULT_ROUTE) - } else { + if (verifiedSeedPhrase) { this.setState({ verifiedSeedPhrase }) + } else { + history.push(DEFAULT_ROUTE) } }) } 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 a5846a944..200d2867f 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,5 +1,5 @@ -import React from 'react' 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' @@ -9,7 +9,7 @@ function shallowRender (props = {}, context = {}) { , { context: { - t: (str) => str + '_t', + t: (str) => `${str}_t`, ...context, }, }, @@ -152,7 +152,6 @@ describe('ConfirmSeedPhrase Component', function () { 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') diff --git a/ui/app/pages/first-time-flow/select-action/index.scss b/ui/app/pages/first-time-flow/select-action/index.scss index 34a72a10c..1b398a73e 100644 --- a/ui/app/pages/first-time-flow/select-action/index.scss +++ b/ui/app/pages/first-time-flow/select-action/index.scss @@ -11,7 +11,6 @@ } &__body-header { - font-family: Roboto; font-style: normal; font-weight: normal; line-height: 39px; @@ -59,7 +58,6 @@ } &__button-text-big { - font-family: Roboto; font-style: normal; font-weight: normal; line-height: 28px; @@ -70,7 +68,6 @@ } &__button-text-small { - font-family: Roboto; font-style: normal; font-weight: normal; line-height: 20px; 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 5379952f1..f66eda3a5 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 @@ -45,7 +45,6 @@ export default class SelectAction extends PureComponent {
-
{ t('newToMetaMask') } 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 2293cd6a5..baeda007b 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,8 +1,8 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import sinon from 'sinon' import { mountWithRouter } from '../../../../../../test/lib/render-helpers' -import SelectAction from '../index' +import SelectAction from '..' describe('Selection Action', function () { let wrapper 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 510334dca..c3a584f0c 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,9 +1,9 @@ -import React from 'react' 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 '../index' +import Welcome from '..' describe('Welcome', function () { const mockStore = { diff --git a/ui/app/pages/home/home.component.js b/ui/app/pages/home/home.component.js index 880e438e0..92af97d3b 100644 --- a/ui/app/pages/home/home.component.js +++ b/ui/app/pages/home/home.component.js @@ -158,7 +158,7 @@ export default class Home extends PureComponent { threeBoxLastUpdated && showRestorePrompt ? ( ) } + renderPopover = () => { const { setConnectedStatusPopoverHasBeenShown } = this.props const { t } = this.context diff --git a/ui/app/pages/home/home.container.js b/ui/app/pages/home/home.container.js index 8a1c0eed7..a42e53911 100644 --- a/ui/app/pages/home/home.container.js +++ b/ui/app/pages/home/home.container.js @@ -1,4 +1,3 @@ -import Home from './home.component' import { compose } from 'redux' import { connect } from 'react-redux' import { withRouter } from 'react-router-dom' @@ -23,6 +22,7 @@ import { ENVIRONMENT_TYPE_NOTIFICATION, ENVIRONMENT_TYPE_POPUP, } from '../../../../app/scripts/lib/enums' +import Home from './home.component' const mapStateToProps = (state) => { const { metamask, appState } = state diff --git a/ui/app/pages/home/index.scss b/ui/app/pages/home/index.scss index 814223bf3..4d4926e86 100644 --- a/ui/app/pages/home/index.scss +++ b/ui/app/pages/home/index.scss @@ -43,10 +43,11 @@ display: flex; flex-direction: column; - @extend %content-text; + @include H6; padding-left: 24px; padding-right: 24px; + color: $Grey-800; div { margin-bottom: 20px; diff --git a/ui/app/pages/index.js b/ui/app/pages/index.js index 5ec61b4d2..16e63204c 100644 --- a/ui/app/pages/index.js +++ b/ui/app/pages/index.js @@ -3,10 +3,10 @@ import PropTypes from 'prop-types' import { Provider } from 'react-redux' import { HashRouter } from 'react-router-dom' import * as Sentry from '@sentry/browser' -import ErrorPage from './error' -import Routes from './routes' import { I18nProvider, LegacyI18nProvider } from '../contexts/i18n' import { MetaMetricsProvider, LegacyMetaMetricsProvider } from '../contexts/metametrics' +import ErrorPage from './error' +import Routes from './routes' class Index extends PureComponent { state = {} diff --git a/ui/app/pages/keychains/index.scss b/ui/app/pages/keychains/index.scss index a70255d0d..54b52981f 100644 --- a/ui/app/pages/keychains/index.scss +++ b/ui/app/pages/keychains/index.scss @@ -95,7 +95,6 @@ .import-account__faq-link { font-size: 18px; line-height: 23px; - font-family: Roboto; } .import-account__selector-label { @@ -110,7 +109,6 @@ background-color: #fff; margin-top: 14px; color: #5b5d67; - font-family: Roboto; font-size: 18px; line-height: 23px; padding: 14px 21px; @@ -125,7 +123,6 @@ font-size: 18px; line-height: 23px; margin-top: 21px; - font-family: Roboto; } .import-account__input-wrapper { @@ -173,7 +170,6 @@ border: 1px solid #1b344d; border-radius: 4px; color: #1b344d; - font-family: Roboto; font-size: 18px; display: flex; flex-flow: column nowrap; @@ -190,7 +186,6 @@ .import-account__file-name { color: #000; - font-family: Roboto; font-size: 18px; line-height: 23px; margin-left: 22px; diff --git a/ui/app/pages/keychains/restore-vault.js b/ui/app/pages/keychains/restore-vault.js index 7a83a50e1..dc4ef5fd0 100644 --- a/ui/app/pages/keychains/restore-vault.js +++ b/ui/app/pages/keychains/restore-vault.js @@ -76,9 +76,11 @@ class RestoreVaultPage extends Component { onClick = () => { const { password, seedPhrase } = this.state const { + // eslint-disable-next-line no-shadow createNewVaultAndRestore, leaveImportSeedScreenState, history, + // eslint-disable-next-line no-shadow initializeThreeBox, } = this.props diff --git a/ui/app/pages/keychains/tests/reveal-seed.test.js b/ui/app/pages/keychains/tests/reveal-seed.test.js index 7a5325aca..ee89b58c6 100644 --- a/ui/app/pages/keychains/tests/reveal-seed.test.js +++ b/ui/app/pages/keychains/tests/reveal-seed.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import sinon from 'sinon' import { mount } from 'enzyme' import RevealSeedPage from '../reveal-seed' diff --git a/ui/app/pages/lock/lock.container.js b/ui/app/pages/lock/lock.container.js index 382f936c7..e7e12b103 100644 --- a/ui/app/pages/lock/lock.container.js +++ b/ui/app/pages/lock/lock.container.js @@ -1,8 +1,8 @@ -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 diff --git a/ui/app/pages/lock/tests/lock.test.js b/ui/app/pages/lock/tests/lock.test.js index 85eff210a..4f4c870e7 100644 --- a/ui/app/pages/lock/tests/lock.test.js +++ b/ui/app/pages/lock/tests/lock.test.js @@ -1,8 +1,8 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import sinon from 'sinon' import { mountWithRouter } from '../../../../../test/lib/render-helpers' -import Lock from '../index' +import Lock from '..' describe('Lock', function () { diff --git a/ui/app/pages/mobile-sync/mobile-sync.component.js b/ui/app/pages/mobile-sync/mobile-sync.component.js index d93e64c0d..be0d3dbe2 100644 --- a/ui/app/pages/mobile-sync/mobile-sync.component.js +++ b/ui/app/pages/mobile-sync/mobile-sync.component.js @@ -29,7 +29,6 @@ export default class MobileSyncPage extends Component { keyrings: PropTypes.array, } - state = { screen: PASSWORD_PROMPT_SCREEN, password: '', @@ -131,7 +130,7 @@ export default class MobileSyncPage extends Component { const { channel, message } = data // handle message if (channel !== this.channelName || !message) { - return false + return } if (message.event === 'start-sync') { @@ -173,8 +172,10 @@ export default class MobileSyncPage extends Component { chunkString (str, size) { const numChunks = Math.ceil(str.length / size) const chunks = new Array(numChunks) - for (let i = 0, o = 0; i < numChunks; ++i, o += size) { + for (let i = 0, o = 0; i < numChunks;) { chunks[i] = str.substr(o, size) + i += 1 + o += size } return chunks } @@ -192,18 +193,19 @@ export default class MobileSyncPage extends Component { storeInHistory: false, }, (status, response) => { - if (!status.error) { - resolve() - } else { + if (status.error) { reject(response) + } else { + resolve() } - }) + }, + ) }) } async startSyncing () { if (this.syncing) { - return false + return } this.syncing = true this.setState({ syncing: true }) @@ -251,17 +253,16 @@ export default class MobileSyncPage extends Component { storeInHistory: false, }, (status, response) => { - if (!status.error) { - resolve() - } else { + if (status.error) { reject(response) + } else { + resolve() } }, ) }) } - componentWillUnmount () { this.clearTimeouts() this.disconnectWebsockets() @@ -369,7 +370,6 @@ export default class MobileSyncPage extends Component { {t('syncWithMobileScanThisCode')}
{ return { diff --git a/ui/app/pages/index.scss b/ui/app/pages/pages.scss similarity index 59% rename from ui/app/pages/index.scss rename to ui/app/pages/pages.scss index 95bdc7489..f09773ae1 100644 --- a/ui/app/pages/index.scss +++ b/ui/app/pages/pages.scss @@ -1,14 +1,20 @@ -@import 'unlock-page/index'; +/** Please import your files in alphabetical order **/ @import 'add-token/index'; -@import 'error/index'; -@import 'home/index'; -@import 'send/send'; +@import 'asset/asset'; @import 'confirm-add-token/index'; +@import 'confirm-approve/index'; +@import 'confirm-decrypt-message/confirm-decrypt-message'; +@import 'confirm-encryption-public-key/confirm-encryption-public-key'; @import 'connected-sites/index'; @import 'connected-accounts/index'; -@import 'settings/index'; +@import 'connected-sites/index'; +@import 'create-account/index'; +@import 'error/index'; @import 'first-time-flow/index'; +@import 'home/index'; @import 'keychains/index'; -@import 'confirm-approve/index'; @import 'permissions-connect/index'; -@import 'asset/asset'; +@import 'send/send'; +@import 'settings/index'; +@import 'token/index'; +@import 'unlock-page/index'; 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 606b2ecc9..e1c10d0ff 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 @@ -4,7 +4,7 @@ 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-v2' +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' diff --git a/ui/app/pages/permissions-connect/choose-account/index.scss b/ui/app/pages/permissions-connect/choose-account/index.scss index 4f71942c1..bb4b05a42 100644 --- a/ui/app/pages/permissions-connect/choose-account/index.scss +++ b/ui/app/pages/permissions-connect/choose-account/index.scss @@ -24,13 +24,13 @@ &__title { - @extend %header--18; + @include H4; } &__text, &__text-blue, &__text-grey { - @extend %content-text; + @include H6; } &__text-blue { @@ -120,7 +120,7 @@ } &__label { - @extend %content-text; + @include H6; color: $Black-100; text-overflow: ellipsis; @@ -129,17 +129,14 @@ } &__balance { - @extend %content-text; + @include H7; - font-size: 12px; color: $Grey-500; } &__last-connected { - @extend %content-text; + @include H8; - font-size: 10px; - line-height: 140.62%; display: flex; flex-direction: column; align-items: flex-end; diff --git a/ui/app/pages/permissions-connect/index.scss b/ui/app/pages/permissions-connect/index.scss index a5f9f1d2d..eb6b14dbf 100644 --- a/ui/app/pages/permissions-connect/index.scss +++ b/ui/app/pages/permissions-connect/index.scss @@ -24,7 +24,7 @@ } &__back { - @extend %content-text; + @include H6; color: $Grey-600; cursor: pointer; @@ -35,9 +35,8 @@ } &__page-count { - @extend %content-text; + @include H7; - font-size: 12px; color: #6a737d; grid-column: 2; justify-self: end; diff --git a/ui/app/pages/permissions-connect/permissions-connect.component.js b/ui/app/pages/permissions-connect/permissions-connect.component.js index 6bef21f37..2aa1b0a4c 100644 --- a/ui/app/pages/permissions-connect/permissions-connect.component.js +++ b/ui/app/pages/permissions-connect/permissions-connect.component.js @@ -85,7 +85,8 @@ export default class PermissionConnect extends Component { getRequestAccountTabIds() if (!permissionsRequest) { - return history.push(DEFAULT_ROUTE) + history.push(DEFAULT_ROUTE) + return } const environmentType = getEnvironmentType() @@ -161,26 +162,24 @@ export default class PermissionConnect extends Component { const { redirecting } = this.state const { page } = this.props const { t } = this.context - return !redirecting - ? ( -
- { page === '2' + return redirecting + ? null + : ( +
+ {page === '2' ? (
this.goBack()}> - { t('back') } + {t('back')}
) : null }
- { t('xOfY', [ page, '2' ]) } + {t('xOfY', [page, '2'])}
) - : null } render () { @@ -243,8 +242,8 @@ export default class PermissionConnect extends Component { render={() => ( { - approvePermissionsRequest(request, accounts) + approvePermissionsRequest={(...args) => { + approvePermissionsRequest(...args) this.redirect(true) }} rejectPermissionsRequest={(requestId) => this.cancelPermissionsRequest(requestId)} diff --git a/ui/app/pages/permissions-connect/permissions-connect.container.js b/ui/app/pages/permissions-connect/permissions-connect.container.js index 9f0d03068..e65677a4d 100644 --- a/ui/app/pages/permissions-connect/permissions-connect.container.js +++ b/ui/app/pages/permissions-connect/permissions-connect.container.js @@ -1,6 +1,5 @@ import { connect } from 'react-redux' import PropTypes from 'prop-types' -import PermissionApproval from './permissions-connect.component' import { getPermissionsRequests, getNativeCurrency, @@ -22,6 +21,7 @@ import { CONNECT_ROUTE, CONNECT_CONFIRM_PERMISSIONS_ROUTE, } from '../../helpers/constants/routes' +import PermissionApproval from './permissions-connect.component' const mapStateToProps = (state, ownProps) => { const { @@ -32,7 +32,7 @@ const mapStateToProps = (state, ownProps) => { const currentAddress = getSelectedAddress(state) const permissionsRequest = permissionsRequests - .find((permissionsRequest) => permissionsRequest.metadata.id === permissionsRequestId) + .find((req) => req.metadata.id === permissionsRequestId) const { metadata = {} } = permissionsRequest || {} const { origin } = metadata diff --git a/ui/app/pages/permissions-connect/redirect/index.scss b/ui/app/pages/permissions-connect/redirect/index.scss index b2cc68554..fa90ca0c1 100644 --- a/ui/app/pages/permissions-connect/redirect/index.scss +++ b/ui/app/pages/permissions-connect/redirect/index.scss @@ -4,7 +4,7 @@ justify-content: center; &__result { - @extend %header--24; + @include H3; position: absolute; top: 30%; diff --git a/ui/app/pages/routes/routes.component.js b/ui/app/pages/routes/routes.component.js index 578483425..88b8321e9 100644 --- a/ui/app/pages/routes/routes.component.js +++ b/ui/app/pages/routes/routes.component.js @@ -265,16 +265,16 @@ export default class Routes extends Component { } toggleMetamaskActive () { - if (!this.props.isUnlocked) { + if (this.props.isUnlocked) { + // currently active: deactivate + this.props.lockMetaMask() + } else { // currently inactive: redirect to password box const passwordBox = document.querySelector('input[type=password]') if (!passwordBox) { return } passwordBox.focus() - } else { - // currently active: deactivate - this.props.lockMetaMask() } } diff --git a/ui/app/pages/routes/routes.container.js b/ui/app/pages/routes/routes.container.js index d4a638250..9fdfa9067 100644 --- a/ui/app/pages/routes/routes.container.js +++ b/ui/app/pages/routes/routes.container.js @@ -7,7 +7,6 @@ import { getPreferences, submittedPendingTransactionsSelector, } from '../../selectors' -import Routes from './routes.component' import { hideSidebar, lockMetamask, @@ -16,6 +15,7 @@ import { setMouseUserState, } from '../../store/actions' import { pageChanged } from '../../ducks/history/history' +import Routes from './routes.component' function mapStateToProps (state) { const { appState } = state diff --git a/ui/app/pages/send/account-list-item/account-list-item.component.js b/ui/app/pages/send/account-list-item/account-list-item.component.js deleted file mode 100644 index 58df336e5..000000000 --- a/ui/app/pages/send/account-list-item/account-list-item.component.js +++ /dev/null @@ -1,101 +0,0 @@ -import React from 'react' -import PropTypes from 'prop-types' -import classnames from 'classnames' -import { checksumAddress } from '../../../helpers/utils/util' -import Identicon from '../../../components/ui/identicon' -import UserPreferencedCurrencyDisplay from '../../../components/app/user-preferenced-currency-display' -import { PRIMARY, SECONDARY } from '../../../helpers/constants/common' -import Tooltip from '../../../components/ui/tooltip-v2' -import AccountMismatchWarning from '../../../components/ui/account-mismatch-warning/account-mismatch-warning.component' -import { useI18nContext } from '../../../hooks/useI18nContext' - -export default function AccountListItem ({ - account, - className, - displayAddress = false, - displayBalance = true, - handleClick, - icon = null, - balanceIsCached, - showFiat = true, -}) { - const t = useI18nContext() - const { name, address, balance } = account || {} - - return ( -
handleClick && handleClick({ name, address, balance })} - > - -
- - -
{ name || address }
- - {icon &&
{ icon }
} - - -
- - {displayAddress && name && ( -
- { checksumAddress(address) } -
- )} - - {displayBalance && ( - -
-
- - { - balanceIsCached - ? * - : null - } -
- {showFiat && ( - - )} -
-
- )} - -
- ) -} - -AccountListItem.propTypes = { - account: PropTypes.object, - className: PropTypes.string, - displayAddress: PropTypes.bool, - displayBalance: PropTypes.bool, - handleClick: PropTypes.func, - icon: PropTypes.node, - balanceIsCached: PropTypes.bool, - showFiat: PropTypes.bool, -} diff --git a/ui/app/pages/send/account-list-item/account-list-item.container.js b/ui/app/pages/send/account-list-item/account-list-item.container.js deleted file mode 100644 index 40888d3ba..000000000 --- a/ui/app/pages/send/account-list-item/account-list-item.container.js +++ /dev/null @@ -1,21 +0,0 @@ -import { connect } from 'react-redux' -import { - getNativeCurrency, - getIsMainnet, - isBalanceCached, - getPreferences, -} from '../../../selectors' -import AccountListItem from './account-list-item.component' - -export default connect(mapStateToProps)(AccountListItem) - -function mapStateToProps (state) { - const { showFiatInTestnets } = getPreferences(state) - const isMainnet = getIsMainnet(state) - - return { - nativeCurrency: getNativeCurrency(state), - balanceIsCached: isBalanceCached(state), - showFiat: (isMainnet || !!showFiatInTestnets), - } -} diff --git a/ui/app/pages/send/account-list-item/index.js b/ui/app/pages/send/account-list-item/index.js deleted file mode 100644 index 907485cf7..000000000 --- a/ui/app/pages/send/account-list-item/index.js +++ /dev/null @@ -1 +0,0 @@ -export { default } from './account-list-item.container' diff --git a/ui/app/pages/send/account-list-item/tests/account-list-item-container.test.js b/ui/app/pages/send/account-list-item/tests/account-list-item-container.test.js deleted file mode 100644 index 611830d78..000000000 --- a/ui/app/pages/send/account-list-item/tests/account-list-item-container.test.js +++ /dev/null @@ -1,63 +0,0 @@ -import assert from 'assert' -import proxyquire from 'proxyquire' - -let mapStateToProps - -proxyquire('../account-list-item.container.js', { - 'react-redux': { - connect: (ms) => { - mapStateToProps = ms - return () => ({}) - }, - }, - '../../../selectors': { - getConversionRate: () => `mockConversionRate`, - getCurrentCurrency: () => `mockCurrentCurrency`, - getNativeCurrency: () => `mockNativeCurrency`, - isBalanceCached: () => `mockBalanceIsCached`, - getPreferences: ({ showFiatInTestnets }) => ({ - showFiatInTestnets, - }), - getIsMainnet: ({ isMainnet }) => isMainnet, - }, -}) - -describe('account-list-item container', function () { - - describe('mapStateToProps()', function () { - - it('should map the correct properties to props', function () { - assert.deepEqual(mapStateToProps({ isMainnet: true, showFiatInTestnets: false }), { - nativeCurrency: 'mockNativeCurrency', - balanceIsCached: 'mockBalanceIsCached', - showFiat: true, - }) - }) - - it('should map the correct properties to props when in mainnet and showFiatInTestnet is true', function () { - assert.deepEqual(mapStateToProps({ isMainnet: true, showFiatInTestnets: true }), { - nativeCurrency: 'mockNativeCurrency', - balanceIsCached: 'mockBalanceIsCached', - showFiat: true, - }) - }) - - it('should map the correct properties to props when not in mainnet and showFiatInTestnet is true', function () { - assert.deepEqual(mapStateToProps({ isMainnet: false, showFiatInTestnets: true }), { - nativeCurrency: 'mockNativeCurrency', - balanceIsCached: 'mockBalanceIsCached', - showFiat: true, - }) - }) - - it('should map the correct properties to props when not in mainnet and showFiatInTestnet is false', function () { - assert.deepEqual(mapStateToProps({ isMainnet: false, showFiatInTestnets: false }), { - nativeCurrency: 'mockNativeCurrency', - balanceIsCached: 'mockBalanceIsCached', - showFiat: false, - }) - }) - - }) - -}) 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 de4e3a89e..3230e00d8 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 @@ -7,6 +7,7 @@ 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 { @@ -147,13 +148,14 @@ export default class AddRecipient extends Component { return (
-
this.setState({ isShowingTransfer: false })} >
{ t('backToAll') } -
+ { (ownedAccounts && ownedAccounts.length > 1) && !query && ( -
this.setState({ isShowingTransfer: true })} > { t('transferBetweenAccounts') } -
+ ) } @@ -222,7 +225,6 @@ export default class AddRecipient extends Component { ) } - if (toWarning) { return ( ) } + + 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 8ee7716cf..5b8918c79 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 @@ -31,7 +31,7 @@ function mapStateToProps (state) { ensResolution, addressBookEntryName, ensResolutionError: getSendEnsResolutionError(state), - contacts: addressBook.filter(({ name }) => !!name), + contacts: addressBook.filter(({ name }) => Boolean(name)), nonContacts: addressBook.filter(({ name }) => !name), } } 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 a5407ece0..c669e1943 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,3 +1,5 @@ +import ethUtil from 'ethereumjs-util' +import contractMap from 'eth-contract-metadata' import { REQUIRED_ERROR, INVALID_RECIPIENT_ADDRESS_ERROR, @@ -6,8 +8,6 @@ import { } from '../../send.constants' import { isValidAddress, isEthNetwork, checkExistingAddresses } from '../../../../helpers/utils/util' -import ethUtil from 'ethereumjs-util' -import contractMap from 'eth-contract-metadata' export function getToErrorObject (to, hasHexData = false, network) { let toError = null 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 8e9d10425..c3dce42d8 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,15 +1,14 @@ import React, { Component } from 'react' import PropTypes from 'prop-types' import classnames from 'classnames' -import { isValidDomainName, isValidAddress, isValidAddressHead } from '../../../../helpers/utils/util' -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' // Local Constants const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000' @@ -42,7 +41,7 @@ export default class EnsInput extends Component { } componentDidMount () { - const network = this.props.network + const { network } = this.props const networkHasEnsSupport = getNetworkEnsSupport(network) this.setState({ ensResolution: ZERO_ADDRESS }) @@ -78,8 +77,8 @@ export default class EnsInput extends Component { updateEnsResolutionError('') } - lookupEnsName = (recipient) => { - recipient = recipient.trim() + lookupEnsName = (ensName) => { + const recipient = ensName.trim() log.info(`ENS attempting to resolve name: ${recipient}`) this.ens.lookup(recipient) @@ -122,7 +121,7 @@ export default class EnsInput extends Component { if (!networkHasEnsSupport && !isValidAddress(input) && !isValidAddressHead(input)) { updateEnsResolution('') - updateEnsResolutionError(!networkHasEnsSupport ? 'Network does not support ENS' : '') + updateEnsResolutionError(networkHasEnsSupport ? '' : 'Network does not support ENS') return } @@ -188,7 +187,6 @@ export default class EnsInput extends Component { const { className, selectedAddress, selectedName, contact = {} } = this.props const name = contact.name || selectedName - return (
) } + + return null } } 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 48d266db4..479773e9e 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,11 +1,11 @@ import { connect } from 'react-redux' -import EnsInput from './ens-input.component' import { getCurrentNetwork, getSendTo, getSendToNickname, getAddressBookEntry, } from '../../../../selectors' +import EnsInput from './ens-input.component' export default connect( (state) => { 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 b031323be..a25230267 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,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import { shallow } from 'enzyme' import sinon from 'sinon' import AddRecipient from '../add-recipient.component' @@ -37,7 +37,7 @@ describe('AddRecipient Component', function () { nonContacts={[{ address: '0x70F061544cC398520615B5d3e7A3BedD70cd4510', name: 'Fav 7' }]} contacts={[{ address: '0x60F061544cC398520615B5d3e7A3BedD70cd4510', name: 'Fav 6' }]} /> - ), { context: { t: (str) => str + '_t' } }) + ), { context: { t: (str) => `${str}_t` } }) instance = wrapper.instance() }) @@ -94,7 +94,6 @@ describe('AddRecipient Component', function () { const xferLink = wrapper.find('.send__select-recipient-wrapper__list__link') assert.equal(xferLink.length, 1) - const groups = wrapper.find('RecipientGroup') assert.equal(groups.shallow().find('.send__select-recipient-wrapper__group').length, 1) }) 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 a35ba5b9f..628420688 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 @@ -9,7 +9,7 @@ import { } from '../../../send.constants' const stubs = { - isValidAddress: sinon.stub().callsFake((to) => Boolean(to.match(/^[0xabcdef123456798]+$/))), + isValidAddress: sinon.stub().callsFake((to) => Boolean(to.match(/^[0xabcdef123456798]+$/u))), } const toRowUtils = proxyquire('../add-recipient.js', { 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 59fcea367..adab9856e 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 @@ -51,12 +51,12 @@ export default class AmountMaxButton extends Component { name: 'Clicked "Amount Max"', }, }) - if (!maxModeOn) { - setMaxModeTo(true) - this.setMaxAmount() - } else { + if (maxModeOn) { setMaxModeTo(false) clearMaxAmount() + } else { + setMaxModeTo(true) + this.setMaxAmount() } } 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 4060b3eee..1113ad7f9 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 @@ -7,15 +7,15 @@ import { getSendMaxModeState, getBasicGasEstimateLoadingStatus, } from '../../../../../selectors' -import { calcMaxAmount } from './amount-max-button.utils.js' import { updateSendAmount, setMaxModeTo, } from '../../../../../store/actions' -import AmountMaxButton from './amount-max-button.component' 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) 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 606ab6a84..f27207ecb 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,5 +1,5 @@ -import { multiplyCurrencies, subtractCurrencies } from '../../../../../helpers/utils/conversion-util' import ethUtil from 'ethereumjs-util' +import { multiplyCurrencies, subtractCurrencies } from '../../../../../helpers/utils/conversion-util' export function calcMaxAmount ({ balance, gasTotal, sendToken, tokenBalance }) { const { decimals } = sendToken || {} 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 322d21288..cc4546f58 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,8 +1,8 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import { shallow } from 'enzyme' import sinon from 'sinon' -import AmountMaxButton from '../amount-max-button.component.js' +import AmountMaxButton from '../amount-max-button.component' describe('AmountMaxButton Component', function () { let wrapper @@ -13,7 +13,7 @@ describe('AmountMaxButton Component', function () { setMaxModeTo: sinon.spy(), } - const MOCK_EVENT = { preventDefault: () => {} } + const MOCK_EVENT = { preventDefault: () => undefined } before(function () { sinon.spy(AmountMaxButton.prototype, 'setMaxAmount') @@ -32,8 +32,8 @@ describe('AmountMaxButton Component', function () { /> ), { context: { - t: (str) => str + '_t', - metricsEvent: () => {}, + t: (str) => `${str}_t`, + metricsEvent: () => undefined, }, }) instance = wrapper.instance() 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 08fc28b73..caafcfb51 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,7 +1,7 @@ import assert from 'assert' import { calcMaxAmount, -} from '../amount-max-button.utils.js' +} from '../amount-max-button.utils' describe('amount-max-button utils', function () { 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 37b764fbc..c21c38509 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 @@ -2,9 +2,9 @@ import React, { Component } from 'react' import PropTypes from 'prop-types' import { debounce } from 'lodash' import SendRowWrapper from '../send-row-wrapper' -import AmountMaxButton from './amount-max-button' 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 { 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 6264c137c..5b025e985 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,8 +1,8 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import { shallow } from 'enzyme' import sinon from 'sinon' -import SendAmountRow from '../send-amount-row.component.js' +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' @@ -158,9 +158,9 @@ function shallowRenderSendAmountRow () { updateGasFeeError={updateGasFeeError} updateSendAmount={updateSendAmount} updateSendAmountError={updateSendAmountError} - updateGas={() => {}} + updateGas={() => undefined} /> - ), { context: { t: (str) => str + '_t' } }) + ), { context: { t: (str) => `${str}_t` } }) const instance = wrapper.instance() const updateAmount = sinon.spy(instance, 'updateAmount') const updateGas = sinon.spy(instance, 'updateGas') 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 4920156f0..831bf9ac7 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 @@ -124,7 +124,6 @@ export default class SendAssetRow extends Component { ) } - renderAsset (token, insideDropdown = false) { const { address, symbol } = token const { t } = this.context 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 3fdb4803c..dbbf2dddb 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,7 @@ import { connect } from 'react-redux' -import SendAssetRow from './send-asset-row.component' import { getMetaMaskAccounts, getSendTokenAddress } from '../../../../selectors' import { updateSendToken } from '../../../../store/actions' +import SendAssetRow from './send-asset-row.component' function mapStateToProps (state) { return { 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 6ae20f19e..a764849f9 100644 --- a/ui/app/pages/send/send-content/send-content.component.js +++ b/ui/app/pages/send/send-content/send-content.component.js @@ -1,11 +1,11 @@ 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 Dialog from '../../../components/ui/dialog' export default class SendContent extends Component { @@ -48,7 +48,7 @@ export default class SendContent extends Component { const { isOwnedAccount, showAddToAddressBookModal, contact = {} } = this.props if (isOwnedAccount || contact.name) { - return + return null } return ( 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 8ee785736..3bbc36a49 100644 --- a/ui/app/pages/send/send-content/send-content.container.js +++ b/ui/app/pages/send/send-content/send-content.container.js @@ -1,5 +1,4 @@ import { connect } from 'react-redux' -import SendContent from './send-content.component' import { getSendTo, accountsWithSendEtherInfoSelector, @@ -7,12 +6,13 @@ import { } from '../../../selectors' import * as actions from '../../../store/actions' +import SendContent from './send-content.component' function mapStateToProps (state) { const ownedAccounts = accountsWithSendEtherInfoSelector(state) const to = getSendTo(state) return { - isOwnedAccount: !!ownedAccounts.find(({ address }) => address.toLowerCase() === to.toLowerCase()), + isOwnedAccount: Boolean(ownedAccounts.find(({ address }) => address.toLowerCase() === to.toLowerCase())), contact: getAddressBookEntry(state, to), to, } 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 ddbee30bb..601cf0c5f 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 @@ -20,6 +20,7 @@ export default class GasFeeDisplay extends Component { return (
+ {/* eslint-disable-next-line no-nested-ternary */} {gasTotal ? (
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 63a0eba57..d5f6716a7 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,9 +1,9 @@ -import React from 'react' 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 sinon from 'sinon' const propsMethodSpies = { showCustomizeGasModal: sinon.spy(), @@ -24,7 +24,7 @@ describe('GasFeeDisplay Component', function () { showGasButtonGroup={propsMethodSpies.showCustomizeGasModal} onReset={propsMethodSpies.onReset} /> - ), { context: { t: (str) => str + '_t' } }) + ), { context: { t: (str) => `${str}_t` } }) }) afterEach(function () { 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 9388cd2d1..8df7bbbfa 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 GasFeeDisplay from './gas-fee-display/gas-fee-display.component' 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 { @@ -151,9 +151,8 @@ export default class SendGasRow extends Component { return advancedGasInputs } else if (gasButtonGroupShown) { return gasPriceButtonGroup - } else { - return gasFeeDisplay } + return gasFeeDisplay } render () { 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 7510588a4..b215087fe 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 @@ -22,7 +22,7 @@ import { import { isBalanceSufficient, calcGasTotal, -} from '../../send.utils.js' +} from '../../send.utils' import { calcMaxAmount } from '../send-amount-row/amount-max-button/amount-max-button.utils' import { showGasButtonGroup, @@ -36,7 +36,6 @@ import { import { showModal, setGasPrice, setGasLimit, setGasTotal, updateSendAmount } from '../../../../store/actions' import SendGasRow from './send-gas-row.component' - export default connect(mapStateToProps, mapDispatchToProps, mergeProps)(SendGasRow) function mapStateToProps (state) { diff --git a/ui/app/pages/send/send-content/send-gas-row/send-gas-row.scss b/ui/app/pages/send/send-content/send-gas-row/send-gas-row.scss index e69de29bb..b8a23d06b 100644 --- a/ui/app/pages/send/send-content/send-gas-row/send-gas-row.scss +++ b/ui/app/pages/send/send-content/send-gas-row/send-gas-row.scss @@ -0,0 +1,82 @@ +.currency-display { + height: 54px; + border: 1px solid $alto; + border-radius: 4px; + background-color: $white; + color: $scorpion; + font-size: 16px; + padding: 8px 10px; + position: relative; + + &__primary-row { + display: flex; + } + + &__input { + color: $scorpion; + font-size: 16px; + line-height: 22px; + border: none; + max-width: 22ch; + } + + &__primary-currency { + color: $scorpion; + font-weight: 400; + font-size: 16px; + line-height: 22px; + } + + &__converted-row { + display: flex; + } + + &__converted-value, + &__converted-currency { + color: $dusty-gray; + font-size: 12px; + line-height: 12px; + } + + &__input-wrapper { + position: relative; + display: flex; + flex: 1; + max-width: 100%; + + input[type="number"] { + -moz-appearance: textfield; + } + + input[type="number"]::-webkit-inner-spin-button { + -webkit-appearance: none; + -moz-appearance: none; + display: none; + } + + input[type="number"]:hover::-webkit-inner-spin-button { + -webkit-appearance: none; + -moz-appearance: none; + display: none; + } + } + + &__currency-symbol { + margin-top: 1px; + color: $scorpion; + } + + .react-numeric-input { + input[type="number"]::-webkit-inner-spin-button { + -webkit-appearance: none; + -moz-appearance: none; + display: none; + } + + input[type="number"]:hover::-webkit-inner-spin-button { + -webkit-appearance: none; + -moz-appearance: none; + display: none; + } + } +} 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 1664c3211..e078ed25a 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,8 +1,8 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import { shallow } from 'enzyme' import sinon from 'sinon' -import SendGasRow from '../send-gas-row.component.js' +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' @@ -33,7 +33,7 @@ describe('SendGasRow Component', function () { anotherGasPriceButtonGroupProp: 'bar', }} /> - ), { context: { t: (str) => str + '_t', metricsEvent: () => ({}) } }) + ), { context: { t: (str) => `${str}_t`, metricsEvent: () => ({}) } }) wrapper.setProps({ isMainnet: true }) }) 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 eeff87b84..cf774ae0c 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 @@ -15,7 +15,7 @@ export default class SendHexDataRow extends Component { onInput = (event) => { const { updateSendHexData, updateGas } = this.props - const data = event.target.value.replace(/\n/g, '') || null + const data = event.target.value.replace(/\n/ug, '') || null updateSendHexData(data) updateGas({ data }) } 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 47d624598..5e2b261e0 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,7 +1,7 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import { shallow } from 'enzyme' -import SendRowErrorMessage from '../send-row-error-message.component.js' +import SendRowErrorMessage from '../send-row-error-message.component' describe('SendRowErrorMessage Component', function () { let wrapper @@ -13,7 +13,7 @@ describe('SendRowErrorMessage Component', function () { errors={{ error1: 'abc', error2: 'def' }} errorType="error3" /> - ), { context: { t: (str) => str + '_t' } }) + ), { context: { t: (str) => `${str}_t` } }) }) it('should render null if the passed errors do not contain an error of errorType', function () { 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 8c57cf268..5e8773529 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 @@ -20,7 +20,8 @@ describe('send-row-error-message container', function () { it('should map the correct properties to props', function () { assert.deepEqual(mapStateToProps('mockState', { errorType: 'someType' }), { errors: 'mockErrors:mockState', - errorType: 'someType' }) + errorType: 'someType', + }) }) }) 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 6d793c1bd..00f3ceb7f 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,7 +1,7 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import { shallow } from 'enzyme' -import SendRowWrapper from '../send-row-wrapper.component.js' +import SendRowWrapper from '../send-row-wrapper.component' import SendRowErrorMessage from '../send-row-error-message/send-row-error-message.container' 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 01dc83277..dff83a610 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,7 +1,7 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import { shallow } from 'enzyme' -import SendContent from '../send-content.component.js' +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' @@ -18,7 +18,7 @@ describe('SendContent Component', function () { , - { context: { t: (str) => str + '_t' } }, + { context: { t: (str) => `${str}_t` } }, ) }) 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 02379a9e6..6ffda4952 100644 --- a/ui/app/pages/send/send-footer/send-footer.container.js +++ b/ui/app/pages/send/send-footer/send-footer.container.js @@ -26,13 +26,13 @@ import { getRenderableEstimateDataForSmallButtonsFromGWEI, getDefaultActiveButtonIndex, } from '../../../selectors' +import { getMostRecentOverviewPage } from '../../../ducks/history/history' import SendFooter from './send-footer.component' import { addressIsNew, constructTxParams, constructUpdatedTx, } from './send-footer.utils' -import { getMostRecentOverviewPage } from '../../../ducks/history/history' export default connect(mapStateToProps, mapDispatchToProps)(SendFooter) 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 9235f6755..2fec545dc 100644 --- a/ui/app/pages/send/send-footer/send-footer.utils.js +++ b/ui/app/pages/send/send-footer/send-footer.utils.js @@ -55,15 +55,15 @@ export function constructUpdatedTx ({ } if (sendToken) { - const data = TOKEN_TRANSFER_FUNCTION_SIGNATURE + Array.prototype.map.call( - ethAbi.rawEncode(['address', 'uint256'], [to, ethUtil.addHexPrefix(amount)]), - (x) => ('00' + x.toString(16)).slice(-2), - ).join('') - Object.assign(editingTx.txParams, addHexPrefixToObjectValues({ value: '0', to: sendToken.address, - data, + data: ( + TOKEN_TRANSFER_FUNCTION_SIGNATURE + Array.prototype.map.call( + ethAbi.rawEncode(['address', 'uint256'], [to, ethUtil.addHexPrefix(amount)]), + (x) => (`00${x.toString(16)}`).slice(-2), + ).join('') + ), })) } 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 12317cf09..0ddd961ee 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,9 +1,9 @@ -import React from 'react' 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.js' +import SendFooter from '../send-footer.component' import PageContainerFooter from '../../../../components/ui/page-container/page-container-footer' describe('SendFooter Component', function () { @@ -18,7 +18,7 @@ describe('SendFooter Component', function () { const historySpies = { push: sinon.spy(), } - const MOCK_EVENT = { preventDefault: () => {} } + const MOCK_EVENT = { preventDefault: () => undefined } before(function () { sinon.spy(SendFooter.prototype, 'onCancel') @@ -83,7 +83,6 @@ describe('SendFooter Component', function () { }) }) - describe('formShouldBeDisabled()', function () { const config = { 'should return true if inError is truthy': { 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 54040bfd7..314503e0d 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 @@ -97,7 +97,7 @@ describe('send-footer container', function () { ) assert.deepEqual( actionSpies.signTokenTx.getCall(0).args, - [ '0xabc', 'mockTo', 'mockAmount', { value: 'mockAmount' } ], + ['0xabc', 'mockTo', 'mockAmount', { value: 'mockAmount' }], ) }) @@ -125,7 +125,7 @@ describe('send-footer container', function () { ) assert.deepEqual( actionSpies.signTx.getCall(0).args, - [ { value: 'mockAmount' } ], + [{ value: 'mockAmount' }], ) }) }) @@ -168,7 +168,7 @@ describe('send-footer container', function () { assert.equal(utilsStubs.addressIsNew.getCall(0).args[0], 'mockToAccounts') assert.deepEqual( actionSpies.addToAddressBook.getCall(0).args, - [ '0xmockNewAddress', 'mockNickname' ], + ['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 c84856c3c..b0f5f6586 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 @@ -5,7 +5,7 @@ import { TOKEN_TRANSFER_FUNCTION_SIGNATURE } from '../../send.constants' const stubs = { rawEncode: sinon.stub().callsFake((arr1, arr2) => { - return [ ...arr1, ...arr2 ] + return [...arr1, ...arr2] }), } 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 e79d359c7..e89d127d3 100644 --- a/ui/app/pages/send/send-header/send-header.container.js +++ b/ui/app/pages/send/send-header/send-header.container.js @@ -1,8 +1,8 @@ import { connect } from 'react-redux' import { clearSend } from '../../../store/actions' -import SendHeader from './send-header.component' import { getTitleKey } from '../../../selectors' import { getMostRecentOverviewPage } from '../../../ducks/history/history' +import SendHeader from './send-header.component' export default connect(mapStateToProps, mapDispatchToProps)(SendHeader) 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 8e9c75f8f..2844bc879 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,8 +1,8 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import { shallow } from 'enzyme' import sinon from 'sinon' -import SendHeader from '../send-header.component.js' +import SendHeader from '../send-header.component' import PageContainerHeader from '../../../../components/ui/page-container/page-container-header' describe('SendHeader Component', function () { diff --git a/ui/app/pages/send/send.component.js b/ui/app/pages/send/send.component.js index e73aa8bf7..ff6a54e58 100644 --- a/ui/app/pages/send/send.component.js +++ b/ui/app/pages/send/send.component.js @@ -1,12 +1,12 @@ import React, { Component } from 'react' import PropTypes from 'prop-types' +import { debounce } from 'lodash' import { getAmountErrorObject, getGasFeeErrorObject, getToAddressForGasUpdate, doesAmountErrorRequireUpdate, } from './send.utils' -import { debounce } from 'lodash' import { getToWarningObject, getToErrorObject } from './send-content/add-recipient/add-recipient' import SendHeader from './send-header' import AddRecipient from './send-content/add-recipient' @@ -14,7 +14,6 @@ import SendContent from './send-content' import SendFooter from './send-footer' import EnsInput from './send-content/add-recipient/ens-input' - export default class SendTransactionScreen extends Component { static propTypes = { @@ -225,7 +224,8 @@ export default class SendTransactionScreen extends Component { } = this.props if (!query) { - return this.setState({ toError: '', toWarning: '' }) + this.setState({ toError: '', toWarning: '' }) + return } const toErrorObject = getToErrorObject(query, hasHexData, network) diff --git a/ui/app/pages/send/send.constants.js b/ui/app/pages/send/send.constants.js index 7ef707440..c7460fa32 100644 --- a/ui/app/pages/send/send.constants.js +++ b/ui/app/pages/send/send.constants.js @@ -2,9 +2,9 @@ import ethUtil from 'ethereumjs-util' import { conversionUtil, multiplyCurrencies } from '../../helpers/utils/conversion-util' const MIN_GAS_PRICE_DEC = '0' -const MIN_GAS_PRICE_HEX = (parseInt(MIN_GAS_PRICE_DEC)).toString(16) +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)).toString(16) +const MIN_GAS_LIMIT_HEX = (parseInt(MIN_GAS_LIMIT_DEC, 10)).toString(16) const MIN_GAS_PRICE_GWEI = ethUtil.addHexPrefix(conversionUtil(MIN_GAS_PRICE_HEX, { fromDenomination: 'WEI', diff --git a/ui/app/pages/send/send.container.js b/ui/app/pages/send/send.container.js index e4a1c8194..34e876aae 100644 --- a/ui/app/pages/send/send.container.js +++ b/ui/app/pages/send/send.container.js @@ -1,5 +1,4 @@ import { connect } from 'react-redux' -import SendEther from './send.component' import { withRouter } from 'react-router-dom' import { compose } from 'redux' @@ -43,12 +42,13 @@ import { fetchBasicGasEstimates, } from '../../ducks/gas/gas.duck' import { getTokens } from '../../ducks/metamask/metamask' -import { - calcGasTotal, -} from './send.utils.js' import { isValidDomainName, } from '../../helpers/utils/util' +import { + calcGasTotal, +} from './send.utils' +import SendEther from './send.component' function mapStateToProps (state) { const editingTransactionId = getSendEditingTransactionId(state) @@ -90,9 +90,9 @@ function mapDispatchToProps (dispatch) { value, data, }) => { - !editingTransactionId - ? dispatch(updateGasData({ gasPrice, selectedAddress, sendToken, blockGasLimit, to, value, data })) - : dispatch(setGasTotal(calcGasTotal(gasLimit, gasPrice))) + editingTransactionId + ? dispatch(setGasTotal(calcGasTotal(gasLimit, gasPrice))) + : dispatch(updateGasData({ gasPrice, selectedAddress, sendToken, blockGasLimit, to, value, data })) }, updateSendTokenBalance: ({ sendToken, tokenContract, address }) => { dispatch(updateSendTokenBalance({ diff --git a/ui/app/pages/send/send.scss b/ui/app/pages/send/send.scss index e9b8cd265..7e2459f4d 100644 --- a/ui/app/pages/send/send.scss +++ b/ui/app/pages/send/send.scss @@ -1,3 +1,5 @@ +@import './send-content/send-gas-row/send-gas-row'; + .send { &__header { position: relative; @@ -6,18 +8,18 @@ padding: 14px 0 3px 0; .page-container__title { - @extend %h4; + @include H4; text-align: center; } .page-container__header-close-text { - @extend %link; - font-size: 1rem; line-height: 1.1875rem; position: absolute; right: 1rem; + top: 6px; + width: min-content; } } @@ -48,13 +50,13 @@ overflow-y: auto; &__link { - @extend %link; @extend %row-nowrap; padding: 1rem; font-size: 1rem; border-bottom: 1px solid $alto; align-items: center; + justify-content: flex-start; } &__back-caret { @@ -76,13 +78,12 @@ @extend %col-nowrap; &__load-more { - @extend %link; - font-size: 0.75rem; line-height: 1.0625rem; padding: 0.5rem; text-align: center; border-bottom: 1px solid $alto; + justify-content: flex-start; } } @@ -91,7 +92,7 @@ } &__group-label { - @extend %h8; + @include H8; background-color: $Grey-000; color: $Grey-600; @@ -136,7 +137,7 @@ } &__subtitle { - @extend %h8; + @include H8; color: $Grey-500; } @@ -186,7 +187,7 @@ } &__input { - @extend %h6; + @include H6; flex: 1 1 auto; width: 0; diff --git a/ui/app/pages/send/send.utils.js b/ui/app/pages/send/send.utils.js index 7ffc5dcdb..32dc1939a 100644 --- a/ui/app/pages/send/send.utils.js +++ b/ui/app/pages/send/send.utils.js @@ -1,3 +1,5 @@ +import abi from 'ethereumjs-abi' +import ethUtil from 'ethereumjs-util' import { addCurrencies, conversionUtil, @@ -19,9 +21,6 @@ import { TOKEN_TRANSFER_FUNCTION_SIGNATURE, } from './send.constants' -import abi from 'ethereumjs-abi' -import ethUtil from 'ethereumjs-util' - export { addGasBuffer, calcGasTotal, @@ -69,7 +68,7 @@ function isBalanceSufficient ({ { value: totalAmount, fromNumericBase: 'hex', - conversionRate: conversionRate, + conversionRate, fromCurrency: primaryCurrency, }, ) @@ -238,6 +237,7 @@ async function estimateGas ({ // if not, fall back to block gasLimit if (!blockGasLimit) { + // eslint-disable-next-line no-param-reassign blockGasLimit = MIN_GAS_LIMIT_HEX } @@ -261,9 +261,9 @@ async function estimateGas ({ if (simulationFailed) { const estimateWithBuffer = addGasBuffer(paramsForGasEstimate.gas, blockGasLimit, 1.5) return ethUtil.addHexPrefix(estimateWithBuffer) - } else { - throw error } + throw error + } } @@ -301,11 +301,11 @@ function addGasBuffer (initialGasLimitHex, blockGasLimitHex, bufferMultiplier = function generateTokenTransferData ({ toAddress = '0x0', amount = '0x0', sendToken }) { if (!sendToken) { - return + return undefined } return TOKEN_TRANSFER_FUNCTION_SIGNATURE + Array.prototype.map.call( abi.rawEncode(['address', 'uint256'], [toAddress, ethUtil.addHexPrefix(amount)]), - (x) => ('00' + x.toString(16)).slice(-2), + (x) => (`00${x.toString(16)}`).slice(-2), ).join('') } @@ -314,7 +314,7 @@ function getToAddressForGasUpdate (...addresses) { } function removeLeadingZeroes (str) { - return str.replace(/^0*(?=\d)/, '') + return str.replace(/^0*(?=\d)/u, '') } function ellipsify (text, first = 6, last = 4) { diff --git a/ui/app/pages/send/tests/send-component.test.js b/ui/app/pages/send/tests/send-component.test.js index 757b8fa63..5a157aa6b 100644 --- a/ui/app/pages/send/tests/send-component.test.js +++ b/ui/app/pages/send/tests/send-component.test.js @@ -1,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import proxyquire from 'proxyquire' import { shallow } from 'enzyme' import sinon from 'sinon' @@ -63,12 +63,12 @@ describe('Send Component', function () { tokenBalance="mockTokenBalance" tokenContract={{ method: 'mockTokenMethod' }} updateAndSetGasLimit={propsMethodSpies.updateAndSetGasLimit} - qrCodeDetected={() => {}} - scanQrCode={() => {}} - updateSendEnsResolution={() => {}} - updateSendEnsResolutionError={() => {}} + qrCodeDetected={() => undefined} + scanQrCode={() => undefined} + updateSendEnsResolution={() => undefined} + updateSendEnsResolutionError={() => undefined} updateSendErrors={propsMethodSpies.updateSendErrors} - updateSendTo={() => {}} + updateSendTo={() => undefined} updateSendTokenBalance={propsMethodSpies.updateSendTokenBalance} resetSendState={propsMethodSpies.resetSendState} updateToNicknameIfNecessary={propsMethodSpies.updateToNicknameIfNecessary} diff --git a/ui/app/pages/send/tests/send-container.test.js b/ui/app/pages/send/tests/send-container.test.js index 84a138d92..6cc39fe31 100644 --- a/ui/app/pages/send/tests/send-container.test.js +++ b/ui/app/pages/send/tests/send-container.test.js @@ -21,7 +21,7 @@ proxyquire('../send.container.js', { return () => ({}) }, }, - 'react-router-dom': { withRouter: () => {} }, + 'react-router-dom': { withRouter: () => undefined }, 'redux': { compose: (_, arg2) => () => arg2() }, '../../store/actions': actionSpies, '../../ducks/send/send.duck': duckActionSpies, @@ -67,7 +67,7 @@ describe('send container', function () { it('should dispatch an updateGasData action when editingTransactionId is falsy', function () { const { gasPrice, selectedAddress, sendToken, blockGasLimit, to, value, data } = mockProps mapDispatchToPropsObject.updateAndSetGasLimit( - Object.assign({}, mockProps, { editingTransactionId: false }), + { ...mockProps, editingTransactionId: false }, ) assert(dispatchSpy.calledOnce) assert.deepEqual( @@ -85,7 +85,7 @@ describe('send container', function () { } it('should dispatch an action', function () { - mapDispatchToPropsObject.updateSendTokenBalance(Object.assign({}, mockProps)) + mapDispatchToPropsObject.updateSendTokenBalance({ ...mockProps }) assert(dispatchSpy.calledOnce) assert.deepEqual( actionSpies.updateSendTokenBalance.getCall(0).args[0], diff --git a/ui/app/pages/send/tests/send-utils.test.js b/ui/app/pages/send/tests/send-utils.test.js index 08bc30289..0d23947ff 100644 --- a/ui/app/pages/send/tests/send-utils.test.js +++ b/ui/app/pages/send/tests/send-utils.test.js @@ -10,18 +10,19 @@ import { const stubs = { addCurrencies: sinon.stub().callsFake((a, b) => { - if (String(a).match(/^0x.+/)) { - a = Number(String(a).slice(2)) + let [a1, b1] = [a, b] + if (String(a).match(/^0x.+/u)) { + a1 = Number(String(a).slice(2)) } - if (String(b).match(/^0x.+/)) { - b = Number(String(b).slice(2)) + if (String(b).match(/^0x.+/u)) { + b1 = Number(String(b).slice(2)) } - return a + b + return a1 + b1 }), conversionUtil: sinon.stub().callsFake((val) => parseInt(val, 16)), conversionGTE: sinon.stub().callsFake((obj1, obj2) => obj1.value >= obj2.value), multiplyCurrencies: sinon.stub().callsFake((a, b) => `${a}x${b}`), - calcTokenAmount: sinon.stub().callsFake((a, d) => 'calc:' + a + d), + calcTokenAmount: sinon.stub().callsFake((a, d) => `calc:${a}${d}`), rawEncode: sinon.stub().returns([16, 1100]), conversionGreaterThan: sinon.stub().callsFake((obj1, obj2) => obj1.value > obj2.value), conversionLessThan: sinon.stub().callsFake((obj1, obj2) => obj1.value < obj2.value), @@ -69,7 +70,7 @@ describe('send utils', function () { toNumericBase: 'hex', multiplicandBase: 16, multiplierBase: 16, - } ], + }], ) }) }) @@ -294,8 +295,8 @@ describe('send utils', function () { to: '0xisContract', estimateGasMethod: sinon.stub().callsFake( ({ to }) => { - if (typeof to === 'string' && to.match(/willFailBecauseOf:/)) { - throw new Error(to.match(/:(.+)$/)[1]) + if (typeof to === 'string' && to.match(/willFailBecauseOf:/u)) { + throw new Error(to.match(/:(.+)$/u)[1]) } return { toString: (n) => `0xabc${n}` } }, @@ -311,7 +312,7 @@ describe('send utils', function () { beforeEach(function () { global.eth = { getCode: sinon.stub().callsFake( - (address) => Promise.resolve(address.match(/isContract/) ? 'not-0x' : '0x'), + (address) => Promise.resolve(address.match(/isContract/u) ? 'not-0x' : '0x'), ), } }) @@ -326,32 +327,32 @@ describe('send utils', function () { assert.equal(baseMockParams.estimateGasMethod.callCount, 1) assert.deepEqual( baseMockParams.estimateGasMethod.getCall(0).args[0], - Object.assign({ gasPrice: undefined, value: undefined }, baseExpectedCall), + { gasPrice: undefined, value: undefined, ...baseExpectedCall }, ) assert.equal(result, '0xabc16') }) it('should call ethQuery.estimateGas with the expected params when initialGasLimitHex is lower than the upperGasLimit', async function () { - const result = await estimateGas(Object.assign({}, baseMockParams, { blockGasLimit: '0xbcd' })) + const result = await estimateGas({ ...baseMockParams, blockGasLimit: '0xbcd' }) assert.equal(baseMockParams.estimateGasMethod.callCount, 1) assert.deepEqual( baseMockParams.estimateGasMethod.getCall(0).args[0], - Object.assign({ gasPrice: undefined, value: undefined }, baseExpectedCall, { gas: '0xbcdx0.95' }), + { gasPrice: undefined, value: undefined, ...baseExpectedCall, gas: '0xbcdx0.95' }, ) assert.equal(result, '0xabc16x1.5') }) it('should call ethQuery.estimateGas with a value of 0x0 and the expected data and to if passed a sendToken', async function () { - const result = await estimateGas(Object.assign({ data: 'mockData', sendToken: { address: 'mockAddress' } }, baseMockParams)) + const result = await estimateGas({ data: 'mockData', sendToken: { address: 'mockAddress' }, ...baseMockParams }) assert.equal(baseMockParams.estimateGasMethod.callCount, 1) assert.deepEqual( baseMockParams.estimateGasMethod.getCall(0).args[0], - Object.assign({}, baseExpectedCall, { - gasPrice: undefined, + { + ...baseExpectedCall, gasPrice: undefined, value: '0x0', data: '0xa9059cbb104c', to: 'mockAddress', - }), + }, ) assert.equal(result, '0xabc16') }) @@ -370,46 +371,40 @@ describe('send utils', function () { it(`should return ${SIMPLE_GAS_COST} if ethQuery.getCode does not return '0x'`, async function () { assert.equal(baseMockParams.estimateGasMethod.callCount, 0) - const result = await estimateGas(Object.assign({}, baseMockParams, { to: '0x123' })) + const result = await estimateGas({ ...baseMockParams, to: '0x123' }) assert.equal(result, SIMPLE_GAS_COST) }) it(`should return ${SIMPLE_GAS_COST} if not passed a sendToken or truthy to address`, async function () { assert.equal(baseMockParams.estimateGasMethod.callCount, 0) - const result = await estimateGas(Object.assign({}, baseMockParams, { to: null })) + const result = await estimateGas({ ...baseMockParams, to: null }) assert.equal(result, SIMPLE_GAS_COST) }) it(`should not return ${SIMPLE_GAS_COST} if passed a sendToken`, async function () { assert.equal(baseMockParams.estimateGasMethod.callCount, 0) - const result = await estimateGas(Object.assign({}, baseMockParams, { to: '0x123', sendToken: { address: '0x0' } })) + const result = await estimateGas({ ...baseMockParams, to: '0x123', sendToken: { address: '0x0' } }) assert.notEqual(result, SIMPLE_GAS_COST) }) it(`should return ${BASE_TOKEN_GAS_COST} if passed a sendToken but no to address`, async function () { - const result = await estimateGas(Object.assign({}, baseMockParams, { to: null, sendToken: { address: '0x0' } })) + const result = await estimateGas({ ...baseMockParams, to: null, sendToken: { address: '0x0' } }) assert.equal(result, BASE_TOKEN_GAS_COST) }) it(`should return the adjusted blockGasLimit if it fails with a 'Transaction execution error.'`, async function () { - const result = await estimateGas(Object.assign({}, baseMockParams, { - to: 'isContract willFailBecauseOf:Transaction execution error.', - })) + const result = await estimateGas({ ...baseMockParams, to: 'isContract willFailBecauseOf:Transaction execution error.' }) assert.equal(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 estimateGas(Object.assign({}, baseMockParams, { - to: 'isContract willFailBecauseOf:gas required exceeds allowance or always failing transaction.', - })) + const result = await estimateGas({ ...baseMockParams, to: 'isContract willFailBecauseOf:gas required exceeds allowance or always failing transaction.' }) assert.equal(result, '0x64x0.95') }) it(`should reject other errors`, async function () { try { - await estimateGas(Object.assign({}, baseMockParams, { - to: 'isContract willFailBecauseOf:some other error', - })) + await estimateGas({ ...baseMockParams, to: 'isContract willFailBecauseOf:some other error' }) } catch (err) { assert.equal(err.message, 'some other error') } 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 df952eff6..055ad2977 100644 --- a/ui/app/pages/settings/advanced-tab/advanced-tab.component.js +++ b/ui/app/pages/settings/advanced-tab/advanced-tab.component.js @@ -422,7 +422,7 @@ export default class AdvancedTab extends PureComponent { handleIpfsGatewaySave () { const url = new URL(addUrlProtocolPrefix(this.state.ipfsGateway)) - const host = url.host + const { host } = url this.props.setIpfsGateway(host) } @@ -489,9 +489,9 @@ export default class AdvancedTab extends PureComponent { function addUrlProtocolPrefix (urlString) { if (!urlString.match( - /(^http:\/\/)|(^https:\/\/)/, + /(^http:\/\/)|(^https:\/\/)/u, )) { - return 'https://' + urlString + return `https://${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 c36bc204f..64777f4fa 100644 --- a/ui/app/pages/settings/advanced-tab/advanced-tab.container.js +++ b/ui/app/pages/settings/advanced-tab/advanced-tab.container.js @@ -1,4 +1,3 @@ -import AdvancedTab from './advanced-tab.component' import { compose } from 'redux' import { connect } from 'react-redux' import { withRouter } from 'react-router-dom' @@ -14,6 +13,7 @@ import { setIpfsGateway, } from '../../../store/actions' import { getPreferences } from '../../../selectors' +import AdvancedTab from './advanced-tab.component' export const mapStateToProps = (state) => { const { appState: { warning }, metamask } = state 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 69fe064c8..548623187 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,5 +1,5 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import sinon from 'sinon' import { shallow } from 'enzyme' import AdvancedTab from '../advanced-tab.component' @@ -10,10 +10,10 @@ describe('AdvancedTab Component', function () { const root = shallow( {}} - setIpfsGateway={() => {}} - setShowFiatConversionOnTestnetsPreference={() => {}} - setThreeBoxSyncingPermission={() => {}} + setAutoLockTimeLimit={() => undefined} + setIpfsGateway={() => undefined} + setShowFiatConversionOnTestnetsPreference={() => undefined} + setThreeBoxSyncingPermission={() => undefined} threeBoxDisabled threeBoxSyncingAllowed={false} />, @@ -33,9 +33,9 @@ describe('AdvancedTab Component', function () { {}} - setShowFiatConversionOnTestnetsPreference={() => {}} - setThreeBoxSyncingPermission={() => {}} + setIpfsGateway={() => undefined} + setShowFiatConversionOnTestnetsPreference={() => undefined} + setThreeBoxSyncingPermission={() => undefined} threeBoxDisabled threeBoxSyncingAllowed={false} />, diff --git a/ui/app/pages/settings/alerts-tab/alerts-tab.js b/ui/app/pages/settings/alerts-tab/alerts-tab.js index 1c503e06f..80aa3b00f 100644 --- a/ui/app/pages/settings/alerts-tab/alerts-tab.js +++ b/ui/app/pages/settings/alerts-tab/alerts-tab.js @@ -3,7 +3,7 @@ import PropTypes from 'prop-types' import { useDispatch, useSelector } from 'react-redux' import { ALERT_TYPES } from '../../../../../app/scripts/controllers/alert' -import Tooltip from '../../../components/ui/tooltip-v2' +import Tooltip from '../../../components/ui/tooltip' import ToggleButton from '../../../components/ui/toggle-button' import { setAlertEnabledness } from '../../../store/actions' import { getAlertEnabledness } from '../../../ducks/metamask/metamask' 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 20ebdcee6..12f420186 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,12 +1,12 @@ 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' -import { debounce } from 'lodash' export default class AddContact extends PureComponent { 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 66c40e51a..9c5993e4f 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,4 +1,3 @@ -import AddContact from './add-contact.component' import { compose } from 'redux' import { connect } from 'react-redux' import { withRouter } from 'react-router-dom' @@ -6,6 +5,7 @@ import { addToAddressBook, showQrScanner, qrCodeDetected } from '../../../../sto import { getQrCodeData, } from '../../../../selectors' +import AddContact from './add-contact.component' const mapStateToProps = (state) => { return { 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 835963a83..74cc1b89b 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,15 +1,15 @@ import React, { Component } from 'react' import PropTypes from 'prop-types' import ContactList from '../../../components/app/contact-list' -import EditContact from './edit-contact' -import AddContact from './add-contact' -import ViewContact from './view-contact' -import MyAccounts from './my-accounts' 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' export default class ContactListTab extends Component { static contextTypes = { @@ -30,7 +30,7 @@ export default class ContactListTab extends Component { renderAddresses () { const { addressBook, history, selectedAddress } = this.props - const contacts = addressBook.filter(({ name }) => !!name) + const contacts = addressBook.filter(({ name }) => Boolean(name)) const nonContacts = addressBook.filter(({ name }) => !name) return ( @@ -121,6 +121,7 @@ export default class ContactListTab extends Component { } else if (!hideAddressBook && showingMyAccounts) { return () } + return null } render () { 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 d3bb1799a..597b74683 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,4 +1,3 @@ -import ContactListTab from './contact-list-tab.component' import { compose } from 'redux' import { connect } from 'react-redux' import { withRouter } from 'react-router-dom' @@ -14,13 +13,13 @@ import { CONTACT_MY_ACCOUNTS_VIEW_ROUTE, CONTACT_MY_ACCOUNTS_EDIT_ROUTE, } from '../../../helpers/constants/routes' - +import ContactListTab from './contact-list-tab.component' const mapStateToProps = (state, ownProps) => { const { location } = ownProps const { pathname } = location - const pathNameTail = pathname.match(/[^/]+$/)[0] + 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)) 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 3766f1ac8..b372fae5f 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,4 +1,3 @@ -import EditContact from './edit-contact.component' import { compose } from 'redux' import { connect } from 'react-redux' import { withRouter } from 'react-router-dom' @@ -11,11 +10,12 @@ import { CONTACT_LIST_ROUTE, } from '../../../../helpers/constants/routes' import { addToAddressBook, removeFromAddressBook, setAccountLabel } from '../../../../store/actions' +import EditContact from './edit-contact.component' const mapStateToProps = (state, ownProps) => { const { location } = ownProps const { pathname } = location - const pathNameTail = pathname.match(/[^/]+$/)[0] + const pathNameTail = pathname.match(/[^/]+$/u)[0] const pathNameTailIsAddress = pathNameTail.includes('0x') const address = pathNameTailIsAddress ? pathNameTail.toLowerCase() : ownProps.match.params.id diff --git a/ui/app/pages/settings/contact-list-tab/index.scss b/ui/app/pages/settings/contact-list-tab/index.scss index 02273a66f..9c33c3701 100644 --- a/ui/app/pages/settings/contact-list-tab/index.scss +++ b/ui/app/pages/settings/contact-list-tab/index.scss @@ -33,7 +33,6 @@ &__header, &__header--edit { &__name { - font-family: Roboto; font-style: normal; font-weight: normal; font-size: 24px; @@ -179,7 +178,6 @@ } &__header { - font-family: Roboto; font-style: normal; font-weight: normal; font-size: 18px; @@ -193,7 +191,6 @@ } &__text { - font-family: Roboto; font-style: normal; font-weight: normal; font-size: 14px; 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 86e569e3d..6dab955b6 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,8 +1,8 @@ -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) 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 ce9312c87..6256c1134 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 @@ -6,17 +6,17 @@ 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-v2' +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}/g) - .join(' ') + `0x ${ + address + .slice(2) + .match(/.{1,4}/ug) + .join(' ')}` ) } diff --git a/ui/app/pages/settings/contact-list-tab/view-contact/view-contact.container.js b/ui/app/pages/settings/contact-list-tab/view-contact/view-contact.container.js index 7f7c5d8c1..87bf707db 100644 --- a/ui/app/pages/settings/contact-list-tab/view-contact/view-contact.container.js +++ b/ui/app/pages/settings/contact-list-tab/view-contact/view-contact.container.js @@ -1,4 +1,3 @@ -import ViewContact from './view-contact.component' import { compose } from 'redux' import { connect } from 'react-redux' import { withRouter } from 'react-router-dom' @@ -11,11 +10,12 @@ import { CONTACT_MY_ACCOUNTS_ROUTE, CONTACT_MY_ACCOUNTS_VIEW_ROUTE, } from '../../../../helpers/constants/routes' +import ViewContact from './view-contact.component' const mapStateToProps = (state, ownProps) => { const { location } = ownProps const { pathname } = location - const pathNameTail = pathname.match(/[^/]+$/)[0] + const pathNameTail = pathname.match(/[^/]+$/u)[0] const pathNameTailIsAddress = pathNameTail.includes('0x') const address = pathNameTailIsAddress ? pathNameTail.toLowerCase() : ownProps.match.params.id diff --git a/ui/app/pages/settings/index.scss b/ui/app/pages/settings/index.scss index 0c4371cf4..b72deb39e 100644 --- a/ui/app/pages/settings/index.scss +++ b/ui/app/pages/settings/index.scss @@ -70,7 +70,6 @@ } &__sub-header-text { - font-family: Roboto; font-style: normal; font-weight: normal; font-size: 20px; diff --git a/ui/app/pages/settings/info-tab/index.scss b/ui/app/pages/settings/info-tab/index.scss index 9cc7e21b2..3cbe63b5c 100644 --- a/ui/app/pages/settings/info-tab/index.scss +++ b/ui/app/pages/settings/info-tab/index.scss @@ -21,6 +21,11 @@ } } + &__link-text { + width: max-content; + padding: 0; + } + &__link-item { padding: 15px 0; @@ -29,10 +34,6 @@ } } - &__link-text { - @extend %link; - } - &__version-number { padding-top: 5px; font-size: 13px; diff --git a/ui/app/pages/settings/info-tab/info-tab.component.js b/ui/app/pages/settings/info-tab/info-tab.component.js index 9d522a3a1..21c2ef5f4 100644 --- a/ui/app/pages/settings/info-tab/info-tab.component.js +++ b/ui/app/pages/settings/info-tab/info-tab.component.js @@ -1,5 +1,6 @@ import React, { PureComponent } from 'react' import PropTypes from 'prop-types' +import Button from '../../../components/ui/button' export default class InfoTab extends PureComponent { state = { @@ -19,71 +20,71 @@ export default class InfoTab extends PureComponent { { t('links') }
- - - { t('privacyMsg') } - - + { t('privacyMsg') } +
- - - { t('terms') } - - + { t('terms') } +
- - - { t('attributions') } - - + { t('attributions') } +

- - - { t('supportCenter') } - - + { t('supportCenter') } +
- - - { t('visitWebSite') } - - + { t('visitWebSite') } +
- - - { t('contactUs') } - - + { t('contactUs') } +
) diff --git a/ui/app/pages/settings/networks-tab/index.scss b/ui/app/pages/settings/networks-tab/index.scss index 92504f641..f6a69af39 100644 --- a/ui/app/pages/settings/networks-tab/index.scss +++ b/ui/app/pages/settings/networks-tab/index.scss @@ -96,7 +96,6 @@ } &__network-form-label { - font-family: Roboto; font-style: normal; font-weight: normal; font-size: 14px; @@ -177,7 +176,6 @@ &__networks-list-name { margin-left: 11px; - font-family: Roboto; font-style: normal; font-weight: normal; font-size: 16px; @@ -187,6 +185,11 @@ &:hover { cursor: pointer; } + + svg { + margin-left: 10px; + padding-top: 3px; + } } &__networks-list-arrow { @@ -216,6 +219,11 @@ font-weight: bold; color: #000; } + + &__networks-list-name--disabled { + font-weight: 300; + color: #cdcdcd; + } } .network-form { 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 34209983a..024af3a31 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 @@ -206,15 +206,15 @@ export default class NetworkForm extends PureComponent { } validateChainId = (chainId) => { - this.setErrorTo('chainId', !!chainId && Number.isNaN(parseInt(chainId)) + // eslint-disable-next-line radix + this.setErrorTo('chainId', Boolean(chainId) && Number.isNaN(parseInt(chainId)) ? `${this.context.t('invalidInput')} chainId` - : '', - ) + : '') } isValidWhenAppended = (url) => { const appendedRpc = `http://${url}` - return validUrl.isWebUri(appendedRpc) && !url.match(/^https?:\/\/$/) + return validUrl.isWebUri(appendedRpc) && !url.match(/^https?:\/\/$/u) } validateBlockExplorerURL = (url, stateKey) => { 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 e0046edfc..c9450e4c5 100644 --- a/ui/app/pages/settings/networks-tab/networks-tab.component.js +++ b/ui/app/pages/settings/networks-tab/networks-tab.component.js @@ -1,12 +1,13 @@ import React, { PureComponent } from 'react' import PropTypes from 'prop-types' +import classnames from 'classnames' import { SETTINGS_ROUTE } from '../../../helpers/constants/routes' import { ENVIRONMENT_TYPE_POPUP } from '../../../../../app/scripts/lib/enums' import { getEnvironmentType } from '../../../../../app/scripts/lib/util' -import classnames from 'classnames' import Button from '../../../components/ui/button' -import NetworkForm from './network-form' +import LockIcon from '../../../components/ui/lock-icon' import NetworkDropdownIcon from '../../../components/app/dropdowns/components/network-dropdown-icon' +import NetworkForm from './network-form' export default class NetworksTab extends PureComponent { static contextTypes = { @@ -103,7 +104,7 @@ export default class NetworksTab extends PureComponent { return (
{ setNetworksTabAddMode(false) @@ -117,9 +118,17 @@ export default class NetworksTab extends PureComponent {
{ label || this.context.t(labelKey) } + { currentProviderType !== 'rpc' && ( + + ) }
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 9377a1111..5b35f3ba5 100644 --- a/ui/app/pages/settings/networks-tab/networks-tab.container.js +++ b/ui/app/pages/settings/networks-tab/networks-tab.container.js @@ -1,4 +1,3 @@ -import NetworksTab from './networks-tab.component' import { compose } from 'redux' import { connect } from 'react-redux' import { withRouter } from 'react-router-dom' @@ -10,6 +9,7 @@ import { editRpc, showModal, } from '../../../store/actions' +import NetworksTab from './networks-tab.component' import { defaultNetworksData } from './networks-tab.constants' const defaultNetworks = defaultNetworksData.map((network) => ({ ...network, viewOnly: true })) @@ -36,7 +36,7 @@ const mapStateToProps = (state) => { } }) - const networksToRender = [ ...defaultNetworks, ...frequentRpcNetworkListDetails ] + const networksToRender = [...defaultNetworks, ...frequentRpcNetworkListDetails] let selectedNetwork = networksToRender.find((network) => network.rpcUrl === networksTabSelectedRpcUrl) || {} const networkIsSelected = Boolean(selectedNetwork.rpcUrl) 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 9852b685e..cfbcfbeb9 100644 --- a/ui/app/pages/settings/security-tab/security-tab.container.js +++ b/ui/app/pages/settings/security-tab/security-tab.container.js @@ -1,4 +1,3 @@ -import SecurityTab from './security-tab.component' import { compose } from 'redux' import { connect } from 'react-redux' import { withRouter } from 'react-router-dom' @@ -7,6 +6,7 @@ import { setParticipateInMetaMetrics, setUsePhishDetect, } from '../../../store/actions' +import SecurityTab from './security-tab.component' const mapStateToProps = (state) => { const { appState: { warning }, metamask } = state 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 1ac996d05..fd1b8c085 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,8 +1,8 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import sinon from 'sinon' import { mount } from 'enzyme' -import SecurityTab from '../index' +import SecurityTab from '..' describe('Security Tab', function () { let wrapper @@ -28,7 +28,7 @@ describe('Security Tab', function () { , { context: { t: (str) => str, - metricsEvent: () => {}, + metricsEvent: () => undefined, }, }, ) diff --git a/ui/app/pages/settings/settings-tab/index.scss b/ui/app/pages/settings/settings-tab/index.scss index 5d9864984..39670e46f 100644 --- a/ui/app/pages/settings/settings-tab/index.scss +++ b/ui/app/pages/settings/settings-tab/index.scss @@ -5,12 +5,6 @@ color: $crimson; } - &__advanced-link { - @extend %small-link; - - padding-left: 5px; - } - &__rpc-save-button { align-self: flex-end; padding: 5px; 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 39d67b5f9..c7d984f88 100644 --- a/ui/app/pages/settings/settings-tab/settings-tab.component.js +++ b/ui/app/pages/settings/settings-tab/settings-tab.component.js @@ -1,6 +1,6 @@ import React, { PureComponent } from 'react' import PropTypes from 'prop-types' -import availableCurrencies from '../../../helpers/constants/available-conversions' +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' @@ -101,7 +101,6 @@ export default class SettingsTab extends PureComponent { ) } - renderBlockieOptIn () { const { t } = this.context const { useBlockie, setUseBlockie } = this.props 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 1d9f65750..0915ccf7c 100644 --- a/ui/app/pages/settings/settings-tab/settings-tab.container.js +++ b/ui/app/pages/settings/settings-tab/settings-tab.container.js @@ -1,4 +1,3 @@ -import SettingsTab from './settings-tab.component' import { connect } from 'react-redux' import { setCurrentCurrency, @@ -8,6 +7,7 @@ import { setParticipateInMetaMetrics, } from '../../../store/actions' import { getPreferences } from '../../../selectors' +import SettingsTab from './settings-tab.component' const mapStateToProps = (state) => { const { appState: { warning }, metamask } = state 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 7fefd559e..1803ff590 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,8 +1,8 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import sinon from 'sinon' import { mount } from 'enzyme' -import SettingsTab from '../index' +import SettingsTab from '..' describe('Settings Tab', function () { let wrapper diff --git a/ui/app/pages/settings/settings.component.js b/ui/app/pages/settings/settings.component.js index 866ed4be7..d4372eed0 100644 --- a/ui/app/pages/settings/settings.component.js +++ b/ui/app/pages/settings/settings.component.js @@ -1,15 +1,8 @@ import React, { PureComponent } from 'react' import PropTypes from 'prop-types' import { Switch, Route, matchPath } from 'react-router-dom' -import TabBar from '../../components/app/tab-bar' import classnames from 'classnames' -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' +import TabBar from '../../components/app/tab-bar' import { ALERTS_ROUTE, ADVANCED_ROUTE, @@ -26,6 +19,13 @@ import { 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' class SettingsPage extends PureComponent { static propTypes = { diff --git a/ui/app/pages/settings/settings.container.js b/ui/app/pages/settings/settings.container.js index ebeb2ae4b..f1881581b 100644 --- a/ui/app/pages/settings/settings.container.js +++ b/ui/app/pages/settings/settings.container.js @@ -1,4 +1,3 @@ -import Settings from './settings.component' import { compose } from 'redux' import { connect } from 'react-redux' import { withRouter } from 'react-router-dom' @@ -24,6 +23,7 @@ import { CONTACT_MY_ACCOUNTS_EDIT_ROUTE, CONTACT_MY_ACCOUNTS_VIEW_ROUTE, } from '../../helpers/constants/routes' +import Settings from './settings.component' const ROUTES_TO_I18N_KEYS = { [GENERAL_ROUTE]: 'general', @@ -42,7 +42,7 @@ const ROUTES_TO_I18N_KEYS = { const mapStateToProps = (state, ownProps) => { const { location } = ownProps const { pathname } = location - const pathNameTail = pathname.match(/[^/]+$/)[0] + const pathNameTail = pathname.match(/[^/]+$/u)[0] const isAddressEntryPage = pathNameTail.includes('0x') const isMyAccountsPage = pathname.match('my-accounts') diff --git a/ui/app/pages/token/actionable-message/actionable-message.js b/ui/app/pages/token/actionable-message/actionable-message.js new file mode 100644 index 000000000..84cade2ec --- /dev/null +++ b/ui/app/pages/token/actionable-message/actionable-message.js @@ -0,0 +1,51 @@ +import React from 'react' +import PropTypes from 'prop-types' +import classnames from 'classnames' + +export default function ActionableMessage ({ + message = '', + primaryAction = null, + secondaryAction = null, + className = '', +}) { + return ( +
+
+ {message} +
+ {(primaryAction || secondaryAction) && ( +
+ {primaryAction && ( +
+ {primaryAction.label} +
+ )} + {secondaryAction && ( +
+ {secondaryAction.label} +
+ )} +
+ )} +
+ ) +} + +ActionableMessage.propTypes = { + message: PropTypes.string.isRequired, + primaryAction: PropTypes.shape({ + label: PropTypes.string, + onClick: PropTypes.func, + }), + secondaryAction: PropTypes.shape({ + label: PropTypes.string, + onClick: PropTypes.func, + }), + className: PropTypes.string, +} diff --git a/ui/app/pages/token/actionable-message/actionable-message.stories.js b/ui/app/pages/token/actionable-message/actionable-message.stories.js new file mode 100644 index 000000000..d881fca82 --- /dev/null +++ b/ui/app/pages/token/actionable-message/actionable-message.stories.js @@ -0,0 +1,58 @@ +import React from 'react' +import { action } from '@storybook/addon-actions' +import { text } from '@storybook/addon-knobs/react' +import ActionableMessage from '.' + +export default { + title: 'ActionableMessage', +} + +export const NoAction = () => ( +
+ +
+) + +export const OneAction = () => ( +
+ +
+) + +export const TwoActions = () => ( +
+ +
+) + +export const LeftAligned = () => ( +
+ +
+) diff --git a/ui/app/pages/token/actionable-message/index.js b/ui/app/pages/token/actionable-message/index.js new file mode 100644 index 000000000..c6edbc359 --- /dev/null +++ b/ui/app/pages/token/actionable-message/index.js @@ -0,0 +1 @@ +export { default } from './actionable-message' diff --git a/ui/app/pages/token/actionable-message/index.scss b/ui/app/pages/token/actionable-message/index.scss new file mode 100644 index 000000000..516e45c44 --- /dev/null +++ b/ui/app/pages/token/actionable-message/index.scss @@ -0,0 +1,55 @@ +.actionable-message { + background: $Blue-000; + border: 1px solid $Blue-200; + border-radius: 8px; + padding: 16px; + margin-top: 18px; + display: flex; + flex-flow: column; + align-items: center; + + @include H7; + + &__message { + color: $Blue-600; + text-align: center; + } + + &__actions { + display: flex; + width: 80%; + justify-content: space-evenly; + align-items: center; + margin-top: 10px; + color: $Blue-600; + } + + &__action { + font-weight: bold; + cursor: pointer; + } + + &--warning { + background: $Yellow-100; + border: 1px solid $Yellow-500; + justify-content: center; + + .actionable-message__message, + .actionable-message__action { + color: $Black-100; + } + + .actionable-message__action--secondary { + text-decoration: underline; + } + } + + &--left-aligned { + .actionable-message__message, + .actionable-message__actions { + justify-content: flex-start; + text-align: left; + width: 100%; + } + } +} diff --git a/ui/app/pages/token/exchange-rate-display/exchange-rate-display.js b/ui/app/pages/token/exchange-rate-display/exchange-rate-display.js new file mode 100644 index 000000000..85ae82fe1 --- /dev/null +++ b/ui/app/pages/token/exchange-rate-display/exchange-rate-display.js @@ -0,0 +1,65 @@ +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' + +export default function ExchangeRateDisplay ({ + primaryTokenValue, + primaryTokenDecimals = 18, + primaryTokenSymbol, + secondaryTokenValue, + secondaryTokenDecimals = 18, + secondaryTokenSymbol, + arrowColor = 'black', + className, +}) { + const [showPrimaryToSecondary, setShowPrimaryToSecondary] = useState(true) + const [arrowsRotation, setArrowRotation] = useState(0) + + const primaryTokenAmount = calcTokenAmount(primaryTokenValue, primaryTokenDecimals) + const secondaryTokenAmount = calcTokenAmount(secondaryTokenValue, secondaryTokenDecimals) + + const conversionRateFromPrimaryToSecondary = (new BigNumber(secondaryTokenAmount)).div(primaryTokenAmount).round(6).toString(10) + const conversionRateFromSecondaryToPrimary = (new BigNumber(primaryTokenAmount)).div(secondaryTokenAmount).round(6).toString(10) + + const baseSymbol = showPrimaryToSecondary ? primaryTokenSymbol : secondaryTokenSymbol + const ratiodSymbol = showPrimaryToSecondary ? secondaryTokenSymbol : primaryTokenSymbol + const rate = showPrimaryToSecondary ? conversionRateFromPrimaryToSecondary : conversionRateFromSecondaryToPrimary + + return ( +
+ 1 + {baseSymbol} + = + {rate} + {ratiodSymbol} +
{ + setShowPrimaryToSecondary(!showPrimaryToSecondary) + setArrowRotation(arrowsRotation + 360) + }} + style={{ transform: `rotate(${arrowsRotation}deg)` }} + > + + + +
+
+ ) +} + +ExchangeRateDisplay.propTypes = { + primaryTokenValue: PropTypes.string.isRequired, + primaryTokenDecimals: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), + primaryTokenSymbol: PropTypes.string.isRequired, + secondaryTokenValue: PropTypes.string.isRequired, + secondaryTokenDecimals: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), + secondaryTokenSymbol: PropTypes.string.isRequired, + className: PropTypes.string, + arrowColor: PropTypes.string, +} diff --git a/ui/app/pages/token/exchange-rate-display/exchange-rate-display.stories.js b/ui/app/pages/token/exchange-rate-display/exchange-rate-display.stories.js new file mode 100644 index 000000000..ff939f121 --- /dev/null +++ b/ui/app/pages/token/exchange-rate-display/exchange-rate-display.stories.js @@ -0,0 +1,47 @@ +import React from 'react' +import { text, number } from '@storybook/addon-knobs/react' +import ExchangeRateDisplay from './exchange-rate-display' + +export default { + title: 'ExchangeRateDisplay', +} + +export const Default = () => { + return ( + + ) +} + +export const WhiteOnBlue = () => { + return ( +
+ +
+ ) +} diff --git a/ui/app/pages/token/exchange-rate-display/index.js b/ui/app/pages/token/exchange-rate-display/index.js new file mode 100644 index 000000000..e572fe698 --- /dev/null +++ b/ui/app/pages/token/exchange-rate-display/index.js @@ -0,0 +1 @@ +export { default } from './exchange-rate-display' diff --git a/ui/app/pages/token/exchange-rate-display/index.scss b/ui/app/pages/token/exchange-rate-display/index.scss new file mode 100644 index 000000000..c416f1f53 --- /dev/null +++ b/ui/app/pages/token/exchange-rate-display/index.scss @@ -0,0 +1,26 @@ +.exchange-rate-display { + @include H6; + + display: flex; + align-items: flex-end; + justify-content: center; + color: $Black-100; + + span { + margin-right: 4px; + } + + &__bold { + font-weight: bold; + } + + &__switch-arrows { + cursor: pointer; + margin-top: 2px; + transition: transform 0.5s ease-in-out; + } + + &--white { + color: $white; + } +} diff --git a/ui/app/pages/token/fee-card/fee-card.js b/ui/app/pages/token/fee-card/fee-card.js new file mode 100644 index 000000000..42e751d77 --- /dev/null +++ b/ui/app/pages/token/fee-card/fee-card.js @@ -0,0 +1,69 @@ +import React from 'react' +import PropTypes from 'prop-types' + +export default function FeeCard ({ + onFeeRowClick = null, + feeRowText, + feeRowLinkText = '', + primaryFee, + secondaryFee = '', + onSecondRowClick = null, + secondRowText = '', + secondRowLinkText = '', + hideSecondRow = false, +}) { + return ( +
+
+
onFeeRowClick && onFeeRowClick()}> +
+
+ {feeRowText} +
+ {onFeeRowClick && ( +
+ {feeRowLinkText} +
+ )} +
+
+
+ {primaryFee} +
+ {secondaryFee && ( +
+ {secondaryFee} +
+ )} +
+
+ {!hideSecondRow && secondRowText && ( +
+
+
+ {secondRowText} +
+ {secondRowLinkText && ( +
onSecondRowClick && onSecondRowClick()}> + {secondRowLinkText} +
+ )} +
+
+ )} +
+
+ ) +} + +FeeCard.propTypes = { + onFeeRowClick: PropTypes.func, + feeRowText: PropTypes.string.isRequired, + feeRowLinkText: PropTypes.string, + primaryFee: PropTypes.string.isRequired, + secondaryFee: PropTypes.string, + onSecondRowClick: PropTypes.func, + secondRowText: PropTypes.string, + secondRowLinkText: PropTypes.string, + hideSecondRow: PropTypes.bool, +} diff --git a/ui/app/pages/token/fee-card/fee-card.stories.js b/ui/app/pages/token/fee-card/fee-card.stories.js new file mode 100644 index 000000000..d29807d99 --- /dev/null +++ b/ui/app/pages/token/fee-card/fee-card.stories.js @@ -0,0 +1,47 @@ +import React from 'react' +import { action } from '@storybook/addon-actions' +import { text } from '@storybook/addon-knobs/react' +import FeeCard from './fee-card' + +const containerStyle = { + width: '300px', +} + +export default { + title: 'FeeCard', +} + +export const WithSecondRow = () => { + return ( +
+ +
+ ) +} + +export const WithoutSecondRow = () => { + return ( +
+ +
+ ) +} diff --git a/ui/app/pages/token/fee-card/index.js b/ui/app/pages/token/fee-card/index.js new file mode 100644 index 000000000..84bc1acbb --- /dev/null +++ b/ui/app/pages/token/fee-card/index.js @@ -0,0 +1 @@ +export { default } from './fee-card' diff --git a/ui/app/pages/token/fee-card/index.scss b/ui/app/pages/token/fee-card/index.scss new file mode 100644 index 000000000..d9acd2554 --- /dev/null +++ b/ui/app/pages/token/fee-card/index.scss @@ -0,0 +1,102 @@ +.fee-card { + border-radius: 8px; + border: 1px solid $Grey-100; + width: 100%; + margin-top: auto; + margin-bottom: 8px; + + @include H7; + + &__main { + padding: 16px 16px 12px 16px; + } + + &__row-header { + display: flex; + align-items: center; + margin-top: 8px; + justify-content: space-between; + + @media screen and (min-width: 576px) { + @include H6; + } + + &:first-of-type { + margin-top: 0; + } + + div { + display: flex; + align-items: center; + } + } + + &__row-header-text { + font-weight: bold; + margin-right: 8px; + cursor: pointer; + } + + &__row { + display: flex; + align-items: center; + justify-content: space-between; + margin-top: 8px; + } + + &__row-label { + display: flex; + align-items: center; + + img { + height: 10px; + width: 10px; + margin-left: 4px; + cursor: pointer; + } + } + + &__row-text { + margin-right: 8px; + } + + &__row-fee { + margin-right: 4px; + } + + &__link { + color: $Blue-500; + cursor: pointer; + } + + &__total-box { + border-top: 1px solid $Grey-100; + padding: 12px 16px 16px 16px; + } + + &__total-row { + display: flex; + justify-content: space-between; + align-items: center; + font-weight: bold; + } + + &__total-secondary { + width: 100%; + display: flex; + justify-content: flex-end; + font-weight: bold; + color: $Grey-500; + margin-top: 4px; + } + + &__row-header-secondary { + color: $Grey-500; + margin-right: 20px; + } + + &__row-header-primary { + font-weight: bold; + color: $Grey-500; + } +} diff --git a/ui/app/pages/token/index.scss b/ui/app/pages/token/index.scss new file mode 100644 index 000000000..9cf06a407 --- /dev/null +++ b/ui/app/pages/token/index.scss @@ -0,0 +1,3 @@ +@import 'fee-card/index'; +@import 'exchange-rate-display/index'; +@import 'actionable-message/index'; 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 ec4eb914d..48bb2b78d 100644 --- a/ui/app/pages/unlock-page/tests/unlock-page.test.js +++ b/ui/app/pages/unlock-page/tests/unlock-page.test.js @@ -1,8 +1,8 @@ -import React from 'react' import assert from 'assert' +import React from 'react' import sinon from 'sinon' import { mount } from 'enzyme' -import UnlockPage from '../index' +import UnlockPage from '..' describe('Unlock Page', function () { let wrapper @@ -19,7 +19,6 @@ describe('Unlock Page', function () { showOptInModal: sinon.spy(), } - beforeEach(function () { wrapper = mount( diff --git a/ui/app/pages/unlock-page/unlock-page.component.js b/ui/app/pages/unlock-page/unlock-page.component.js index ffaadc5ee..5fffbf399 100644 --- a/ui/app/pages/unlock-page/unlock-page.component.js +++ b/ui/app/pages/unlock-page/unlock-page.component.js @@ -1,9 +1,9 @@ +import { EventEmitter } from 'events' import React, { Component } from 'react' import PropTypes from 'prop-types' import Button from '@material-ui/core/Button' -import TextField from '../../components/ui/text-field' import getCaretCoordinates from 'textarea-caret' -import { EventEmitter } from 'events' +import TextField from '../../components/ui/text-field' import Mascot from '../../components/ui/mascot' import { DEFAULT_ROUTE } from '../../helpers/constants/routes' diff --git a/ui/app/pages/unlock-page/unlock-page.container.js b/ui/app/pages/unlock-page/unlock-page.container.js index 848f52a50..e0943a33d 100644 --- a/ui/app/pages/unlock-page/unlock-page.container.js +++ b/ui/app/pages/unlock-page/unlock-page.container.js @@ -31,6 +31,7 @@ const mapDispatchToProps = (dispatch) => { } const mergeProps = (stateProps, dispatchProps, ownProps) => { + // eslint-disable-next-line no-shadow const { markPasswordForgotten, tryUnlockMetamask, ...restDispatchProps } = dispatchProps const { history, onSubmit: ownPropsSubmit, ...restOwnProps } = ownProps diff --git a/ui/app/selectors/confirm-transaction.js b/ui/app/selectors/confirm-transaction.js index 553a44307..93c876ef7 100644 --- a/ui/app/selectors/confirm-transaction.js +++ b/ui/app/selectors/confirm-transaction.js @@ -121,7 +121,6 @@ export const unconfirmedTransactionsCountSelector = createSelector( }, ) - export const currentCurrencySelector = (state) => state.metamask.currentCurrency export const conversionRateSelector = (state) => state.metamask.conversionRate diff --git a/ui/app/selectors/custom-gas.js b/ui/app/selectors/custom-gas.js index 816242874..b3c1b1dcd 100644 --- a/ui/app/selectors/custom-gas.js +++ b/ui/app/selectors/custom-gas.js @@ -1,11 +1,9 @@ +import { addHexPrefix } from 'ethereumjs-util' import { conversionUtil, multiplyCurrencies, conversionGreaterThan, } from '../helpers/utils/conversion-util' -import { - getCurrentCurrency, getIsMainnet, getPreferences, -} from '.' import { formatCurrency, } from '../helpers/utils/confirm-tx.util' @@ -18,9 +16,11 @@ import { import { calcGasTotal, } from '../pages/send/send.utils' -import { addHexPrefix } from 'ethereumjs-util' import { GAS_ESTIMATE_TYPES } from '../helpers/constants/common' +import { + getCurrentCurrency, getIsMainnet, getPreferences, +} from '.' const NUMBER_OF_DECIMALS_SM_BTNS = 5 @@ -132,7 +132,6 @@ export function getRenderableEthFee (estimate, gasLimit, numberOfDecimals = 9) { return formatETHFee(fee) } - export function getRenderableConvertedCurrencyFee (estimate, gasLimit, convertedCurrency, conversionRate) { const value = conversionUtil(estimate, { fromNumericBase: 'dec', toNumericBase: 'hex' }) const fee = basicPriceEstimateToETHTotal(value, gasLimit) @@ -164,8 +163,8 @@ export function formatTimeEstimate (totalSeconds, greaterThanMax, lessThanMin) { symbol = '> ' } - const formattedMin = `${minutes ? minutes + ' min' : ''}` - const formattedSec = `${seconds ? seconds + ' sec' : ''}` + const formattedMin = `${minutes ? `${minutes} min` : ''}` + const formattedSec = `${seconds ? `${seconds} sec` : ''}` const formattedCombined = formattedMin && formattedSec ? `${symbol}${formattedMin} ${formattedSec}` : symbol + [formattedMin, formattedSec].find((t) => t) @@ -199,8 +198,8 @@ export function getRenderableBasicEstimateData (state, gasLimit) { const { showFiatInTestnets } = getPreferences(state) const isMainnet = getIsMainnet(state) - const showFiat = (isMainnet || !!showFiatInTestnets) - const conversionRate = state.metamask.conversionRate + const showFiat = (isMainnet || Boolean(showFiatInTestnets)) + const { conversionRate } = state.metamask const currentCurrency = getCurrentCurrency(state) const { gas: { @@ -253,9 +252,9 @@ export function getRenderableEstimateDataForSmallButtonsFromGWEI (state) { const { showFiatInTestnets } = getPreferences(state) const isMainnet = getIsMainnet(state) - const showFiat = (isMainnet || !!showFiatInTestnets) + const showFiat = (isMainnet || Boolean(showFiatInTestnets)) const gasLimit = state.metamask.send.gasLimit || getCustomGasLimit(state) || '0x5208' - const conversionRate = state.metamask.conversionRate + const { conversionRate } = state.metamask const currentCurrency = getCurrentCurrency(state) const { gas: { diff --git a/ui/app/selectors/permissions.js b/ui/app/selectors/permissions.js index d42081153..bc7bcabe4 100644 --- a/ui/app/selectors/permissions.js +++ b/ui/app/selectors/permissions.js @@ -1,8 +1,8 @@ import { forOwn } from 'lodash' -import { getMetaMaskAccountsOrdered, getOriginOfCurrentTab, getSelectedAddress } from '.' import { CAVEAT_NAMES, } from '../../../app/scripts/controllers/permissions/enums' +import { getMetaMaskAccountsOrdered, getOriginOfCurrentTab, getSelectedAddress } from '.' // selectors @@ -249,7 +249,7 @@ export function getPermissionsForActiveTab (state) { export function getLastConnectedInfo (state) { const { permissionsHistory = {} } = state.metamask return Object.keys(permissionsHistory).reduce((acc, origin) => { - const ethAccountsHistory = JSON.parse(JSON.stringify(permissionsHistory[origin]['eth_accounts'])) + const ethAccountsHistory = JSON.parse(JSON.stringify(permissionsHistory[origin].eth_accounts)) return { ...acc, [origin]: ethAccountsHistory, @@ -261,10 +261,10 @@ export function getPermissionsMetadataHostCounts (state) { const metadata = getPermissionDomainsMetadata(state) return Object.values(metadata).reduce((counts, { host }) => { if (host) { - if (!counts[host]) { - counts[host] = 1 - } else { + if (counts[host]) { counts[host] += 1 + } else { + counts[host] = 1 } } return counts diff --git a/ui/app/selectors/selectors.js b/ui/app/selectors/selectors.js index cfa680186..3789e3854 100644 --- a/ui/app/selectors/selectors.js +++ b/ui/app/selectors/selectors.js @@ -1,6 +1,6 @@ -import { NETWORK_TYPES } from '../helpers/constants/common' import { stripHexPrefix, addHexPrefix } from 'ethereumjs-util' import { createSelector } from 'reselect' +import { NETWORK_TYPES } from '../helpers/constants/common' import { shortenAddress, checksumAddress, @@ -63,11 +63,10 @@ export const getMetaMaskAccounts = createSelector( }, } - } else { - return { - ...selectedAccounts, - [accountID]: account, - } + } + return { + ...selectedAccounts, + [accountID]: account, } }, {}), ) @@ -78,7 +77,7 @@ export function getSelectedAddress (state) { export function getSelectedIdentity (state) { const selectedAddress = getSelectedAddress(state) - const identities = state.metamask.identities + const { identities } = state.metamask return identities[selectedAddress] } @@ -88,7 +87,7 @@ export function getNumberOfAccounts (state) { } export function getNumberOfTokens (state) { - const tokens = state.metamask.tokens + const { tokens } = state.metamask return tokens ? tokens.length : 0 } @@ -119,7 +118,7 @@ export const getMetaMaskAccountsOrdered = createSelector( getMetaMaskAccounts, (keyrings, identities, accounts) => keyrings .reduce((list, keyring) => list.concat(keyring.accounts), []) - .filter((address) => !!identities[address]) + .filter((address) => Boolean(identities[address])) .map((address) => ({ ...identities[address], ...accounts[address] })), ) @@ -157,7 +156,7 @@ export function getAssetImages (state) { } export function getAddressBook (state) { - const network = state.metamask.network + const { network } = state.metamask if (!state.metamask.addressBook[network]) { return [] } @@ -180,7 +179,7 @@ export function accountsWithSendEtherInfoSelector (state) { const identities = getMetaMaskIdentities(state) const accountsWithSendEtherInfo = Object.entries(identities).map(([key, identity]) => { - return Object.assign({}, identity, accounts[key]) + return { ...identity, ...accounts[key] } }) return accountsWithSendEtherInfo @@ -258,7 +257,7 @@ export function isEthereumNetwork (state) { GOERLI, } = NETWORK_TYPES - return [ KOVAN, MAINNET, RINKEBY, ROPSTEN, GOERLI].includes(networkType) + return [KOVAN, MAINNET, RINKEBY, ROPSTEN, GOERLI].includes(networkType) } export function getPreferences ({ metamask }) { diff --git a/ui/app/selectors/send.js b/ui/app/selectors/send.js index 8244983a5..3fcd3e760 100644 --- a/ui/app/selectors/send.js +++ b/ui/app/selectors/send.js @@ -1,4 +1,5 @@ import abi from 'human-standard-token-abi' +import { calcGasTotal } from '../pages/send/send.utils' import { accountsWithSendEtherInfoSelector, getAddressBook, @@ -6,7 +7,6 @@ import { getTargetAccount, getAveragePriceEstimateInHexWEI, } from '.' -import { calcGasTotal } from '../pages/send/send.utils' export function getBlockGasLimit (state) { return state.metamask.currentBlockGasLimit @@ -157,9 +157,8 @@ export function getTitleKey (state) { return 'edit' } else if (isToken) { return 'sendTokens' - } else { - return 'sendETH' } + return 'sendETH' } export function isSendFormInError (state) { diff --git a/ui/app/selectors/tests/custom-gas.test.js b/ui/app/selectors/tests/custom-gas.test.js index 7e3e6c085..6ae6119c4 100644 --- a/ui/app/selectors/tests/custom-gas.test.js +++ b/ui/app/selectors/tests/custom-gas.test.js @@ -52,22 +52,30 @@ describe('custom-gas selectors', function () { describe('getEstimatedGasPrices', function () { it('should return price and time estimates', function () { - const mockState = { gas: { priceAndTimeEstimates: [ - { gasprice: 12, somethingElse: 20 }, - { gasprice: 22, expectedTime: 30 }, - { gasprice: 32, somethingElse: 40 }, - ] } } + const mockState = { + gas: { + priceAndTimeEstimates: [ + { gasprice: 12, somethingElse: 20 }, + { gasprice: 22, expectedTime: 30 }, + { gasprice: 32, somethingElse: 40 }, + ], + }, + } assert.deepEqual(getEstimatedGasPrices(mockState), [12, 22, 32]) }) }) describe('getEstimatedGasTimes', function () { it('should return price and time estimates', function () { - const mockState = { gas: { priceAndTimeEstimates: [ - { somethingElse: 12, expectedTime: 20 }, - { gasPrice: 22, expectedTime: 30 }, - { somethingElse: 32, expectedTime: 40 }, - ] } } + const mockState = { + gas: { + priceAndTimeEstimates: [ + { somethingElse: 12, expectedTime: 20 }, + { gasPrice: 22, expectedTime: 30 }, + { somethingElse: 32, expectedTime: 40 }, + ], + }, + } assert.deepEqual(getEstimatedGasTimes(mockState), [20, 30, 40]) }) }) diff --git a/ui/app/selectors/tests/send.test.js b/ui/app/selectors/tests/send.test.js index d232baf1b..529e03958 100644 --- a/ui/app/selectors/tests/send.test.js +++ b/ui/app/selectors/tests/send.test.js @@ -37,11 +37,11 @@ import { import mockState from './send-selectors-test-data' describe('send selectors', function () { - const tempGlobalEth = Object.assign({}, global.eth) + const tempGlobalEth = { ...global.eth } beforeEach(function () { global.eth = { contract: sinon.stub().returns({ - at: (address) => 'mockAt:' + address, + at: (address) => `mockAt:${address}`, }), } }) @@ -217,9 +217,9 @@ describe('send selectors', function () { }) it('should return null if send token is not set', function () { - const modifiedMetamaskState = Object.assign({}, mockState.metamask, { send: {} }) + const modifiedMetamaskState = { ...mockState.metamask, send: {} } assert.equal( - getSendTokenContract(Object.assign({}, mockState, { metamask: modifiedMetamaskState })), + getSendTokenContract({ ...mockState, metamask: modifiedMetamaskState }), null, ) }) @@ -280,11 +280,12 @@ describe('send selectors', function () { it('should get the selected account balance if the send.from does not exist', function () { const editedMockState = { - metamask: Object.assign({}, mockState.metamask, { + metamask: { + ...mockState.metamask, send: { from: null, }, - }), + }, } assert.equal( getSendFromBalance(editedMockState), @@ -308,11 +309,12 @@ describe('send selectors', function () { it('should return the current account if send.from does not exist', function () { const editedMockState = { - metamask: Object.assign({}, mockState.metamask, { + metamask: { + ...mockState.metamask, send: { from: null, }, - }), + }, } assert.deepEqual( getSendFromObject(editedMockState), @@ -532,7 +534,8 @@ describe('send selectors', function () { editingTransactionId: true, token: {}, }), - ), 'edit') + ), 'edit', + ) }) it('should return the correct key when getSendEditingTransactionId is falsy and getSendToken is truthy', function () { @@ -543,7 +546,8 @@ describe('send selectors', function () { editingTransactionId: false, token: {}, }), - ), 'sendTokens') + ), 'sendTokens', + ) }) it('should return the correct key when getSendEditingTransactionId is falsy and getSendToken is falsy', function () { @@ -554,7 +558,8 @@ describe('send selectors', function () { editingTransactionId: false, token: null, }), - ), 'sendETH') + ), 'sendETH', + ) }) }) }) @@ -571,7 +576,7 @@ describe('send selectors', function () { it('should return true if any of the values of the object returned by getSendErrors are truthy', function () { assert.equal(isSendFormInError( getSendMockState({ - errors: [ true ], + errors: [true], }), ), true) }) @@ -584,7 +589,7 @@ describe('send selectors', function () { ), false) assert.equal(isSendFormInError( getSendMockState({ - errors: [ false ], + errors: [false], }), ), false) }) diff --git a/ui/app/selectors/tests/transactions.test.js b/ui/app/selectors/tests/transactions.test.js index 12a931e81..65f36b3ea 100644 --- a/ui/app/selectors/tests/transactions.test.js +++ b/ui/app/selectors/tests/transactions.test.js @@ -184,7 +184,7 @@ describe('Transaction Selectors', function () { const expectedResult = [ { nonce: '0x0', - transactions: [ tx1 ], + transactions: [tx1], initialTransaction: tx1, primaryTransaction: tx1, hasRetried: false, @@ -192,7 +192,7 @@ describe('Transaction Selectors', function () { }, { nonce: '0x1', - transactions: [ tx2 ], + transactions: [tx2], initialTransaction: tx2, primaryTransaction: tx2, hasRetried: false, @@ -273,7 +273,7 @@ describe('Transaction Selectors', function () { const expectedResult = [ { nonce: submittedTx.txParams.nonce, - transactions: [ submittedTx ], + transactions: [submittedTx], initialTransaction: submittedTx, primaryTransaction: submittedTx, hasRetried: false, @@ -281,7 +281,7 @@ describe('Transaction Selectors', function () { }, { nonce: unapprovedTx.txParams.nonce, - transactions: [ unapprovedTx ], + transactions: [unapprovedTx], initialTransaction: unapprovedTx, primaryTransaction: unapprovedTx, hasRetried: false, @@ -289,7 +289,7 @@ describe('Transaction Selectors', function () { }, { nonce: approvedTx.txParams.nonce, - transactions: [ approvedTx ], + transactions: [approvedTx], initialTransaction: approvedTx, primaryTransaction: approvedTx, hasRetried: false, @@ -305,7 +305,7 @@ describe('Transaction Selectors', function () { const expectedResult = [ { nonce: confirmedTx.txParams.nonce, - transactions: [ confirmedTx ], + transactions: [confirmedTx], initialTransaction: confirmedTx, primaryTransaction: confirmedTx, hasRetried: false, @@ -318,7 +318,7 @@ describe('Transaction Selectors', function () { it('submittedPendingTransactionsSelector', function () { - const expectedResult = [ submittedTx ] + const expectedResult = [submittedTx] assert.deepEqual(submittedPendingTransactionsSelector(state), expectedResult) }) }) diff --git a/ui/app/selectors/transactions.js b/ui/app/selectors/transactions.js index f0d63b115..7d62d4979 100644 --- a/ui/app/selectors/transactions.js +++ b/ui/app/selectors/transactions.js @@ -10,10 +10,10 @@ import { TRANSACTION_TYPE_RETRY, } from '../../../app/scripts/controllers/transactions/enums' import { hexToDecimal } from '../helpers/utils/conversions.util' +import txHelper from '../../lib/tx-helper' import { getSelectedAddress, } from '.' -import txHelper from '../../lib/tx-helper' export const incomingTxListSelector = (state) => { const { showIncomingTransactions } = state.metamask.featureFlags @@ -21,7 +21,7 @@ export const incomingTxListSelector = (state) => { return [] } - const network = state.metamask.network + const { network } = state.metamask const selectedAddress = getSelectedAddress(state) return Object.values(state.metamask.incomingTransactions) .filter(({ metamaskNetworkId, txParams }) => ( diff --git a/ui/app/store/actionConstants.js b/ui/app/store/actionConstants.js index 4a11aa111..ac7cc11a0 100644 --- a/ui/app/store/actionConstants.js +++ b/ui/app/store/actionConstants.js @@ -36,6 +36,7 @@ export const SET_CURRENT_FIAT = 'SET_CURRENT_FIAT' 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' diff --git a/ui/app/store/actions.js b/ui/app/store/actions.js index 49a43da24..543860f5a 100644 --- a/ui/app/store/actions.js +++ b/ui/app/store/actions.js @@ -1,26 +1,26 @@ import abi from 'human-standard-token-abi' import pify from 'pify' +import ethUtil from 'ethereumjs-util' +import log from 'loglevel' import getBuyEthUrl from '../../../app/scripts/lib/buy-eth-url' import { checksumAddress } from '../helpers/utils/util' import { calcTokenBalance, estimateGas } from '../pages/send/send.utils' -import ethUtil from 'ethereumjs-util' 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 log from 'loglevel' import { ENVIRONMENT_TYPE_NOTIFICATION } from '../../../app/scripts/lib/enums' import { hasUnconfirmedTransactions } from '../helpers/utils/confirm-tx.util' import { setCustomGasLimit } from '../ducks/gas/gas.duck' import txHelper from '../../lib/tx-helper' import { getEnvironmentType } from '../../../app/scripts/lib/util' -import * as actionConstants from './actionConstants' import { getPermittedAccountsForCurrentTab, getSelectedAddress, } from '../selectors' import { switchedToUnconnectedAccount } from '../ducks/alerts/unconnected-account' import { getUnconnectedAccountAlertEnabledness } from '../ducks/metamask/metamask' +import * as actionConstants from './actionConstants' let background = null let promisifiedBackground = null @@ -46,7 +46,8 @@ export function tryUnlockMetamask (password) { return new Promise((resolve, reject) => { background.submitPassword(password, (error) => { if (error) { - return reject(error) + reject(error) + return } resolve() @@ -61,7 +62,8 @@ export function tryUnlockMetamask (password) { background.verifySeedPhrase((err) => { if (err) { dispatch(displayWarning(err.message)) - return reject(err) + reject(err) + return } resolve() @@ -87,7 +89,8 @@ export function createNewVaultAndRestore (password, seed) { return new Promise((resolve, reject) => { background.createNewVaultAndRestore(password, seed, (err, _vault) => { if (err) { - return reject(err) + reject(err) + return } vault = _vault resolve() @@ -146,7 +149,8 @@ export function submitPassword (password) { return new Promise((resolve, reject) => { background.submitPassword(password, (error) => { if (error) { - return reject(error) + reject(error) + return } resolve() @@ -158,7 +162,8 @@ export function createNewVault (password) { return new Promise((resolve, reject) => { background.createNewVaultAndKeychain(password, (error) => { if (error) { - return reject(error) + reject(error) + return } resolve(true) @@ -170,7 +175,8 @@ export function verifyPassword (password) { return new Promise((resolve, reject) => { background.verifyPassword(password, (error) => { if (error) { - return reject(error) + reject(error) + return } resolve(true) @@ -182,7 +188,8 @@ export function verifySeedPhrase () { return new Promise((resolve, reject) => { background.verifySeedPhrase((error, seedWords) => { if (error) { - return reject(error) + reject(error) + return } resolve(seedWords) @@ -228,7 +235,8 @@ export function fetchInfoToSync () { background.fetchInfoToSync((err, result) => { if (err) { dispatch(displayWarning(err.message)) - return reject(err) + reject(err) + return } resolve(result) }) @@ -245,10 +253,11 @@ export function resetAccount () { dispatch(hideLoadingIndication()) if (err) { dispatch(displayWarning(err.message)) - return reject(err) + reject(err) + return } - log.info('Transaction history reset for ' + account) + log.info(`Transaction history reset for ${account}`) dispatch(showAccountsPage()) resolve(account) }) @@ -264,9 +273,10 @@ export function removeAccount (address) { await new Promise((resolve, reject) => { background.removeAccount(address, (error, account) => { if (error) { - return reject(error) + reject(error) + return } - return resolve(account) + resolve(account) }) }) await forceUpdateMetamaskState(dispatch) @@ -277,7 +287,7 @@ export function removeAccount (address) { dispatch(hideLoadingIndication()) } - log.info('Account removed: ' + address) + log.info(`Account removed: ${address}`) dispatch(showAccountsPage()) } } @@ -395,11 +405,12 @@ export function unlockHardwareWalletAccount (index, deviceName, hdPath) { if (err) { log.error(err) dispatch(displayWarning(err.message)) - return reject(err) + reject(err) + return } dispatch(hideLoadingIndication()) - return resolve() + resolve() }) }) } @@ -498,8 +509,7 @@ export function decryptMsgInline (decryptedMsgData) { } dispatch(updateMetamaskState(newState)) - decryptedMsgData = newState.unapprovedDecryptMsgs[decryptedMsgData.metamaskId] - return decryptedMsgData + return newState.unapprovedDecryptMsgs[decryptedMsgData.metamaskId] } } @@ -576,7 +586,7 @@ export function signTx (txData) { return (dispatch) => { global.ethQuery.sendTransaction(txData, (err) => { if (err) { - return dispatch(displayWarning(err.message)) + dispatch(displayWarning(err.message)) } }) dispatch(showConfTxPage()) @@ -712,7 +722,7 @@ export function updateSendAmount (amount) { export function updateCustomNonce (value) { return { type: actionConstants.UPDATE_CUSTOM_NONCE, - value: value, + value, } } @@ -776,7 +786,8 @@ const updateMetamaskStateFromBackground = () => { return new Promise((resolve, reject) => { background.getState((error, newState) => { if (error) { - return reject(error) + reject(error) + return } resolve(newState) @@ -795,7 +806,8 @@ export function updateTransaction (txData) { dispatch(txError(err)) dispatch(goHome()) log.error(err.message) - return reject(err) + reject(err) + return } resolve(txData) @@ -823,7 +835,8 @@ export function updateAndApproveTx (txData) { dispatch(txError(err)) dispatch(goHome()) log.error(err.message) - return reject(err) + reject(err) + return } resolve(txData) @@ -975,7 +988,8 @@ export function cancelTx (txData) { return new Promise((resolve, reject) => { background.cancelTransaction(txData.id, (err) => { if (err) { - return reject(err) + reject(err) + return } resolve() @@ -1006,7 +1020,8 @@ export function cancelTxs (txDataList) { const cancellations = txIds.map((id) => new Promise((resolve, reject) => { background.cancelTransaction(id, (err) => { if (err) { - return reject(err) + reject(err) + return } resolve() @@ -1025,7 +1040,8 @@ export function cancelTxs (txDataList) { dispatch(hideLoadingIndication()) if (getEnvironmentType() === ENVIRONMENT_TYPE_NOTIFICATION) { - return global.platform.closeCurrentWindow() + global.platform.closeCurrentWindow() + } } } @@ -1036,9 +1052,11 @@ export function markPasswordForgotten () { await new Promise((resolve, reject) => { return background.markPasswordForgotten((error) => { if (error) { - return reject(error) + reject(error) + return } - return resolve() + resolve() + }) }) } finally { @@ -1130,7 +1148,8 @@ const backgroundSetLocked = () => { return new Promise((resolve, reject) => { background.setLocked((error) => { if (error) { - return reject(error) + reject(error) + return } resolve() }) @@ -1220,7 +1239,8 @@ export function addPermittedAccount (origin, address) { await new Promise((resolve, reject) => { background.addPermittedAccount(origin, address, (error) => { if (error) { - return reject(error) + reject(error) + return } resolve() }) @@ -1234,7 +1254,8 @@ export function removePermittedAccount (origin, address) { await new Promise((resolve, reject) => { background.removePermittedAccount(origin, address, (error) => { if (error) { - return reject(error) + reject(error) + return } resolve() }) @@ -1264,7 +1285,8 @@ export function addToken (address, symbol, decimals, image) { dispatch(hideLoadingIndication()) if (err) { dispatch(displayWarning(err.message)) - return reject(err) + reject(err) + return } dispatch(updateTokens(tokens)) resolve(tokens) @@ -1281,7 +1303,8 @@ export function removeToken (address) { dispatch(hideLoadingIndication()) if (err) { dispatch(displayWarning(err.message)) - return reject(err) + reject(err) + return } dispatch(updateTokens(tokens)) resolve(tokens) @@ -1296,15 +1319,15 @@ export function addTokens (tokens) { return Promise.all(tokens.map(({ address, symbol, decimals }) => ( dispatch(addToken(address, symbol, decimals)) ))) - } else { - return Promise.all( - Object - .entries(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)) + )), + ) + } } @@ -1319,7 +1342,8 @@ export function removeSuggestedTokens () { } dispatch(clearPendingTokens()) if (getEnvironmentType() === ENVIRONMENT_TYPE_NOTIFICATION) { - return global.platform.closeCurrentWindow() + global.platform.closeCurrentWindow() + return } resolve(suggestedTokens) }) @@ -1357,7 +1381,8 @@ export function createCancelTransaction (txId, customGasPrice) { background.createCancelTransaction(txId, customGasPrice, (err, newState) => { if (err) { dispatch(displayWarning(err.message)) - return reject(err) + reject(err) + return } const { currentNetworkTxList } = newState @@ -1380,7 +1405,8 @@ export function createSpeedUpTransaction (txId, customGasPrice, customGasLimit) background.createSpeedUpTransaction(txId, customGasPrice, customGasLimit, (err, newState) => { if (err) { dispatch(displayWarning(err.message)) - return reject(err) + reject(err) + return } const { currentNetworkTxList } = newState @@ -1402,7 +1428,8 @@ export function createRetryTransaction (txId, customGasPrice, customGasLimit) { background.createSpeedUpTransaction(txId, customGasPrice, customGasLimit, (err, newState) => { if (err) { dispatch(displayWarning(err.message)) - return reject(err) + reject(err) + return } const { currentNetworkTxList } = newState @@ -1504,7 +1531,6 @@ export function setRpcTarget (newRpc, chainId, ticker = 'ETH', nickname) { } catch (error) { log.error(error) dispatch(displayWarning('Had a problem changing networks!')) - return } } } @@ -1517,7 +1543,8 @@ export function delRpcTarget (oldRpc) { if (err) { log.error(err) dispatch(displayWarning('Had a problem removing network!')) - return reject(err) + reject(err) + return } resolve() }) @@ -1541,7 +1568,7 @@ export function addToAddressBook (recipient, nickname = '', memo = '') { throw error } if (!set) { - return dispatch(displayWarning('Address book failed to update')) + dispatch(displayWarning('Address book failed to update')) } } } @@ -1570,7 +1597,6 @@ export function hideNetworkDropdown () { } } - export function showModal (payload) { return { type: actionConstants.MODAL_OPEN, @@ -1688,21 +1714,22 @@ export function exportAccount (password, address) { log.error('Error in submitting password.') dispatch(hideLoadingIndication()) dispatch(displayWarning('Incorrect Password.')) - return reject(err) + reject(err) + return } log.debug(`background.exportAccount`) - return background.exportAccount(address, function (err, result) { + background.exportAccount(address, function (err2, result) { dispatch(hideLoadingIndication()) - if (err) { - log.error(err) + if (err2) { + log.error(err2) dispatch(displayWarning('Had a problem exporting the account.')) - return reject(err) + reject(err2) + return } dispatch(showPrivateKey(result)) - - return resolve(result) + resolve(result) }) }) }) @@ -1716,22 +1743,22 @@ export function exportAccounts (password, addresses) { background.submitPassword(password, function (err) { if (err) { log.error('Error in submitting password.') - return reject(err) + reject(err) + return } log.debug(`background.exportAccounts`) - const accountPromises = addresses.map((address) => - new Promise( - (resolve, reject) => background.exportAccount(address, function (err, result) { - if (err) { - log.error(err) - dispatch(displayWarning('Had a problem exporting the account.')) - return reject(err) - } - return resolve(result) - }), - ), - ) - return resolve(Promise.all(accountPromises)) + const accountPromises = addresses.map((address) => new Promise( + (resolve2, reject2) => background.exportAccount(address, function (err2, result) { + if (err2) { + log.error(err2) + dispatch(displayWarning('Had a problem exporting the account.')) + reject2(err2) + return + } + resolve2(result) + }), + )) + resolve(Promise.all(accountPromises)) }) }) } @@ -1755,20 +1782,26 @@ export function setAccountLabel (account, label) { if (err) { dispatch(displayWarning(err.message)) - return reject(err) + reject(err) + return } dispatch({ type: actionConstants.SET_ACCOUNT_LABEL, value: { account, label }, }) - resolve(account) }) }) } } +export function clearAccountDetails () { + return { + type: actionConstants.CLEAR_ACCOUNT_DETAILS, + } +} + export function showSendTokenPage () { return { type: actionConstants.SHOW_SEND_TOKEN_PAGE, @@ -1793,7 +1826,8 @@ export function setFeatureFlag (feature, activated, notificationType) { dispatch(hideLoadingIndication()) if (err) { dispatch(displayWarning(err.message)) - return reject(err) + reject(err) + return } dispatch(updateFeatureFlags(updatedFeatureFlags)) notificationType && dispatch(showModal({ name: notificationType })) @@ -1819,7 +1853,8 @@ export function setPreference (preference, value) { if (err) { dispatch(displayWarning(err.message)) - return reject(err) + reject(err) + return } dispatch(updatePreferences(updatedPreferences)) @@ -1912,14 +1947,14 @@ export function setParticipateInMetaMetrics (val) { log.debug(err) if (err) { dispatch(displayWarning(err.message)) - return reject(err) + reject(err) + return } dispatch({ type: actionConstants.SET_PARTICIPATE_IN_METAMETRICS, value: val, }) - resolve([val, metaMetricsId]) }) }) @@ -1933,14 +1968,14 @@ export function setMetaMetricsSendCount (val) { background.setMetaMetricsSendCount(val, (err) => { if (err) { dispatch(displayWarning(err.message)) - return reject(err) + reject(err) + return } dispatch({ type: actionConstants.SET_METAMETRICS_SEND_COUNT, value: val, }) - resolve(val) }) }) @@ -1954,7 +1989,7 @@ export function setUseBlockie (val) { background.setUseBlockie(val, (err) => { dispatch(hideLoadingIndication()) if (err) { - return dispatch(displayWarning(err.message)) + dispatch(displayWarning(err.message)) } }) dispatch({ @@ -1971,7 +2006,7 @@ export function setUseNonceField (val) { background.setUseNonceField(val, (err) => { dispatch(hideLoadingIndication()) if (err) { - return dispatch(displayWarning(err.message)) + dispatch(displayWarning(err.message)) } }) dispatch({ @@ -1988,7 +2023,7 @@ export function setUsePhishDetect (val) { background.setUsePhishDetect(val, (err) => { dispatch(hideLoadingIndication()) if (err) { - return dispatch(displayWarning(err.message)) + dispatch(displayWarning(err.message)) } }) } @@ -2001,7 +2036,8 @@ export function setIpfsGateway (val) { background.setIpfsGateway(val, (err) => { dispatch(hideLoadingIndication()) if (err) { - return dispatch(displayWarning(err.message)) + dispatch(displayWarning(err.message)) + } else { dispatch({ type: actionConstants.SET_IPFS_GATEWAY, @@ -2022,7 +2058,8 @@ export function updateCurrentLocale (key) { background.setCurrentLocale(key, (err, textDirection) => { if (err) { dispatch(hideLoadingIndication()) - return dispatch(displayWarning(err.message)) + dispatch(displayWarning(err.message)) + return } switchDirection(textDirection) dispatch(setCurrentLocale(key, localeMessages)) @@ -2086,9 +2123,10 @@ export function rejectPermissionsRequest (requestId) { background.rejectPermissionsRequest(requestId, (err) => { if (err) { dispatch(displayWarning(err.message)) - return reject(err) + reject(err) + return } - return forceUpdateMetamaskState(dispatch) + forceUpdateMetamaskState(dispatch) .then(resolve) .catch(reject) }) @@ -2119,7 +2157,8 @@ export function setFirstTimeFlowType (type) { log.debug(`background.setFirstTimeFlowType`) background.setFirstTimeFlowType(type, (err) => { if (err) { - return dispatch(displayWarning(err.message)) + dispatch(displayWarning(err.message)) + } }) dispatch({ @@ -2147,7 +2186,8 @@ export function setLastActiveTime () { return (dispatch) => { background.setLastActiveTime((err) => { if (err) { - return dispatch(displayWarning(err.message)) + dispatch(displayWarning(err.message)) + } }) } @@ -2201,9 +2241,7 @@ export function getContractMethodData (data = '') { return getMethodDataAsync(fourBytePrefix) .then(({ name, params }) => { dispatch(loadingMethodDataFinished()) - background.addKnownMethodData(fourBytePrefix, { name, params }) - return { name, params } }) } @@ -2236,7 +2274,6 @@ export function getTokenParams (tokenAddress) { dispatch(loadingTokenParamsStarted()) log.debug(`loadingTokenParams`) - return fetchSymbolAndDecimals(tokenAddress, existingTokens) .then(({ symbol, decimals }) => { dispatch(addToken(tokenAddress, symbol, Number(decimals))) @@ -2252,9 +2289,10 @@ export function setSeedPhraseBackedUp (seedPhraseBackupState) { background.setSeedPhraseBackedUp(seedPhraseBackupState, (err) => { if (err) { dispatch(displayWarning(err.message)) - return reject(err) + reject(err) + return } - return forceUpdateMetamaskState(dispatch) + forceUpdateMetamaskState(dispatch) .then(resolve) .catch(reject) }) @@ -2268,7 +2306,8 @@ export function initializeThreeBox () { background.initializeThreeBox((err) => { if (err) { dispatch(displayWarning(err.message)) - return reject(err) + reject(err) + return } resolve() }) @@ -2282,7 +2321,8 @@ export function setShowRestorePromptToFalse () { background.setShowRestorePromptToFalse((err) => { if (err) { dispatch(displayWarning(err.message)) - return reject(err) + reject(err) + return } resolve() }) @@ -2296,7 +2336,8 @@ export function turnThreeBoxSyncingOn () { background.turnThreeBoxSyncingOn((err) => { if (err) { dispatch(displayWarning(err.message)) - return reject(err) + reject(err) + return } resolve() }) @@ -2310,7 +2351,8 @@ export function restoreFromThreeBox (accountAddress) { background.restoreFromThreeBox(accountAddress, (err) => { if (err) { dispatch(displayWarning(err.message)) - return reject(err) + reject(err) + return } resolve() }) @@ -2324,7 +2366,8 @@ export function getThreeBoxLastUpdated () { background.getThreeBoxLastUpdated((err, lastUpdated) => { if (err) { dispatch(displayWarning(err.message)) - return reject(err) + reject(err) + return } resolve(lastUpdated) }) @@ -2338,7 +2381,8 @@ export function setThreeBoxSyncingPermission (threeBoxSyncingAllowed) { background.setThreeBoxSyncingPermission(threeBoxSyncingAllowed, (err) => { if (err) { dispatch(displayWarning(err.message)) - return reject(err) + reject(err) + return } resolve() }) @@ -2368,7 +2412,8 @@ export function getNextNonce () { background.getNextNonce(address, (err, nextNonce) => { if (err) { dispatch(displayWarning(err.message)) - return reject(err) + reject(err) + return } dispatch(setNextNonce(nextNonce)) resolve(nextNonce) @@ -2412,7 +2457,6 @@ export function setCurrentWindowTab (currentWindowTab) { } } - export function getCurrentWindowTab () { return async (dispatch) => { const currentWindowTab = await global.platform.currentTab() diff --git a/ui/index.js b/ui/index.js index bc61913b2..9e777ed94 100644 --- a/ui/index.js +++ b/ui/index.js @@ -3,14 +3,14 @@ import log from 'loglevel' import { clone } from 'lodash' import React from 'react' import { render } from 'react-dom' -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 { getEnvironmentType } from '../app/scripts/lib/util' import { ALERT_TYPES } from '../app/scripts/controllers/alert' import { SENTRY_STATE } from '../app/scripts/lib/setupSentry' import { ENVIRONMENT_TYPE_POPUP } from '../app/scripts/lib/enums' +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' import { getPermittedAccountsForCurrentTab, getSelectedAddress } from './app/selectors' @@ -28,7 +28,8 @@ export default function launchMetamaskUi (opts, cb) { // check if we are unlocked first backgroundConnection.getState(function (err, metamaskState) { if (err) { - return cb(err) + cb(err) + return } startApp(metamaskState, backgroundConnection, opts) .then((store) => { @@ -74,7 +75,7 @@ async function startApp (metamaskState, backgroundConnection, opts) { } if (getEnvironmentType() === ENVIRONMENT_TYPE_POPUP) { - const origin = draftInitialState.activeTab.origin + const { origin } = draftInitialState.activeTab const permittedAccountsForCurrentTab = getPermittedAccountsForCurrentTab(draftInitialState) const selectedAddress = getSelectedAddress(draftInitialState) const unconnectedAccountAlertShownOrigins = getUnconnectedAccountAlertShown(draftInitialState) @@ -111,8 +112,8 @@ async function startApp (metamaskState, backgroundConnection, opts) { })) } - backgroundConnection.on('update', function (metamaskState) { - store.dispatch(actions.updateMetamaskState(metamaskState)) + backgroundConnection.on('update', function (state) { + store.dispatch(actions.updateMetamaskState(state)) }) // global metamask api - used by tooling @@ -188,7 +189,8 @@ window.logStateString = function (cb) { const state = window.getCleanAppState() global.platform.getPlatformInfo((err, platform) => { if (err) { - return cb(err) + cb(err) + return } state.platform = platform const stateString = JSON.stringify(state, null, 2) diff --git a/ui/lib/account-link.js b/ui/lib/account-link.js index 1f9ba293e..8427d41ad 100644 --- a/ui/lib/account-link.js +++ b/ui/lib/account-link.js @@ -1,33 +1,24 @@ export default function getAccountLink (address, network, rpcPrefs) { if (rpcPrefs && rpcPrefs.blockExplorerUrl) { - return `${rpcPrefs.blockExplorerUrl.replace(/\/+$/, '')}/address/${address}` + return `${rpcPrefs.blockExplorerUrl.replace(/\/+$/u, '')}/address/${address}` } + // eslint-disable-next-line radix const net = parseInt(network) - let link switch (net) { case 1: // main net - link = `https://etherscan.io/address/${address}` - break + return `https://etherscan.io/address/${address}` case 2: // morden test net - link = `https://morden.etherscan.io/address/${address}` - break + return `https://morden.etherscan.io/address/${address}` case 3: // ropsten test net - link = `https://ropsten.etherscan.io/address/${address}` - break + return `https://ropsten.etherscan.io/address/${address}` case 4: // rinkeby test net - link = `https://rinkeby.etherscan.io/address/${address}` - break + return `https://rinkeby.etherscan.io/address/${address}` case 42: // kovan test net - link = `https://kovan.etherscan.io/address/${address}` - break + return `https://kovan.etherscan.io/address/${address}` case 5: // goerli test net - link = `https://goerli.etherscan.io/address/${address}` - break + return `https://goerli.etherscan.io/address/${address}` default: - link = '' - break + return '' } - - return link } diff --git a/ui/lib/icon-factory.js b/ui/lib/icon-factory.js index 077604195..19489819a 100644 --- a/ui/lib/icon-factory.js +++ b/ui/lib/icon-factory.js @@ -1,7 +1,8 @@ -let iconFactory import { isValidAddress } from 'ethereumjs-util' -import { checksumAddress } from '../app/helpers/utils/util' import contractMap from 'eth-contract-metadata' +import { checksumAddress } from '../app/helpers/utils/util' + +let iconFactory export default function iconFactoryGenerator (jazzicon) { if (!iconFactory) { diff --git a/ui/lib/tx-helper.js b/ui/lib/tx-helper.js index 03a7b3e1e..fcb264c0c 100644 --- a/ui/lib/tx-helper.js +++ b/ui/lib/tx-helper.js @@ -1,5 +1,5 @@ -import { valuesFor } from '../app/helpers/utils/util' import log from 'loglevel' +import { valuesFor } from '../app/helpers/utils/util' export default function txHelper (unapprovedTxs, unapprovedMsgs, personalMsgs, decryptMsgs, encryptionPublicKeyMsgs, typedMessages, network) { log.debug('tx-helper called with params:') diff --git a/ui/lib/webcam-utils.js b/ui/lib/webcam-utils.js index ef7da9496..c9b6c5503 100644 --- a/ui/lib/webcam-utils.js +++ b/ui/lib/webcam-utils.js @@ -25,11 +25,10 @@ class WebcamUtils { permissions: hasWebcamPermissions, environmentReady, } - } else { - 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 } } diff --git a/yarn.lock b/yarn.lock index 88f90db9f..2683bd446 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1730,10 +1730,10 @@ web3 "^0.20.7" web3-provider-engine "^15.0.4" -"@metamask/eslint-config@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@metamask/eslint-config/-/eslint-config-1.1.0.tgz#03c6fbec8ba3d95fa017d8b98ab5d0701f7458a4" - integrity sha512-yFFHIxFn3cBd9brIW/+0fJGq16hT0xUyElP0YxiZHaY7j2T/l+X/414L9kqBOuPfPa9bIKulIcJJOfcrMJZp9w== +"@metamask/eslint-config@^3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@metamask/eslint-config/-/eslint-config-3.1.0.tgz#8412ddd3f660748598902fd8dbef6fadc060f25e" + integrity sha512-He/zV0Cb5W421mEQveaqSegLarONJbJPReJppQkwhi239PCE7j+6eRji/j2Unwq8TBuOlgQtqL49+dtvks+lPQ== "@metamask/eth-ledger-bridge-keyring@^0.2.6": version "0.2.6" @@ -1823,6 +1823,13 @@ "@nodelib/fs.scandir" "2.1.3" fastq "^1.6.0" +"@npmcli/move-file@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@npmcli/move-file/-/move-file-1.0.1.tgz#de103070dac0f48ce49cf6693c23af59c0f70464" + integrity sha512-Uv6h1sT+0DrblvIrolFtbvM1FgWm+/sy4B3pvLp67Zys+thcukzS5ekn7HsZFGpWP4Q3fYJCljbWQE/XivMRLw== + dependencies: + mkdirp "^1.0.4" + "@popperjs/core@^2.4.0": version "2.4.0" resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.4.0.tgz#0e1bdf8d021e7ea58affade33d9d607e11365915" @@ -2552,6 +2559,11 @@ resolved "https://registry.yarnpkg.com/@types/is-function/-/is-function-1.0.0.tgz#1b0b819b1636c7baf0d6785d030d12edf70c3e83" integrity sha512-iTs9HReBu7evG77Q4EC8hZnqRt57irBDkK9nvmHroiOIVwYMQc4IvYvdRgwKfYepunIY7Oh/dBuuld+Gj9uo6w== +"@types/json-schema@^7.0.4": + version "7.0.5" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.5.tgz#dcce4430e64b443ba8945f0290fb564ad5bac6dd" + integrity sha512-7+2BITlgjgDhH0vvwZU/HZJVyk+2XUlvxXe8dFMedNX/aMkaOq++rMAFXc0tM7ij15QaWlbdQASBR9dihi+bDQ== + "@types/json5@^0.0.29": version "0.0.29" resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" @@ -3323,22 +3335,12 @@ ajv@^5.1.0: fast-json-stable-stringify "^2.0.0" json-schema-traverse "^0.3.0" -ajv@^6.1.0: - version "6.10.0" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.0.tgz#90d0d54439da587cd7e843bfb7045f50bd22bdf1" - integrity sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg== +ajv@^6.1.0, ajv@^6.10.0, ajv@^6.12.2, ajv@^6.9.1: + version "6.12.3" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.3.tgz#18c5af38a111ddeb4f2697bd78d68abc1cabd706" + integrity sha512-4K0cK3L1hsqk9xIb2z9vs/XU+PGJZ9PNpJRDS9YLzmNdX6jmVPfamLvTJr0aDAusnHyCHO6MjzlkAsgtqp9teA== dependencies: - fast-deep-equal "^2.0.1" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.4.1" - uri-js "^4.2.2" - -ajv@^6.10.0, ajv@^6.9.1: - version "6.10.1" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.1.tgz#ebf8d3af22552df9dd049bfbe50cc2390e823593" - integrity sha512-w1YQaVGNC6t2UCPjEawK/vo/dG8OOrVtUmhBT1uJJYxbl5kU2Tj3v6LGqBcsysN1yhuCStJCCA3GqdvKY8sqXQ== - dependencies: - fast-deep-equal "^2.0.1" + fast-deep-equal "^3.1.1" fast-json-stable-stringify "^2.0.0" json-schema-traverse "^0.4.1" uri-js "^4.2.2" @@ -6056,27 +6058,6 @@ cacache@^12.0.2: unique-filename "^1.1.1" y18n "^4.0.0" -cacache@^12.0.3: - version "12.0.4" - resolved "https://registry.yarnpkg.com/cacache/-/cacache-12.0.4.tgz#668bcbd105aeb5f1d92fe25570ec9525c8faa40c" - integrity sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ== - dependencies: - bluebird "^3.5.5" - chownr "^1.1.1" - figgy-pudding "^3.5.1" - glob "^7.1.4" - graceful-fs "^4.1.15" - infer-owner "^1.0.3" - lru-cache "^5.1.1" - mississippi "^3.0.0" - mkdirp "^0.5.1" - move-concurrently "^1.0.1" - promise-inflight "^1.0.1" - rimraf "^2.6.3" - ssri "^6.0.1" - unique-filename "^1.1.1" - y18n "^4.0.0" - cacache@^13.0.1: version "13.0.1" resolved "https://registry.yarnpkg.com/cacache/-/cacache-13.0.1.tgz#a8000c21697089082f85287a1aec6e382024a71c" @@ -6101,6 +6082,29 @@ cacache@^13.0.1: ssri "^7.0.0" unique-filename "^1.1.1" +cacache@^15.0.4: + version "15.0.5" + resolved "https://registry.yarnpkg.com/cacache/-/cacache-15.0.5.tgz#69162833da29170d6732334643c60e005f5f17d0" + integrity sha512-lloiL22n7sOjEEXdL8NAjTgv9a1u43xICE9/203qonkZUCj5X1UEWIdf2/Y0d6QcCtMzbKQyhrcDbdvlZTs/+A== + dependencies: + "@npmcli/move-file" "^1.0.1" + chownr "^2.0.0" + fs-minipass "^2.0.0" + glob "^7.1.4" + infer-owner "^1.0.4" + lru-cache "^6.0.0" + minipass "^3.1.1" + minipass-collect "^1.0.2" + minipass-flush "^1.0.5" + minipass-pipeline "^1.2.2" + mkdirp "^1.0.3" + p-map "^4.0.0" + promise-inflight "^1.0.1" + rimraf "^3.0.2" + ssri "^8.0.0" + tar "^6.0.2" + unique-filename "^1.1.1" + cache-base@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" @@ -6543,6 +6547,11 @@ chownr@^1.1.2: resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.3.tgz#42d837d5239688d55f303003a508230fa6727142" integrity sha512-i70fVHhmV3DtTl6nqvZOnIjbY0Pe4kAUjwHj8z0zAdgBtYrJyYwLKCCuRBQ5ppkyL0AkN7HKRnETdmdp1zqNXw== +chownr@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" + integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== + chrome-trace-event@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz#234090ee97c7d4ad1a2c4beae27505deffc608a4" @@ -7262,23 +7271,22 @@ copy-to-clipboard@^3.0.8: dependencies: toggle-selection "^1.0.3" -copy-webpack-plugin@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-5.1.1.tgz#5481a03dea1123d88a988c6ff8b78247214f0b88" - integrity sha512-P15M5ZC8dyCjQHWwd4Ia/dm0SgVvZJMYeykVIVYXbGyqO4dWB5oyPHp9i7wjwo5LhtlhKbiBCdS2NvM07Wlybg== +copy-webpack-plugin@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-6.0.3.tgz#2b3d2bfc6861b96432a65f0149720adbd902040b" + integrity sha512-q5m6Vz4elsuyVEIUXr7wJdIdePWTubsqVbEMvf1WQnHGv0Q+9yPRu7MtYFPt+GBOXRav9lvIINifTQ1vSCs+eA== dependencies: - cacache "^12.0.3" - find-cache-dir "^2.1.0" - glob-parent "^3.1.0" - globby "^7.1.1" - is-glob "^4.0.1" - loader-utils "^1.2.3" - minimatch "^3.0.4" + cacache "^15.0.4" + fast-glob "^3.2.4" + find-cache-dir "^3.3.1" + glob-parent "^5.1.1" + globby "^11.0.1" + loader-utils "^2.0.0" normalize-path "^3.0.0" - p-limit "^2.2.1" - schema-utils "^1.0.0" - serialize-javascript "^2.1.2" - webpack-log "^2.0.0" + p-limit "^3.0.1" + schema-utils "^2.7.0" + serialize-javascript "^4.0.0" + webpack-sources "^1.4.3" core-js-compat@^3.1.1: version "3.1.3" @@ -8653,13 +8661,6 @@ dir-glob@2.0.0: arrify "^1.0.1" path-type "^3.0.0" -dir-glob@^2.0.0: - version "2.2.2" - resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-2.2.2.tgz#fa09f0694153c8918b18ba0deafae94769fc50c4" - integrity sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw== - dependencies: - path-type "^3.0.0" - dir-glob@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" @@ -11154,6 +11155,11 @@ fast-deep-equal@^2.0.1: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= +fast-deep-equal@^3.1.1: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + fast-future@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/fast-future/-/fast-future-1.0.2.tgz#8435a9aaa02d79248d17d704e76259301d99280a" @@ -11171,7 +11177,7 @@ fast-glob@^2.0.2: merge2 "^1.2.3" micromatch "^3.1.10" -fast-glob@^3.0.3, fast-glob@^3.1.1, fast-glob@^3.2.2: +fast-glob@^3.0.3, fast-glob@^3.1.1, fast-glob@^3.2.2, fast-glob@^3.2.4: version "3.2.4" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.4.tgz#d20aefbf99579383e7f3cc66529158c9b98554d3" integrity sha512-kr/Oo6PX51265qeuCYsyGypiO5uJFgBS0jksyG7FUeCyQzNwYnzrNIMR1NXfkZXsMYXYLRAHgISHBz8gQcxKHQ== @@ -11488,13 +11494,13 @@ find-cache-dir@^2.0.0, find-cache-dir@^2.1.0: make-dir "^2.0.0" pkg-dir "^3.0.0" -find-cache-dir@^3.0.0, find-cache-dir@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.2.0.tgz#e7fe44c1abc1299f516146e563108fd1006c1874" - integrity sha512-1JKclkYYsf1q9WIJKLZa9S9muC+08RIjzAlLrK4QcYLJMS6mk9yombQ9qf+zJ7H9LS800k0s44L4sDq9VYzqyg== +find-cache-dir@^3.0.0, find-cache-dir@^3.2.0, find-cache-dir@^3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.1.tgz#89b33fad4a4670daa94f855f7fbe31d6d84fe880" + integrity sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ== dependencies: commondir "^1.0.1" - make-dir "^3.0.0" + make-dir "^3.0.2" pkg-dir "^4.1.0" find-root@^1.1.0: @@ -12303,10 +12309,10 @@ glob-parent@^3.0.1, glob-parent@^3.1.0: is-glob "^3.1.0" path-dirname "^1.0.0" -glob-parent@^5.0.0, glob-parent@^5.1.0, glob-parent@~5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.0.tgz#5f4c1d1e748d30cd73ad2944b3577a81b081e8c2" - integrity sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw== +glob-parent@^5.0.0, glob-parent@^5.1.0, glob-parent@^5.1.1, glob-parent@~5.1.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229" + integrity sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ== dependencies: is-glob "^4.0.1" @@ -12567,18 +12573,6 @@ globby@^6.1.0: pify "^2.0.0" pinkie-promise "^2.0.0" -globby@^7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/globby/-/globby-7.1.1.tgz#fb2ccff9401f8600945dfada97440cca972b8680" - integrity sha1-+yzP+UAfhgCUXfral0QMypcrhoA= - dependencies: - array-union "^1.0.1" - dir-glob "^2.0.0" - glob "^7.1.2" - ignore "^3.3.5" - pify "^3.0.0" - slash "^1.0.0" - globjoin@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/globjoin/-/globjoin-0.1.4.tgz#2f4494ac8919e3767c5cbb691e9f463324285d43" @@ -15523,13 +15517,13 @@ jed@1.1.1: resolved "https://registry.yarnpkg.com/jed/-/jed-1.1.1.tgz#7a549bbd9ffe1585b0cd0a191e203055bee574b4" integrity sha1-elSbvZ/+FYWwzQoZHiAwVb7ldLQ= -jest-worker@^24.9.0: - version "24.9.0" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-24.9.0.tgz#5dbfdb5b2d322e98567898238a9697bcce67b3e5" - integrity sha512-51PE4haMSXcHohnSMdM42anbvZANYTqMrr52tVKPqqsPJMzoP6FYYDVqahX/HrAoKEKz3uUPzSvKs9A3qR4iVw== +jest-worker@^25.4.0: + version "25.5.0" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-25.5.0.tgz#2611d071b79cea0f43ee57a3d118593ac1547db1" + integrity sha512-/dsSmUkIy5EBGfv/IjjqmFxrNAUpBERfGs1oHROyD7yxjG/w+t0GOJDX8O1k32ySmd7+a5IhnJU2qQFcJ4n1vw== dependencies: merge-stream "^2.0.0" - supports-color "^6.1.0" + supports-color "^7.0.0" jmespath@^0.15.0: version "0.15.0" @@ -17095,6 +17089,15 @@ loader-utils@^1.0.1, loader-utils@^1.0.2, loader-utils@^1.1.0: emojis-list "^2.0.0" json5 "^0.5.0" +loader-utils@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.0.tgz#e4cace5b816d425a166b5f097e10cd12b36064b0" + integrity sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ== + dependencies: + big.js "^5.2.2" + emojis-list "^3.0.0" + json5 "^2.1.2" + locale-currency@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/locale-currency/-/locale-currency-0.0.1.tgz#c9e15a22ff575b4b4bb947a4bf92ac236bd1fe9b" @@ -17538,6 +17541,13 @@ lru-cache@^5.1.1: dependencies: yallist "^3.0.2" +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + lru-queue@0.1: version "0.1.0" resolved "https://registry.yarnpkg.com/lru-queue/-/lru-queue-0.1.0.tgz#2738bd9f0d3cf4f84490c5736c48699ac632cda3" @@ -17596,10 +17606,10 @@ make-dir@^2.0.0: pify "^4.0.1" semver "^5.6.0" -make-dir@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.0.0.tgz#1b5f39f6b9270ed33f9f054c5c0f84304989f801" - integrity sha512-grNJDhb8b1Jm1qeqW5R/O63wUo4UXo2v2HMic6YT9i/HBlF93S8jkMgH7yugvY9ABDShH4VZMn8I+U8+fCNegw== +make-dir@^3.0.0, make-dir@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" + integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== dependencies: semver "^6.0.0" @@ -18215,6 +18225,14 @@ minizlib@^1.2.1: dependencies: minipass "^2.2.1" +minizlib@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.0.tgz#fd52c645301ef09a63a2c209697c294c6ce02cf3" + integrity sha512-EzTZN/fjSvifSX0SlqUERCN39o6T40AMarPbv0MrarSFtIITCBh7bi+dU8nxGFHuqs9jdIAeoYoKuQAAASsPPA== + dependencies: + minipass "^3.0.0" + yallist "^4.0.0" + mississippi@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-3.0.0.tgz#ea0a3291f97e0b5e8776b363d5f0a12d94c67022" @@ -18266,6 +18284,11 @@ mkdirp@*, mkdirp@0.5.5, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@^ dependencies: minimist "^1.2.5" +mkdirp@^1.0.3, mkdirp@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" + integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== + mocha@^7.2.0: version "7.2.0" resolved "https://registry.yarnpkg.com/mocha/-/mocha-7.2.0.tgz#01cc227b00d875ab1eed03a75106689cfed5a604" @@ -19913,13 +19936,20 @@ p-limit@^2.0.0, p-limit@^2.2.0: dependencies: p-try "^2.0.0" -p-limit@^2.2.1: +p-limit@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== dependencies: p-try "^2.0.0" +p-limit@^3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.0.2.tgz#1664e010af3cadc681baafd3e2a437be7b0fb5fe" + integrity sha512-iwqZSOoWIW+Ew4kAGUlN16J4M7OB3ysMLSZtnhmqx7njIHFPlxWBX8xo3lVTyFVq6mI/lL9qt2IsN1sHwaxJkg== + dependencies: + p-try "^2.0.0" + p-locate@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" @@ -19965,6 +19995,13 @@ p-map@^3.0.0: dependencies: aggregate-error "^3.0.0" +p-map@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" + integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ== + dependencies: + aggregate-error "^3.0.0" + p-map@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/p-map/-/p-map-1.1.1.tgz#05f5e4ae97a068371bc2a5cc86bfbdbc19c4ae7a" @@ -23291,10 +23328,10 @@ rimraf@^2.6.3, rimraf@^2.7.1: dependencies: glob "^7.1.3" -rimraf@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.1.tgz#48d3d4cb46c80d388ab26cd61b1b466ae9ae225a" - integrity sha512-IQ4ikL8SjBiEDZfk+DFVwqRK8md24RWMEJkdSlgNLkyyAImcjf8SWvU1qFMDOb4igBClbTQ/ugPqXcRwdFTxZw== +rimraf@^3.0.0, rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== dependencies: glob "^7.1.3" @@ -23627,12 +23664,13 @@ schema-utils@^1.0.0: ajv-errors "^1.0.0" ajv-keywords "^3.1.0" -schema-utils@^2.0.1, schema-utils@^2.5.0, schema-utils@^2.6.0, schema-utils@^2.6.1, schema-utils@^2.6.4: - version "2.6.4" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.6.4.tgz#a27efbf6e4e78689d91872ee3ccfa57d7bdd0f53" - integrity sha512-VNjcaUxVnEeun6B2fiiUDjXXBtD4ZSH7pdbfIu1pOFwgptDPLMo/z9jr4sUfsjFVPqDCEin/F7IYlq7/E6yDbQ== +schema-utils@^2.0.1, schema-utils@^2.5.0, schema-utils@^2.6.0, schema-utils@^2.6.4, schema-utils@^2.6.6, schema-utils@^2.7.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.0.tgz#17151f76d8eae67fbbf77960c33c676ad9f4efc7" + integrity sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A== dependencies: - ajv "^6.10.2" + "@types/json-schema" "^7.0.4" + ajv "^6.12.2" ajv-keywords "^3.4.1" scope-analyzer@^2.0.1: @@ -23845,10 +23883,12 @@ serialize-error@^7.0.1: dependencies: type-fest "^0.13.1" -serialize-javascript@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-2.1.2.tgz#ecec53b0e0317bdc95ef76ab7074b7384785fa61" - integrity sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ== +serialize-javascript@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-4.0.0.tgz#b525e1238489a5ecfc42afacc3fe99e666f4b1aa" + integrity sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw== + dependencies: + randombytes "^2.1.0" serve-favicon@^2.5.0: version "2.5.0" @@ -24666,6 +24706,13 @@ ssri@^7.0.0: figgy-pudding "^3.5.1" minipass "^3.1.1" +ssri@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/ssri/-/ssri-8.0.0.tgz#79ca74e21f8ceaeddfcb4b90143c458b8d988808" + integrity sha512-aq/pz989nxVYwn16Tsbj1TqFpD5LLrQxHf5zaHuieFV+R0Bbr4y8qUsOA45hXT/N4/9UNXTarBjnjVmjSOVaAA== + dependencies: + minipass "^3.1.1" + stable@^0.1.8, stable@~0.1.8: version "0.1.8" resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" @@ -25362,7 +25409,7 @@ supports-color@^6.1.0: dependencies: has-flag "^3.0.0" -supports-color@^7.1.0: +supports-color@^7.0.0, supports-color@^7.1.0: version "7.1.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.1.0.tgz#68e32591df73e25ad1c4b49108a2ec507962bfd1" integrity sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g== @@ -25620,6 +25667,18 @@ tar@^4.0.2: safe-buffer "^5.1.2" yallist "^3.0.3" +tar@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/tar/-/tar-6.0.2.tgz#5df17813468a6264ff14f766886c622b84ae2f39" + integrity sha512-Glo3jkRtPcvpDlAs/0+hozav78yoXKFr+c4wgw62NNMO3oo4AaJdCo21Uu7lcwr55h39W2XD1LMERc64wtbItg== + dependencies: + chownr "^2.0.0" + fs-minipass "^2.0.0" + minipass "^3.0.0" + minizlib "^2.1.0" + mkdirp "^1.0.3" + yallist "^4.0.0" + tarn@^1.1.4: version "1.1.5" resolved "https://registry.yarnpkg.com/tarn/-/tarn-1.1.5.tgz#7be88622e951738b9fa3fb77477309242cdddc2d" @@ -25694,35 +25753,36 @@ term-size@^2.1.0: integrity sha512-UqvQSch04R+69g4RDhrslmGvGL3ucDRX/U+snYW0Mab4uCAyKSndUksaoqlJ81QKSpRnIsuOYQCbC2ZWx2896A== terser-webpack-plugin@^1.4.3: - version "1.4.3" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.4.3.tgz#5ecaf2dbdc5fb99745fd06791f46fc9ddb1c9a7c" - integrity sha512-QMxecFz/gHQwteWwSo5nTc6UaICqN1bMedC5sMtUc7y3Ha3Q8y6ZO0iCR8pq4RJC8Hjf0FEPEHZqcMB/+DFCrA== + version "1.4.5" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz#a217aefaea330e734ffacb6120ec1fa312d6040b" + integrity sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw== dependencies: cacache "^12.0.2" find-cache-dir "^2.1.0" is-wsl "^1.1.0" schema-utils "^1.0.0" - serialize-javascript "^2.1.2" + serialize-javascript "^4.0.0" source-map "^0.6.1" terser "^4.1.2" webpack-sources "^1.4.0" worker-farm "^1.7.0" terser-webpack-plugin@^2.1.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-2.3.2.tgz#6d3d1b0590c8f729bfbaeb7fb2528b8b62db4c74" - integrity sha512-SmvB/6gtEPv+CJ88MH5zDOsZdKXPS/Uzv2//e90+wM1IHFUhsguPKEILgzqrM1nQ4acRXN/SV4Obr55SXC+0oA== + version "2.3.8" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-2.3.8.tgz#894764a19b0743f2f704e7c2a848c5283a696724" + integrity sha512-/fKw3R+hWyHfYx7Bv6oPqmk4HGQcrWLtV3X6ggvPuwPNHSnzvVV51z6OaaCOus4YLjutYGOz3pEpbhe6Up2s1w== dependencies: cacache "^13.0.1" - find-cache-dir "^3.2.0" - jest-worker "^24.9.0" - schema-utils "^2.6.1" - serialize-javascript "^2.1.2" + find-cache-dir "^3.3.1" + jest-worker "^25.4.0" + p-limit "^2.3.0" + schema-utils "^2.6.6" + serialize-javascript "^4.0.0" source-map "^0.6.1" - terser "^4.4.3" + terser "^4.6.12" webpack-sources "^1.4.3" -terser@^4.1.2, terser@^4.4.3: +terser@^4.1.2: version "4.6.3" resolved "https://registry.yarnpkg.com/terser/-/terser-4.6.3.tgz#e33aa42461ced5238d352d2df2a67f21921f8d87" integrity sha512-Lw+ieAXmY69d09IIc/yqeBqXpEQIpDGZqT34ui1QWXIUpR2RjbqEkT8X7Lgex19hslSqcWM5iMN2kM11eMsESQ==