diff --git a/.prettierignore b/.prettierignore index 5428362b5..f1835d8dc 100644 --- a/.prettierignore +++ b/.prettierignore @@ -7,3 +7,4 @@ app/vendor/** .nyc_output/** .vscode/** test/e2e/send-eth-with-private-key-test/** +*.scss diff --git a/.storybook/main.js b/.storybook/main.js index 2411f2066..8b1860ee5 100644 --- a/.storybook/main.js +++ b/.storybook/main.js @@ -7,7 +7,7 @@ module.exports = { addons: [ '@storybook/addon-knobs', '@storybook/addon-actions', - '@storybook/addon-backgrounds' + '@storybook/addon-backgrounds', ], webpackFinal: async (config) => { config.module.strictExportPresence = true @@ -27,18 +27,29 @@ module.exports = { loader: 'sass-loader', options: { sourceMap: true, + implementation: require('sass'), + sassOptions: { + includePaths: ['ui/app/css/'], + }, }, }, ], }) - config.plugins.push(new CopyWebpackPlugin({ - patterns: [ - { - from: path.join('node_modules', '@fortawesome', 'fontawesome-free', 'webfonts'), - to: path.join('fonts', 'fontawesome'), - }, - ], - })) + config.plugins.push( + new CopyWebpackPlugin({ + patterns: [ + { + from: path.join( + 'node_modules', + '@fortawesome', + 'fontawesome-free', + 'webfonts', + ), + to: path.join('fonts', 'fontawesome'), + }, + ], + }), + ) return config }, } diff --git a/README.md b/README.md index 83b90ae1c..545f1218c 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,8 @@ # MetaMask Browser Extension +Hey! We are hiring JavaScript Engineers! [Apply here](https://boards.greenhouse.io/consensys/jobs/2572388)! +--- + You can find the latest version of MetaMask on [our official website](https://metamask.io/). For help using MetaMask, visit our [User Support Site](https://metamask.zendesk.com/hc/en-us). For [general questions](https://metamask.zendesk.com/hc/en-us/community/topics/360000682532-General), [feature requests](https://metamask.zendesk.com/hc/en-us/community/topics/360000682552-Feature-Requests-Ideas), or [developer questions](https://metamask.zendesk.com/hc/en-us/community/topics/360001751291-Developer-Questions), visit our [Community Forum](https://metamask.zendesk.com/hc/en-us/community/topics). diff --git a/app/scripts/background.js b/app/scripts/background.js index 1f8badfda..c63c4ade0 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -19,6 +19,12 @@ import extension from 'extensionizer' import { storeAsStream, storeTransformStream } from '@metamask/obs-store' import PortStream from 'extension-port-stream' import { captureException } from '@sentry/browser' + +import { + ENVIRONMENT_TYPE_POPUP, + ENVIRONMENT_TYPE_NOTIFICATION, + ENVIRONMENT_TYPE_FULLSCREEN, +} from '../../shared/constants/app' import migrations from './migrations' import Migrator from './lib/migrator' import ExtensionPlatform from './platforms/extension' @@ -31,12 +37,6 @@ import rawFirstTimeState from './first-time-state' import getFirstPreferredLangCode from './lib/get-first-preferred-lang-code' import getObjStructure from './lib/getObjStructure' import setupEnsIpfsResolver from './lib/ens-ipfs/setup' - -import { - ENVIRONMENT_TYPE_POPUP, - ENVIRONMENT_TYPE_NOTIFICATION, - ENVIRONMENT_TYPE_FULLSCREEN, -} from './lib/enums' /* eslint-enable import/first */ const { sentry } = global diff --git a/app/scripts/controllers/network/contract-addresses.js b/app/scripts/constants/contracts.js similarity index 100% rename from app/scripts/controllers/network/contract-addresses.js rename to app/scripts/constants/contracts.js diff --git a/app/scripts/controllers/detect-tokens.js b/app/scripts/controllers/detect-tokens.js index 1ad46193d..d91fdb989 100644 --- a/app/scripts/controllers/detect-tokens.js +++ b/app/scripts/controllers/detect-tokens.js @@ -2,12 +2,11 @@ import Web3 from 'web3' import contracts from '@metamask/contract-metadata' import { warn } from 'loglevel' import SINGLE_CALL_BALANCES_ABI from 'single-call-balance-checker-abi' -import { MAINNET_CHAIN_ID } from './network/enums' +import { MAINNET_CHAIN_ID } from '../../../shared/constants/network' +import { SINGLE_CALL_BALANCES_ADDRESS } from '../constants/contracts' // By default, poll every 3 minutes const DEFAULT_INTERVAL = 180 * 1000 -const SINGLE_CALL_BALANCES_ADDRESS = - '0xb1f8e55c7f64d203c1400b9d8555d050f94adf39' /** * A controller that polls for token exchange diff --git a/app/scripts/controllers/incoming-transactions.js b/app/scripts/controllers/incoming-transactions.js index 58a059dd2..e1ff68895 100644 --- a/app/scripts/controllers/incoming-transactions.js +++ b/app/scripts/controllers/incoming-transactions.js @@ -3,7 +3,7 @@ import log from 'loglevel' import BN from 'bn.js' import createId from '../lib/random-id' import { bnToHex } from '../lib/util' -import fetchWithTimeout from '../lib/fetch-with-timeout' +import getFetchWithTimeout from '../../../shared/modules/fetch-with-timeout' import { TRANSACTION_CATEGORIES, @@ -22,11 +22,9 @@ import { RINKEBY_CHAIN_ID, ROPSTEN, ROPSTEN_CHAIN_ID, -} from './network/enums' +} from '../../../shared/constants/network' -const fetch = fetchWithTimeout({ - timeout: 30000, -}) +const fetchWithTimeout = getFetchWithTimeout(30000) /** * This controller is responsible for retrieving incoming transactions. Etherscan is polled once every block to check @@ -227,7 +225,7 @@ export default class IncomingTransactionsController { if (fromBlock) { url += `&startBlock=${parseInt(fromBlock, 10)}` } - const response = await fetch(url) + const response = await fetchWithTimeout(url) const parsedResponse = await response.json() return { diff --git a/app/scripts/controllers/metametrics.js b/app/scripts/controllers/metametrics.js index 3ae74cbf8..2c84ee78c 100644 --- a/app/scripts/controllers/metametrics.js +++ b/app/scripts/controllers/metametrics.js @@ -1,7 +1,7 @@ import { merge, omit } from 'lodash' import { ObservableStore } from '@metamask/obs-store' import { bufferToHex, sha3 } from 'ethereumjs-util' -import { ENVIRONMENT_TYPE_BACKGROUND } from '../lib/enums' +import { ENVIRONMENT_TYPE_BACKGROUND } from '../../../shared/constants/app' import { METAMETRICS_ANONYMOUS_ID, METAMETRICS_BACKGROUND_PAGE_OBJECT, diff --git a/app/scripts/controllers/network/createInfuraClient.js b/app/scripts/controllers/network/createInfuraClient.js index 2a26c9b75..0f37ea4ca 100644 --- a/app/scripts/controllers/network/createInfuraClient.js +++ b/app/scripts/controllers/network/createInfuraClient.js @@ -8,7 +8,7 @@ import providerFromMiddleware from 'eth-json-rpc-middleware/providerFromMiddlewa import createInfuraMiddleware from 'eth-json-rpc-infura' import BlockTracker from 'eth-block-tracker' -import { NETWORK_TYPE_TO_ID_MAP } from './enums' +import { NETWORK_TYPE_TO_ID_MAP } from '../../../../shared/constants/network' export default function createInfuraClient({ network, projectId }) { const infuraMiddleware = createInfuraMiddleware({ diff --git a/app/scripts/controllers/network/network.js b/app/scripts/controllers/network/network.js index 9bfc0fc07..0de14fc5c 100644 --- a/app/scripts/controllers/network/network.js +++ b/app/scripts/controllers/network/network.js @@ -9,25 +9,25 @@ import { createEventEmitterProxy, } from 'swappable-obj-proxy' import EthQuery from 'eth-query' -import createMetamaskMiddleware from './createMetamaskMiddleware' -import createInfuraClient from './createInfuraClient' -import createJsonRpcClient from './createJsonRpcClient' - import { RINKEBY, MAINNET, INFURA_PROVIDER_TYPES, + NETWORK_TYPE_RPC, NETWORK_TYPE_TO_ID_MAP, MAINNET_CHAIN_ID, RINKEBY_CHAIN_ID, -} from './enums' +} from '../../../../shared/constants/network' +import createMetamaskMiddleware from './createMetamaskMiddleware' +import createInfuraClient from './createInfuraClient' +import createJsonRpcClient from './createJsonRpcClient' const env = process.env.METAMASK_ENV let defaultProviderConfigOpts if (process.env.IN_TEST === 'true') { defaultProviderConfigOpts = { - type: 'rpc', + type: NETWORK_TYPE_RPC, rpcUrl: 'http://localhost:8545', chainId: '0x539', nickname: 'Localhost 8545', @@ -161,7 +161,7 @@ export default class NetworkController extends EventEmitter { setRpcTarget(rpcUrl, chainId, ticker = 'ETH', nickname = '', rpcPrefs) { this.setProviderConfig({ - type: 'rpc', + type: NETWORK_TYPE_RPC, rpcUrl, chainId, ticker, @@ -173,8 +173,8 @@ export default class NetworkController extends EventEmitter { async setProviderType(type, rpcUrl = '', ticker = 'ETH', nickname = '') { assert.notEqual( type, - 'rpc', - `NetworkController - cannot call "setProviderType" with type 'rpc'. use "setRpcTarget"`, + NETWORK_TYPE_RPC, + `NetworkController - cannot call "setProviderType" with type "${NETWORK_TYPE_RPC}". Use "setRpcTarget"`, ) assert( INFURA_PROVIDER_TYPES.includes(type), @@ -209,7 +209,7 @@ export default class NetworkController extends EventEmitter { getNetworkIdentifier() { const provider = this.providerStore.getState() - return provider.type === 'rpc' ? provider.rpcUrl : provider.type + return provider.type === NETWORK_TYPE_RPC ? provider.rpcUrl : provider.type } // @@ -228,7 +228,7 @@ export default class NetworkController extends EventEmitter { if (isInfura) { this._configureInfuraProvider(type, this._infuraProjectId) // url-based rpc endpoints - } else if (type === 'rpc') { + } else if (type === NETWORK_TYPE_RPC) { this._configureStandardProvider(rpcUrl, chainId) } else { throw new Error( diff --git a/app/scripts/controllers/network/util.js b/app/scripts/controllers/network/util.js index 958a1d4dd..9c80db551 100644 --- a/app/scripts/controllers/network/util.js +++ b/app/scripts/controllers/network/util.js @@ -1,4 +1,4 @@ -import { NETWORK_TO_NAME_MAP } from './enums' +import { NETWORK_TO_NAME_MAP } from '../../../../shared/constants/network' export const getNetworkDisplayName = (key) => NETWORK_TO_NAME_MAP[key] diff --git a/app/scripts/controllers/permissions/enums.js b/app/scripts/controllers/permissions/enums.js index 510fad1b3..21356804f 100644 --- a/app/scripts/controllers/permissions/enums.js +++ b/app/scripts/controllers/permissions/enums.js @@ -10,11 +10,6 @@ export const METADATA_STORE_KEY = 'domainMetadata' export const METADATA_CACHE_MAX_SIZE = 100 -export const CAVEAT_NAMES = { - exposedAccounts: 'exposedAccounts', - primaryAccountOnly: 'primaryAccountOnly', -} - export const CAVEAT_TYPES = { limitResponseLength: 'limitResponseLength', filterResponse: 'filterResponse', diff --git a/app/scripts/controllers/permissions/index.js b/app/scripts/controllers/permissions/index.js index c4ffd14fb..515741a7e 100644 --- a/app/scripts/controllers/permissions/index.js +++ b/app/scripts/controllers/permissions/index.js @@ -6,10 +6,7 @@ import { CapabilitiesController as RpcCap } from 'rpc-cap' import { ethErrors } from 'eth-json-rpc-errors' import { cloneDeep } from 'lodash' -import createPermissionsMethodMiddleware from './permissionsMethodMiddleware' -import PermissionsLogController from './permissionsLog' - -// Methods that do not require any permissions to use: +import { CAVEAT_NAMES } from '../../../../shared/constants/permissions' import { APPROVAL_TYPE, SAFE_METHODS, // methods that do not require any permissions to use @@ -18,11 +15,13 @@ import { METADATA_CACHE_MAX_SIZE, LOG_STORE_KEY, HISTORY_STORE_KEY, - CAVEAT_NAMES, NOTIFICATION_NAMES, CAVEAT_TYPES, } from './enums' +import createPermissionsMethodMiddleware from './permissionsMethodMiddleware' +import PermissionsLogController from './permissionsLog' + // instanbul ignore next const noop = () => undefined diff --git a/app/scripts/controllers/permissions/permissionsLog.js b/app/scripts/controllers/permissions/permissionsLog.js index e1a37f0c8..28c87af6b 100644 --- a/app/scripts/controllers/permissions/permissionsLog.js +++ b/app/scripts/controllers/permissions/permissionsLog.js @@ -1,6 +1,6 @@ import { cloneDeep } from 'lodash' +import { CAVEAT_NAMES } from '../../../../shared/constants/permissions' import { - CAVEAT_NAMES, HISTORY_STORE_KEY, LOG_IGNORE_METHODS, LOG_LIMIT, diff --git a/app/scripts/controllers/preferences.js b/app/scripts/controllers/preferences.js index 7445be65b..d8ea05856 100644 --- a/app/scripts/controllers/preferences.js +++ b/app/scripts/controllers/preferences.js @@ -7,7 +7,7 @@ import ethers from 'ethers' import log from 'loglevel' import { isPrefixedFormattedHexString } from '../lib/util' import { LISTED_CONTRACT_ADDRESSES } from '../../../shared/constants/tokens' -import { NETWORK_TYPE_TO_ID_MAP } from './network/enums' +import { NETWORK_TYPE_TO_ID_MAP } from '../../../shared/constants/network' export default class PreferencesController { /** diff --git a/app/scripts/controllers/token-rates.js b/app/scripts/controllers/token-rates.js index 9011b1d01..031017c83 100644 --- a/app/scripts/controllers/token-rates.js +++ b/app/scripts/controllers/token-rates.js @@ -2,6 +2,9 @@ import { ObservableStore } from '@metamask/obs-store' import log from 'loglevel' import { normalize as normalizeAddress } from 'eth-sig-util' import ethUtil from 'ethereumjs-util' +import getFetchWithTimeout from '../../../shared/modules/fetch-with-timeout' + +const fetchWithTimeout = getFetchWithTimeout(30000) // By default, poll every 3 minutes const DEFAULT_INTERVAL = 180 * 1000 @@ -34,7 +37,7 @@ export default class TokenRatesController { const query = `contract_addresses=${pairs}&vs_currencies=${nativeCurrency}` if (this._tokens.length > 0) { try { - const response = await window.fetch( + const response = await fetchWithTimeout( `https://api.coingecko.com/api/v3/simple/token_price/ethereum?${query}`, ) const prices = await response.json() diff --git a/app/scripts/lib/account-tracker.js b/app/scripts/lib/account-tracker.js index 850c39291..6b78081f0 100644 --- a/app/scripts/lib/account-tracker.js +++ b/app/scripts/lib/account-tracker.js @@ -19,14 +19,14 @@ import { RINKEBY_CHAIN_ID, ROPSTEN_CHAIN_ID, KOVAN_CHAIN_ID, -} from '../controllers/network/enums' +} from '../../../shared/constants/network' import { SINGLE_CALL_BALANCES_ADDRESS, SINGLE_CALL_BALANCES_ADDRESS_RINKEBY, SINGLE_CALL_BALANCES_ADDRESS_ROPSTEN, SINGLE_CALL_BALANCES_ADDRESS_KOVAN, -} from '../controllers/network/contract-addresses' +} from '../constants/contracts' import { bnToHex } from './util' /** diff --git a/app/scripts/lib/decrypt-message-manager.js b/app/scripts/lib/decrypt-message-manager.js index fc8ce03ce..e84397d42 100644 --- a/app/scripts/lib/decrypt-message-manager.js +++ b/app/scripts/lib/decrypt-message-manager.js @@ -3,9 +3,9 @@ import { ObservableStore } from '@metamask/obs-store' import ethUtil from 'ethereumjs-util' import { ethErrors } from 'eth-json-rpc-errors' import log from 'loglevel' +import { MESSAGE_TYPE } from '../../../shared/constants/app' import { addHexPrefix } from './util' import createId from './random-id' -import { MESSAGE_TYPE } from './enums' const hexRe = /^[0-9A-Fa-f]+$/gu diff --git a/app/scripts/lib/encryption-public-key-manager.js b/app/scripts/lib/encryption-public-key-manager.js index d563cae0b..48f2ab701 100644 --- a/app/scripts/lib/encryption-public-key-manager.js +++ b/app/scripts/lib/encryption-public-key-manager.js @@ -2,8 +2,8 @@ import EventEmitter from 'events' import { ObservableStore } from '@metamask/obs-store' import { ethErrors } from 'eth-json-rpc-errors' import log from 'loglevel' +import { MESSAGE_TYPE } from '../../../shared/constants/app' import createId from './random-id' -import { MESSAGE_TYPE } from './enums' /** * Represents, and contains data about, an 'eth_getEncryptionPublicKey' type request. These are created when diff --git a/app/scripts/lib/ens-ipfs/setup.js b/app/scripts/lib/ens-ipfs/setup.js index ab4cec023..9ec6e1492 100644 --- a/app/scripts/lib/ens-ipfs/setup.js +++ b/app/scripts/lib/ens-ipfs/setup.js @@ -1,6 +1,9 @@ import extension from 'extensionizer' +import getFetchWithTimeout from '../../../../shared/modules/fetch-with-timeout' import resolveEnsToIpfsContentId from './resolver' +const fetchWithTimeout = getFetchWithTimeout(30000) + const supportedTopLevelDomains = ['eth'] export default function setupEnsIpfsResolver({ @@ -55,7 +58,9 @@ export default function setupEnsIpfsResolver({ )}.${ipfsGateway}${pathname}${search || ''}${fragment || ''}` try { // check if ipfs gateway has result - const response = await window.fetch(resolvedUrl, { method: 'HEAD' }) + const response = await fetchWithTimeout(resolvedUrl, { + method: 'HEAD', + }) if (response.status === 200) { url = resolvedUrl } diff --git a/app/scripts/lib/message-manager.js b/app/scripts/lib/message-manager.js index 872f97b0d..a3f0dee58 100644 --- a/app/scripts/lib/message-manager.js +++ b/app/scripts/lib/message-manager.js @@ -2,8 +2,8 @@ import EventEmitter from 'events' import { ObservableStore } from '@metamask/obs-store' import ethUtil from 'ethereumjs-util' import { ethErrors } from 'eth-json-rpc-errors' +import { MESSAGE_TYPE } from '../../../shared/constants/app' import createId from './random-id' -import { MESSAGE_TYPE } from './enums' /** * Represents, and contains data about, an 'eth_sign' type signature request. These are created when a signature for diff --git a/app/scripts/lib/network-store.js b/app/scripts/lib/network-store.js index cc2898292..bfa7a8ba4 100644 --- a/app/scripts/lib/network-store.js +++ b/app/scripts/lib/network-store.js @@ -1,4 +1,7 @@ import log from 'loglevel' +import getFetchWithTimeout from '../../../shared/modules/fetch-with-timeout' + +const fetchWithTimeout = getFetchWithTimeout(30000) const FIXTURE_SERVER_HOST = 'localhost' const FIXTURE_SERVER_PORT = 12345 @@ -24,7 +27,7 @@ export default class ReadOnlyNetworkStore { */ async _init() { try { - const response = await window.fetch(FIXTURE_SERVER_URL) + const response = await fetchWithTimeout(FIXTURE_SERVER_URL) if (response.ok) { this._state = await response.json() } diff --git a/app/scripts/lib/personal-message-manager.js b/app/scripts/lib/personal-message-manager.js index 52d20588f..c08dddbb2 100644 --- a/app/scripts/lib/personal-message-manager.js +++ b/app/scripts/lib/personal-message-manager.js @@ -3,9 +3,9 @@ import { ObservableStore } from '@metamask/obs-store' import ethUtil from 'ethereumjs-util' import { ethErrors } from 'eth-json-rpc-errors' import log from 'loglevel' +import { MESSAGE_TYPE } from '../../../shared/constants/app' import { addHexPrefix } from './util' import createId from './random-id' -import { MESSAGE_TYPE } from './enums' const hexRe = /^[0-9A-Fa-f]+$/gu diff --git a/app/scripts/lib/rpc-method-middleware/handlers/get-provider-state.js b/app/scripts/lib/rpc-method-middleware/handlers/get-provider-state.js index 32b3c18c6..760517e10 100644 --- a/app/scripts/lib/rpc-method-middleware/handlers/get-provider-state.js +++ b/app/scripts/lib/rpc-method-middleware/handlers/get-provider-state.js @@ -1,4 +1,4 @@ -import { MESSAGE_TYPE } from '../../enums' +import { MESSAGE_TYPE } from '../../../../../shared/constants/app' /** * This RPC method gets background state relevant to the provider. diff --git a/app/scripts/lib/rpc-method-middleware/handlers/log-web3-shim-usage.js b/app/scripts/lib/rpc-method-middleware/handlers/log-web3-shim-usage.js index 21e908000..3fb5a5743 100644 --- a/app/scripts/lib/rpc-method-middleware/handlers/log-web3-shim-usage.js +++ b/app/scripts/lib/rpc-method-middleware/handlers/log-web3-shim-usage.js @@ -1,4 +1,4 @@ -import { MESSAGE_TYPE } from '../../enums' +import { MESSAGE_TYPE } from '../../../../../shared/constants/app' /** * This RPC method is called by the inpage provider whenever it detects the diff --git a/app/scripts/lib/rpc-method-middleware/handlers/watch-asset.js b/app/scripts/lib/rpc-method-middleware/handlers/watch-asset.js index 1c5f4c1db..60c8ad6da 100644 --- a/app/scripts/lib/rpc-method-middleware/handlers/watch-asset.js +++ b/app/scripts/lib/rpc-method-middleware/handlers/watch-asset.js @@ -1,4 +1,4 @@ -import { MESSAGE_TYPE } from '../../enums' +import { MESSAGE_TYPE } from '../../../../../shared/constants/app' const watchAsset = { methodNames: [MESSAGE_TYPE.WATCH_ASSET, MESSAGE_TYPE.WATCH_ASSET_LEGACY], diff --git a/app/scripts/lib/typed-message-manager.js b/app/scripts/lib/typed-message-manager.js index 6bcfe846b..1dce10bc8 100644 --- a/app/scripts/lib/typed-message-manager.js +++ b/app/scripts/lib/typed-message-manager.js @@ -6,8 +6,8 @@ import { typedSignatureHash, TYPED_MESSAGE_SCHEMA } from 'eth-sig-util' import { isValidAddress } from 'ethereumjs-util' import log from 'loglevel' import jsonschema from 'jsonschema' +import { MESSAGE_TYPE } from '../../../shared/constants/app' import createId from './random-id' -import { MESSAGE_TYPE } from './enums' /** * Represents, and contains data about, an 'eth_signTypedData' type signature request. These are created when a diff --git a/app/scripts/lib/util.js b/app/scripts/lib/util.js index 1816d04ab..6750d8b43 100644 --- a/app/scripts/lib/util.js +++ b/app/scripts/lib/util.js @@ -14,7 +14,7 @@ import { PLATFORM_CHROME, PLATFORM_EDGE, PLATFORM_BRAVE, -} from './enums' +} from '../../../shared/constants/app' /** * @see {@link getEnvironmentType} diff --git a/app/scripts/migrations/051.js b/app/scripts/migrations/051.js index 0128dd656..4c024458d 100644 --- a/app/scripts/migrations/051.js +++ b/app/scripts/migrations/051.js @@ -1,5 +1,5 @@ import { cloneDeep } from 'lodash' -import { NETWORK_TYPE_TO_ID_MAP } from '../controllers/network/enums' +import { NETWORK_TYPE_TO_ID_MAP } from '../../../shared/constants/network' const version = 51 diff --git a/app/scripts/platforms/extension.js b/app/scripts/platforms/extension.js index 3644e02cb..88117700d 100644 --- a/app/scripts/platforms/extension.js +++ b/app/scripts/platforms/extension.js @@ -1,7 +1,7 @@ import extension from 'extensionizer' import { createExplorerLink as explorerLink } from '@metamask/etherscan-link' import { getEnvironmentType, checkForError } from '../lib/util' -import { ENVIRONMENT_TYPE_BACKGROUND } from '../lib/enums' +import { ENVIRONMENT_TYPE_BACKGROUND } from '../../../shared/constants/app' import { TRANSACTION_STATUSES } from '../../../shared/constants/transaction' export default class ExtensionPlatform { diff --git a/app/scripts/ui.js b/app/scripts/ui.js index f1f4a7b78..7aca1b724 100644 --- a/app/scripts/ui.js +++ b/app/scripts/ui.js @@ -12,12 +12,12 @@ import EthQuery from 'eth-query' import StreamProvider from 'web3-stream-provider' import log from 'loglevel' import launchMetaMaskUi from '../../ui' -import ExtensionPlatform from './platforms/extension' -import { setupMultiplex } from './lib/stream-utils' import { ENVIRONMENT_TYPE_FULLSCREEN, ENVIRONMENT_TYPE_POPUP, -} from './lib/enums' +} from '../../shared/constants/app' +import ExtensionPlatform from './platforms/extension' +import { setupMultiplex } from './lib/stream-utils' import { getEnvironmentType } from './lib/util' start().catch(log.error) diff --git a/development/build/styles.js b/development/build/styles.js index 966b2c818..c8b9e6718 100644 --- a/development/build/styles.js +++ b/development/build/styles.js @@ -1,7 +1,7 @@ const pify = require('pify') const gulp = require('gulp') const sass = require('gulp-sass') -sass.compiler = require('node-sass') +sass.compiler = require('sass') const autoprefixer = require('gulp-autoprefixer') const gulpStylelint = require('gulp-stylelint') const watch = require('gulp-watch') diff --git a/package.json b/package.json index 58b75ae66..131f0f506 100644 --- a/package.json +++ b/package.json @@ -246,7 +246,7 @@ "gulp-rename": "^2.0.0", "gulp-replace": "^1.0.0", "gulp-rtlcss": "^1.4.0", - "gulp-sass": "^4.0.0", + "gulp-sass": "^4.1.0", "gulp-sourcemaps": "^2.6.0", "gulp-stylelint": "^13.0.0", "gulp-terser-js": "^5.2.2", @@ -259,7 +259,6 @@ "mocha": "^7.2.0", "nock": "^9.0.14", "node-fetch": "^2.6.1", - "node-sass": "^4.14.1", "nyc": "^15.0.0", "polyfill-crypto.getrandomvalues": "^1.0.0", "prettier": "^2.1.1", @@ -275,7 +274,8 @@ "remote-redux-devtools": "^0.5.16", "remotedev-server": "^0.3.1", "resolve-url-loader": "^3.1.2", - "sass-loader": "^7.0.1", + "sass": "^1.32.4", + "sass-loader": "^10.1.1", "selenium-webdriver": "4.0.0-alpha.7", "serve-handler": "^6.1.2", "ses": "0.11.0", diff --git a/app/scripts/lib/enums.js b/shared/constants/app.js similarity index 59% rename from app/scripts/lib/enums.js rename to shared/constants/app.js index a6b7a99de..90e4726b0 100644 --- a/app/scripts/lib/enums.js +++ b/shared/constants/app.js @@ -6,19 +6,18 @@ * background - The background process that powers the extension * @typedef {'popup' | 'notification' | 'fullscreen' | 'background'} EnvironmentType */ +export const ENVIRONMENT_TYPE_POPUP = 'popup' +export const ENVIRONMENT_TYPE_NOTIFICATION = 'notification' +export const ENVIRONMENT_TYPE_FULLSCREEN = 'fullscreen' +export const ENVIRONMENT_TYPE_BACKGROUND = 'background' -const ENVIRONMENT_TYPE_POPUP = 'popup' -const ENVIRONMENT_TYPE_NOTIFICATION = 'notification' -const ENVIRONMENT_TYPE_FULLSCREEN = 'fullscreen' -const ENVIRONMENT_TYPE_BACKGROUND = 'background' +export const PLATFORM_BRAVE = 'Brave' +export const PLATFORM_CHROME = 'Chrome' +export const PLATFORM_EDGE = 'Edge' +export const PLATFORM_FIREFOX = 'Firefox' +export const PLATFORM_OPERA = 'Opera' -const PLATFORM_BRAVE = 'Brave' -const PLATFORM_CHROME = 'Chrome' -const PLATFORM_EDGE = 'Edge' -const PLATFORM_FIREFOX = 'Firefox' -const PLATFORM_OPERA = 'Opera' - -const MESSAGE_TYPE = { +export const MESSAGE_TYPE = { ETH_DECRYPT: 'eth_decrypt', ETH_GET_ENCRYPTION_PUBLIC_KEY: 'eth_getEncryptionPublicKey', ETH_SIGN: 'eth_sign', @@ -29,16 +28,3 @@ const MESSAGE_TYPE = { WATCH_ASSET: 'wallet_watchAsset', WATCH_ASSET_LEGACY: 'metamask_watchAsset', } - -export { - ENVIRONMENT_TYPE_POPUP, - ENVIRONMENT_TYPE_NOTIFICATION, - ENVIRONMENT_TYPE_FULLSCREEN, - ENVIRONMENT_TYPE_BACKGROUND, - MESSAGE_TYPE, - PLATFORM_BRAVE, - PLATFORM_CHROME, - PLATFORM_EDGE, - PLATFORM_FIREFOX, - PLATFORM_OPERA, -} diff --git a/shared/constants/metametrics.js b/shared/constants/metametrics.js index 7bd2c4c5e..edb37a2a1 100644 --- a/shared/constants/metametrics.js +++ b/shared/constants/metametrics.js @@ -1,6 +1,6 @@ // Type Imports /** - * @typedef {import('../../app/scripts/lib/enums').EnvironmentType} EnvironmentType + * @typedef {import('../../shared/constants/app').EnvironmentType} EnvironmentType */ // Type Declarations diff --git a/app/scripts/controllers/network/enums.js b/shared/constants/network.js similarity index 98% rename from app/scripts/controllers/network/enums.js rename to shared/constants/network.js index 6887a08dd..eba397466 100644 --- a/app/scripts/controllers/network/enums.js +++ b/shared/constants/network.js @@ -3,6 +3,7 @@ export const RINKEBY = 'rinkeby' export const KOVAN = 'kovan' export const MAINNET = 'mainnet' export const GOERLI = 'goerli' +export const NETWORK_TYPE_RPC = 'rpc' export const MAINNET_NETWORK_ID = '1' export const ROPSTEN_NETWORK_ID = '3' diff --git a/shared/constants/permissions.js b/shared/constants/permissions.js new file mode 100644 index 000000000..f396fbeba --- /dev/null +++ b/shared/constants/permissions.js @@ -0,0 +1,4 @@ +export const CAVEAT_NAMES = { + exposedAccounts: 'exposedAccounts', + primaryAccountOnly: 'primaryAccountOnly', +} diff --git a/app/scripts/lib/fetch-with-timeout.js b/shared/modules/fetch-with-timeout.js similarity index 64% rename from app/scripts/lib/fetch-with-timeout.js rename to shared/modules/fetch-with-timeout.js index a9e895b12..e97ae3402 100644 --- a/app/scripts/lib/fetch-with-timeout.js +++ b/shared/modules/fetch-with-timeout.js @@ -1,4 +1,10 @@ -const fetchWithTimeout = ({ timeout = 120000 } = {}) => { +import { memoize } from 'lodash' + +const getFetchWithTimeout = memoize((timeout) => { + if (!Number.isInteger(timeout) || timeout < 1) { + throw new Error('Must specify positive integer timeout.') + } + return async function _fetch(url, opts) { const abortController = new window.AbortController() const { signal } = abortController @@ -18,6 +24,6 @@ const fetchWithTimeout = ({ timeout = 120000 } = {}) => { throw e } } -} +}) -export default fetchWithTimeout +export default getFetchWithTimeout diff --git a/test/unit/actions/config_test.js b/test/unit/actions/config_test.js index ed60ac299..35064ad9c 100644 --- a/test/unit/actions/config_test.js +++ b/test/unit/actions/config_test.js @@ -2,6 +2,7 @@ import assert from 'assert' import freeze from 'deep-freeze-strict' import reducers from '../../../ui/app/ducks' import * as actionConstants from '../../../ui/app/store/actionConstants' +import { NETWORK_TYPE_RPC } from '../../../shared/constants/network' describe('config view actions', function () { const initialState = { @@ -25,7 +26,7 @@ describe('config view actions', function () { } const result = reducers(initialState, action) - assert.equal(result.metamask.provider.type, 'rpc') + assert.equal(result.metamask.provider.type, NETWORK_TYPE_RPC) assert.equal(result.metamask.provider.rpcUrl, 'foo') }) }) diff --git a/test/unit/app/controllers/detect-tokens-test.js b/test/unit/app/controllers/detect-tokens-test.js index 6039a943c..d76906d26 100644 --- a/test/unit/app/controllers/detect-tokens-test.js +++ b/test/unit/app/controllers/detect-tokens-test.js @@ -7,10 +7,7 @@ import BigNumber from 'bignumber.js' import DetectTokensController from '../../../../app/scripts/controllers/detect-tokens' import NetworkController from '../../../../app/scripts/controllers/network/network' import PreferencesController from '../../../../app/scripts/controllers/preferences' -import { - MAINNET, - ROPSTEN, -} from '../../../../app/scripts/controllers/network/enums' +import { MAINNET, ROPSTEN } from '../../../../shared/constants/network' describe('DetectTokensController', function () { const sandbox = sinon.createSandbox() diff --git a/test/unit/app/controllers/incoming-transactions-test.js b/test/unit/app/controllers/incoming-transactions-test.js index 61768cee8..af8ac1084 100644 --- a/test/unit/app/controllers/incoming-transactions-test.js +++ b/test/unit/app/controllers/incoming-transactions-test.js @@ -14,7 +14,7 @@ import { ROPSTEN, ROPSTEN_CHAIN_ID, ROPSTEN_NETWORK_ID, -} from '../../../../app/scripts/controllers/network/enums' +} from '../../../../shared/constants/network' import { TRANSACTION_CATEGORIES, TRANSACTION_STATUSES, diff --git a/test/unit/app/controllers/metametrics-test.js b/test/unit/app/controllers/metametrics-test.js index 4e66fec4a..11c012bfc 100644 --- a/test/unit/app/controllers/metametrics-test.js +++ b/test/unit/app/controllers/metametrics-test.js @@ -1,7 +1,7 @@ import { strict as assert } from 'assert' import sinon from 'sinon' import MetaMetricsController from '../../../../app/scripts/controllers/metametrics' -import { ENVIRONMENT_TYPE_BACKGROUND } from '../../../../app/scripts/lib/enums' +import { ENVIRONMENT_TYPE_BACKGROUND } from '../../../../shared/constants/app' import { createSegmentMock } from '../../../../app/scripts/lib/segment' import { METAMETRICS_ANONYMOUS_ID, diff --git a/test/unit/app/controllers/permissions/mocks.js b/test/unit/app/controllers/permissions/mocks.js index 48937faf2..8d7d75e75 100644 --- a/test/unit/app/controllers/permissions/mocks.js +++ b/test/unit/app/controllers/permissions/mocks.js @@ -5,8 +5,8 @@ import { ApprovalController } from '@metamask/controllers' import _getRestrictedMethods from '../../../../../app/scripts/controllers/permissions/restrictedMethods' +import { CAVEAT_NAMES } from '../../../../../shared/constants/permissions' import { - CAVEAT_NAMES, CAVEAT_TYPES, NOTIFICATION_NAMES, } from '../../../../../app/scripts/controllers/permissions/enums' diff --git a/test/unit/app/controllers/swaps-test.js b/test/unit/app/controllers/swaps-test.js index 38f948088..2622d04eb 100644 --- a/test/unit/app/controllers/swaps-test.js +++ b/test/unit/app/controllers/swaps-test.js @@ -8,7 +8,7 @@ import { ObservableStore } from '@metamask/obs-store' import { ROPSTEN_NETWORK_ID, MAINNET_NETWORK_ID, -} from '../../../../app/scripts/controllers/network/enums' +} from '../../../../shared/constants/network' import { ETH_SWAPS_TOKEN_ADDRESS } from '../../../../ui/app/helpers/constants/swaps' import { createTestProviderTools } from '../../../stub/provider' import SwapsController, { diff --git a/test/unit/app/fetch-with-timeout.test.js b/test/unit/app/fetch-with-timeout.test.js index 89ea2fec9..dd91ff58b 100644 --- a/test/unit/app/fetch-with-timeout.test.js +++ b/test/unit/app/fetch-with-timeout.test.js @@ -1,14 +1,16 @@ import assert from 'assert' import nock from 'nock' -import fetchWithTimeout from '../../../app/scripts/lib/fetch-with-timeout' +import getFetchWithTimeout from '../../../shared/modules/fetch-with-timeout' -describe('fetchWithTimeout', function () { +describe('getFetchWithTimeout', function () { it('fetches a url', async function () { nock('https://api.infura.io').get('/money').reply(200, '{"hodl": false}') - const fetch = fetchWithTimeout() - const response = await (await fetch('https://api.infura.io/money')).json() + const fetchWithTimeout = getFetchWithTimeout(30000) + const response = await ( + await fetchWithTimeout('https://api.infura.io/money') + ).json() assert.deepEqual(response, { hodl: false, }) @@ -20,12 +22,10 @@ describe('fetchWithTimeout', function () { .delay(2000) .reply(200, '{"moon": "2012-12-21T11:11:11Z"}') - const fetch = fetchWithTimeout({ - timeout: 123, - }) + const fetchWithTimeout = getFetchWithTimeout(123) try { - await fetch('https://api.infura.io/moon').then((r) => r.json()) + await fetchWithTimeout('https://api.infura.io/moon').then((r) => r.json()) assert.fail('Request should throw') } catch (e) { assert.ok(e) @@ -38,15 +38,20 @@ describe('fetchWithTimeout', function () { .delay(2000) .reply(200, '{"moon": "2012-12-21T11:11:11Z"}') - const fetch = fetchWithTimeout({ - timeout: 123, - }) + const fetchWithTimeout = getFetchWithTimeout(123) try { - await fetch('https://api.infura.io/moon').then((r) => r.json()) + await fetchWithTimeout('https://api.infura.io/moon').then((r) => r.json()) assert.fail('Request should be aborted') } catch (e) { assert.deepEqual(e.message, 'Aborted') } }) + + it('throws on invalid timeout', async function () { + assert.throws(() => getFetchWithTimeout(), 'should throw') + assert.throws(() => getFetchWithTimeout(-1), 'should throw') + assert.throws(() => getFetchWithTimeout({}), 'should throw') + assert.throws(() => getFetchWithTimeout(true), 'should throw') + }) }) diff --git a/test/unit/app/util-test.js b/test/unit/app/util-test.js index f2372576f..802ae93c9 100644 --- a/test/unit/app/util-test.js +++ b/test/unit/app/util-test.js @@ -10,7 +10,7 @@ import { ENVIRONMENT_TYPE_NOTIFICATION, ENVIRONMENT_TYPE_FULLSCREEN, ENVIRONMENT_TYPE_BACKGROUND, -} from '../../../app/scripts/lib/enums' +} from '../../../shared/constants/app' describe('app utils', function () { describe('getEnvironmentType', function () { diff --git a/test/unit/localhostState.js b/test/unit/localhostState.js index 8b0c68507..069ac0b78 100644 --- a/test/unit/localhostState.js +++ b/test/unit/localhostState.js @@ -1,3 +1,5 @@ +import { NETWORK_TYPE_RPC } from '../../shared/constants/network' + /** * @typedef {Object} FirstTimeState * @property {Object} config Initial configuration parameters @@ -11,7 +13,7 @@ const initialState = { config: {}, NetworkController: { provider: { - type: 'rpc', + type: NETWORK_TYPE_RPC, rpcUrl: 'http://localhost:8545', chainId: '0x539', }, diff --git a/test/unit/migrations/051-test.js b/test/unit/migrations/051-test.js index d692e5773..ae0a78afe 100644 --- a/test/unit/migrations/051-test.js +++ b/test/unit/migrations/051-test.js @@ -3,7 +3,7 @@ import migration51 from '../../../app/scripts/migrations/051' import { INFURA_PROVIDER_TYPES, NETWORK_TYPE_TO_ID_MAP, -} from '../../../app/scripts/controllers/network/enums' +} from '../../../shared/constants/network' describe('migration #51', function () { it('should update the version metadata', async function () { 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 00c889a94..f16cb41a4 100644 --- a/ui/app/components/app/account-menu/account-menu.component.js +++ b/ui/app/components/app/account-menu/account-menu.component.js @@ -4,7 +4,7 @@ import { debounce } from 'lodash' import Fuse from 'fuse.js' import InputAdornment from '@material-ui/core/InputAdornment' import classnames from 'classnames' -import { ENVIRONMENT_TYPE_POPUP } from '../../../../../app/scripts/lib/enums' +import { ENVIRONMENT_TYPE_POPUP } from '../../../../../shared/constants/app' import { getEnvironmentType } from '../../../../../app/scripts/lib/util' import Identicon from '../../ui/identicon' import SiteIcon from '../../ui/site-icon' 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 72e741a6b..bdc6295d6 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 @@ -3,7 +3,7 @@ import PropTypes from 'prop-types' import { ENVIRONMENT_TYPE_POPUP, ENVIRONMENT_TYPE_NOTIFICATION, -} from '../../../../../../app/scripts/lib/enums' +} from '../../../../../../shared/constants/app' import { getEnvironmentType } from '../../../../../../app/scripts/lib/util' import NetworkDisplay from '../../network-display' import Identicon from '../../../ui/identicon' diff --git a/ui/app/components/app/dropdowns/network-dropdown.js b/ui/app/components/app/dropdowns/network-dropdown.js index e55f77afc..daf1048bb 100644 --- a/ui/app/components/app/dropdowns/network-dropdown.js +++ b/ui/app/components/app/dropdowns/network-dropdown.js @@ -9,7 +9,8 @@ import { NETWORKS_ROUTE, NETWORKS_FORM_ROUTE, } from '../../../helpers/constants/routes' -import { ENVIRONMENT_TYPE_FULLSCREEN } from '../../../../../app/scripts/lib/enums' +import { ENVIRONMENT_TYPE_FULLSCREEN } from '../../../../../shared/constants/app' +import { NETWORK_TYPE_RPC } from '../../../../../shared/constants/network' import { getEnvironmentType, isPrefixedFormattedHexString, @@ -117,7 +118,7 @@ class NetworkDropdown extends Component { return reversedRpcListDetail.map((entry) => { const { rpcUrl, chainId, ticker = 'ETH', nickname = '' } = entry const isCurrentRpcTarget = - provider.type === 'rpc' && rpcUrl === provider.rpcUrl + provider.type === NETWORK_TYPE_RPC && rpcUrl === provider.rpcUrl return ( { const { rpcUrl, chainId, ticker, nickname, type } = provider const setProviderArgs = - type === 'rpc' ? [rpcUrl, chainId, ticker, nickname] : [provider.type] + type === NETWORK_TYPE_RPC + ? [rpcUrl, chainId, ticker, nickname] + : [provider.type] return { isLoadingNetwork: network === 'loading', 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 60ca1c598..d3c9723e7 100644 --- a/ui/app/components/app/menu-bar/account-options-menu.js +++ b/ui/app/components/app/menu-bar/account-options-menu.js @@ -16,7 +16,7 @@ import { import { useI18nContext } from '../../../hooks/useI18nContext' import { useMetricEvent } from '../../../hooks/useMetricEvent' import { getEnvironmentType } from '../../../../../app/scripts/lib/util' -import { ENVIRONMENT_TYPE_FULLSCREEN } from '../../../../../app/scripts/lib/enums' +import { ENVIRONMENT_TYPE_FULLSCREEN } from '../../../../../shared/constants/app' export default function AccountOptionsMenu({ anchorElement, onClose }) { const t = useI18nContext() diff --git a/ui/app/components/app/menu-bar/menu-bar.js b/ui/app/components/app/menu-bar/menu-bar.js index d9d13fcb1..f6c70a43e 100644 --- a/ui/app/components/app/menu-bar/menu-bar.js +++ b/ui/app/components/app/menu-bar/menu-bar.js @@ -5,7 +5,7 @@ import { useSelector } from 'react-redux' import SelectedAccount from '../selected-account' import ConnectedStatusIndicator from '../connected-status-indicator' import { getEnvironmentType } from '../../../../../app/scripts/lib/util' -import { ENVIRONMENT_TYPE_POPUP } from '../../../../../app/scripts/lib/enums' +import { ENVIRONMENT_TYPE_POPUP } from '../../../../../shared/constants/app' import { CONNECTED_ACCOUNTS_ROUTE } from '../../../helpers/constants/routes' import { useI18nContext } from '../../../hooks/useI18nContext' import { useMetricEvent } from '../../../hooks/useMetricEvent' diff --git a/ui/app/components/app/modals/modal.js b/ui/app/components/app/modals/modal.js index 46f915b16..5ad7d3470 100644 --- a/ui/app/components/app/modals/modal.js +++ b/ui/app/components/app/modals/modal.js @@ -6,7 +6,7 @@ import * as actions from '../../../store/actions' import { resetCustomData as resetCustomGasData } from '../../../ducks/gas/gas.duck' import isMobileView from '../../../../lib/is-mobile-view' import { getEnvironmentType } from '../../../../../app/scripts/lib/util' -import { ENVIRONMENT_TYPE_POPUP } from '../../../../../app/scripts/lib/enums' +import { ENVIRONMENT_TYPE_POPUP } from '../../../../../shared/constants/app' // Modal Components import ConfirmCustomizeGasModal from '../gas-customization/gas-modal-page-container' 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 54556f630..2f82ce65f 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 @@ -3,7 +3,7 @@ import PropTypes from 'prop-types' import log from 'loglevel' import { BrowserQRCodeReader } from '@zxing/library' import { getEnvironmentType } from '../../../../../../app/scripts/lib/util' -import { ENVIRONMENT_TYPE_FULLSCREEN } from '../../../../../../app/scripts/lib/enums' +import { ENVIRONMENT_TYPE_FULLSCREEN } from '../../../../../../shared/constants/app' import Spinner from '../../../ui/spinner' import WebcamUtils from '../../../../../lib/webcam-utils' import PageContainerFooter from '../../../ui/page-container/page-container-footer/page-container-footer.component' 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 0838ddc57..c045c1527 100644 --- a/ui/app/components/app/network-display/network-display.component.js +++ b/ui/app/components/app/network-display/network-display.component.js @@ -1,21 +1,7 @@ import React, { Component } from 'react' import PropTypes from 'prop-types' import classnames from 'classnames' -import { - MAINNET_NETWORK_ID, - ROPSTEN_NETWORK_ID, - RINKEBY_NETWORK_ID, - KOVAN_NETWORK_ID, - GOERLI_NETWORK_ID, -} from '../../../../../app/scripts/controllers/network/enums' - -const networkIdToTypeMap = { - [MAINNET_NETWORK_ID]: 'mainnet', - [ROPSTEN_NETWORK_ID]: 'ropsten', - [RINKEBY_NETWORK_ID]: 'rinkeby', - [GOERLI_NETWORK_ID]: 'goerli', - [KOVAN_NETWORK_ID]: 'kovan', -} +import { NETWORK_TYPE_RPC } from '../../../../../shared/constants/network' export default class NetworkDisplay extends Component { static defaultProps = { @@ -23,9 +9,9 @@ export default class NetworkDisplay extends Component { } static propTypes = { + networkNickname: PropTypes.string.isRequired, + networkType: PropTypes.string.isRequired, colored: PropTypes.bool, - network: PropTypes.string, - provider: PropTypes.object, } static contextTypes = { @@ -33,12 +19,11 @@ export default class NetworkDisplay extends Component { } renderNetworkIcon() { - const { network } = this.props - const networkClass = networkIdToTypeMap[network] + const { networkType } = this.props - return networkClass ? ( + return networkType ? (
) : (
- {networkClass ? ( + {networkType ? (
) : (
)}
- {type === 'rpc' && nickname ? nickname : this.context.t(type)} + {networkType === NETWORK_TYPE_RPC && networkNickname + ? networkNickname + : this.context.t(networkType)}
) diff --git a/ui/app/components/app/network-display/network-display.container.js b/ui/app/components/app/network-display/network-display.container.js index 99a14fff4..136336448 100644 --- a/ui/app/components/app/network-display/network-display.container.js +++ b/ui/app/components/app/network-display/network-display.container.js @@ -1,10 +1,14 @@ import { connect } from 'react-redux' import NetworkDisplay from './network-display.component' -const mapStateToProps = ({ metamask: { network, provider } }) => { +const mapStateToProps = ({ + metamask: { + provider: { nickname, type }, + }, +}) => { return { - network, - provider, + networkNickname: nickname, + networkType: type, } } 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 b961f4def..f20933ad9 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' +} from '../../../../../shared/constants/app' import { getEnvironmentType } from '../../../../../app/scripts/lib/util' import Identicon from '../../ui/identicon' import AccountListItem from '../account-list-item' 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 9a421aa67..7c1749fd5 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 @@ -2,7 +2,7 @@ import { connect } from 'react-redux' import { compose } from 'redux' import { withRouter } from 'react-router-dom' -import { MESSAGE_TYPE } from '../../../../../app/scripts/lib/enums' +import { MESSAGE_TYPE } from '../../../../../shared/constants/app' import { goHome } from '../../../store/actions' import { accountsWithSendEtherInfoSelector, diff --git a/ui/app/components/app/signature-request/signature-request.constants.js b/ui/app/components/app/signature-request/signature-request.constants.js index 9cf241928..7311a7a18 100644 --- a/ui/app/components/app/signature-request/signature-request.constants.js +++ b/ui/app/components/app/signature-request/signature-request.constants.js @@ -1,3 +1,3 @@ -import { ENVIRONMENT_TYPE_NOTIFICATION } from '../../../../../app/scripts/lib/enums' +import { ENVIRONMENT_TYPE_NOTIFICATION } from '../../../../../shared/constants/app' export { ENVIRONMENT_TYPE_NOTIFICATION } diff --git a/ui/app/components/app/signature-request/signature-request.container.js b/ui/app/components/app/signature-request/signature-request.container.js index 0a521db4b..0c69f1c7a 100644 --- a/ui/app/components/app/signature-request/signature-request.container.js +++ b/ui/app/components/app/signature-request/signature-request.container.js @@ -2,7 +2,7 @@ import { connect } from 'react-redux' import { clearConfirmTransaction } from '../../../ducks/confirm-transaction/confirm-transaction.duck' import { accountsWithSendEtherInfoSelector } from '../../../selectors' import { getAccountByAddress } from '../../../helpers/utils/util' -import { MESSAGE_TYPE } from '../../../../../app/scripts/lib/enums' +import { MESSAGE_TYPE } from '../../../../../shared/constants/app' import SignatureRequest from './signature-request.component' function mapStateToProps(state) { diff --git a/ui/app/components/app/wallet-overview/eth-overview.js b/ui/app/components/app/wallet-overview/eth-overview.js index 4a550fcef..69aef6382 100644 --- a/ui/app/components/app/wallet-overview/eth-overview.js +++ b/ui/app/components/app/wallet-overview/eth-overview.js @@ -34,7 +34,7 @@ import { setSwapsFromToken, } from '../../../ducks/swaps/swaps' import IconButton from '../../ui/icon-button' -import { MAINNET_CHAIN_ID } from '../../../../../app/scripts/controllers/network/enums' +import { MAINNET_CHAIN_ID } from '../../../../../shared/constants/network' import WalletOverview from './wallet-overview' const EthOverview = ({ className }) => { diff --git a/ui/app/components/app/wallet-overview/token-overview.js b/ui/app/components/app/wallet-overview/token-overview.js index 3a2cfab90..58b5673db 100644 --- a/ui/app/components/app/wallet-overview/token-overview.js +++ b/ui/app/components/app/wallet-overview/token-overview.js @@ -27,7 +27,7 @@ import { getCurrentKeyring, getCurrentChainId, } from '../../../selectors/selectors' -import { MAINNET_CHAIN_ID } from '../../../../../app/scripts/controllers/network/enums' +import { MAINNET_CHAIN_ID } from '../../../../../shared/constants/network' import SwapIcon from '../../ui/icon/swap-icon.component' import SendIcon from '../../ui/icon/overview-send-icon.component' diff --git a/ui/app/components/ui/typography/index.js b/ui/app/components/ui/typography/index.js new file mode 100644 index 000000000..648ce1725 --- /dev/null +++ b/ui/app/components/ui/typography/index.js @@ -0,0 +1 @@ +export { default } from './typography' diff --git a/ui/app/components/ui/typography/typography.js b/ui/app/components/ui/typography/typography.js new file mode 100644 index 000000000..93990b00b --- /dev/null +++ b/ui/app/components/ui/typography/typography.js @@ -0,0 +1,58 @@ +import React from 'react' +import classnames from 'classnames' +import PropTypes from 'prop-types' +import { COLORS, TYPOGRAPHY } from '../../../helpers/constants/design-system' + +const { H6, H7, H8, H9 } = TYPOGRAPHY + +export default function Typography({ + variant = TYPOGRAPHY.Paragraph, + className, + color = COLORS.BLACK, + tag, + children, + spacing = 1, + fontWeight = 'normal', + align, +}) { + const computedClassName = classnames( + 'typography', + className, + `typography--${variant}`, + `typography--align-${align}`, + `typography--spacing-${spacing}`, + `typography--color-${color}`, + `typography--weight-${fontWeight}`, + ) + + let Tag = tag ?? variant + + if (Tag === TYPOGRAPHY.Paragraph) { + Tag = 'p' + } else if ([H7, H8, H9].includes(Tag)) { + Tag = H6 + } + + return {children} +} + +Typography.propTypes = { + variant: PropTypes.oneOf(Object.values(TYPOGRAPHY)), + children: PropTypes.node.isRequired, + color: PropTypes.oneOf(Object.values(COLORS)), + className: PropTypes.string, + align: PropTypes.oneOf(['center', 'right']), + spacing: PropTypes.oneOf([1, 2, 3, 4, 5, 6, 7, 8]), + fontWeight: PropTypes.oneOf(['bold', 'normal']), + tag: PropTypes.oneOf([ + 'p', + 'h1', + 'h2', + 'h3', + 'h4', + 'h5', + 'h6', + 'span', + 'div', + ]), +} diff --git a/ui/app/components/ui/typography/typography.scss b/ui/app/components/ui/typography/typography.scss new file mode 100644 index 000000000..e377f31d2 --- /dev/null +++ b/ui/app/components/ui/typography/typography.scss @@ -0,0 +1,38 @@ +@use "design-system"; +@use "sass:map"; + +.typography { + @include design-system.Paragraph; + + @each $variant in map.keys(design-system.$typography-variants) { + &--#{$variant} { + @include design-system.typography($variant); + } + } + + @each $variant, $color in design-system.$color-map { + &--color-#{$variant} { + color: $color; + } + } + + @each $variant, $weight in design-system.$typography-font-weights { + &--weight-#{$variant} { + font-weight: $weight; + } + } + + &--align-center { + text-align: center; + } + + &--align-right { + text-align: right; + } + + @for $i from 1 through 8 { + &--spacing-#{$i} { + margin: #{$i * 4}px auto; + } + } +} diff --git a/ui/app/components/ui/typography/typography.stories.js b/ui/app/components/ui/typography/typography.stories.js new file mode 100644 index 000000000..68d567e35 --- /dev/null +++ b/ui/app/components/ui/typography/typography.stories.js @@ -0,0 +1,53 @@ +import React from 'react' +import { number, select, text } from '@storybook/addon-knobs' +import { COLORS, TYPOGRAPHY } from '../../../helpers/constants/design-system' +import Typography from '.' + +export default { + title: 'Typography', +} + +const fontWeightOptions = { + bold: 'bold', + normal: 'normal', +} + +const alignOptions = { + left: undefined, + center: 'center', + right: 'right', +} + +export const list = () => ( +
+ {Object.values(TYPOGRAPHY).map((variant) => ( +
+ + {variant} + +
+ ))} +
+) + +export const TheQuickOrangeFox = () => ( +
+
+ + {text('content', 'The quick orange fox jumped over the lazy dog.')} + +
+
+) diff --git a/ui/app/components/ui/ui-components.scss b/ui/app/components/ui/ui-components.scss index 2c7c1163b..3d5e5446c 100644 --- a/ui/app/components/ui/ui-components.scss +++ b/ui/app/components/ui/ui-components.scss @@ -37,5 +37,6 @@ @import 'toggle-button/index'; @import 'token-balance/index'; @import 'tooltip/index'; +@import 'typography/typography'; @import 'unit-input/index'; @import 'url-icon/index'; diff --git a/ui/app/css/design-system/colors.scss b/ui/app/css/design-system/colors.scss index c945c0de1..a1383b661 100644 --- a/ui/app/css/design-system/colors.scss +++ b/ui/app/css/design-system/colors.scss @@ -74,3 +74,66 @@ $accent-pink: #ff45d8; $neutral-white: #fff; $neutral-black: $Black-100; $neutral-grey: $Grey-500; + +// Everything below this line is part of the new color system +$primary-1: #037dd6; +$primary-2: #eaf6ff; +$primary-3: #0260a4; + +$secondary-1: #f66a0a; +$secondary-2: #fef5ef; +$secondary-3: #c65507; + +$error-1: #d73a49; +$error-2: #fcf2f3; +$error-3: #b92534; + +$alert-1: #ffd33d; +$alert-2: #fefcde; +$alert-3: #f8c000; + +$success-1: #4cd964; +$success-2: #caf4d1; +$success-3: #219e37; + +$ui-black: #24292e; +$ui-white: #fff; +$ui-1: #f2f3f4; +$ui-2: #d6d9dc; +$ui-3: #bbc0c5; +$ui-4: #6a737d; + +$mainnet: #29b6af; +$ropsten: #ff4a8d; +$kovan: #9064ff; +$rinkeby: #f6c343; +$goerli: #3099f2; + +$color-map: ( + 'ui-1': $ui-1, + 'ui-2': $ui-2, + 'ui-3': $ui-3, + 'ui-4': $ui-4, + 'white': $ui-white, + 'black': $ui-black, + 'primary-1': $primary-1, + 'primary-2': $primary-2, + 'primary-3': $primary-3, + 'secondary-1': $secondary-1, + 'secondary-2': $secondary-2, + 'secondary-3': $secondary-3, + 'alert-1': $alert-1, + 'alert-2': $alert-2, + 'alert-3': $alert-3, + 'error-1': $error-1, + 'error-2': $error-2, + 'error-3': $error-3, + 'success-1': $success-1, + 'success-2': $success-2, + 'success-3': $success-3, + 'mainnet': $mainnet, + 'ropsten': $ropsten, + 'kovan': $kovan, + 'rinkeby': $rinkeby, + 'goerli': $goerli, +); diff --git a/ui/app/css/design-system/index.scss b/ui/app/css/design-system/index.scss index 2d85fcae3..d4f8980b9 100644 --- a/ui/app/css/design-system/index.scss +++ b/ui/app/css/design-system/index.scss @@ -1,5 +1,5 @@ -@import 'breakpoints'; -@import 'colors'; -@import 'deprecated-colors'; -@import 'typography'; -@import 'z-index'; +@forward 'breakpoints'; +@forward 'colors'; +@forward 'deprecated-colors'; +@forward 'typography'; +@forward 'z-index'; diff --git a/ui/app/css/design-system/typography.scss b/ui/app/css/design-system/typography.scss index 1d6e1a522..ff0725ea8 100644 --- a/ui/app/css/design-system/typography.scss +++ b/ui/app/css/design-system/typography.scss @@ -69,89 +69,80 @@ $fa-font-path: 'fonts/fontawesome'; $font-family: Euclid, Roboto, Helvetica, Arial, sans-serif; -$font-size-h1: 2.5rem; -$font-size-h2: 2rem; -$font-size-h3: 1.5rem; -$font-size-h4: 1.125rem; -$font-size-h5: 1rem; -$font-size-h6: 0.875rem; -$font-size-paragraph: 1rem; -$font-size-h7: 0.75rem; -$font-size-h8: 0.625rem; -$font-size-h9: 0.5rem; - -// Typography -@mixin H1 { - font-style: normal; - font-weight: normal; - font-size: $font-size-h1; +$typography-variants: ( + 'h1': 2.5rem, + 'h2': 2rem, + 'h3': 1.5rem, + 'h4': 1.125rem, + 'h5': 1rem, + 'h6': 0.875rem, + 'paragraph': 1rem, + 'h7': 0.75rem, + 'h8': 0.625rem, + 'h9': 0.5rem, +); + +$typography-font-weights: ( + 'bold': 700, + 'normal': 400, +); + +$font-size-h1: map-get($typography-variants, 'h1'); +$font-size-h2: map-get($typography-variants, 'h2'); +$font-size-h3: map-get($typography-variants, 'h3'); +$font-size-h4: map-get($typography-variants, 'h4'); +$font-size-h5: map-get($typography-variants, 'h5'); +$font-size-h6: map-get($typography-variants, 'h6'); +$font-size-paragraph: map-get($typography-variants, 'paragraph'); +$font-size-h7: map-get($typography-variants, 'h7'); +$font-size-h8: map-get($typography-variants, 'h8'); +$font-size-h9: map-get($typography-variants, 'h9'); + +@mixin typography($variant) { + font-size: map-get($typography-variants, $variant); font-family: $font-family; line-height: 140%; + font-style: normal; + font-weight: normal; } +// Typography +@mixin H1 { + @include typography('h1'); +} @mixin H2 { - font-style: normal; - font-weight: normal; - font-size: $font-size-h2; - font-family: $font-family; - line-height: 140%; + @include typography('h2'); } @mixin H3 { - font-style: normal; - font-weight: normal; - font-size: $font-size-h3; - font-family: $font-family; - line-height: 140%; + @include typography('h3'); } @mixin H4 { - font-style: normal; - font-weight: normal; - font-size: $font-size-h4; - font-family: $font-family; - line-height: 140%; + @include typography('h4'); } @mixin H5 { - font-style: normal; - font-weight: normal; - font-size: $font-size-h5; - line-height: 140%; + @include typography('h5'); } @mixin H6 { - font-style: normal; - font-weight: normal; - font-size: $font-size-h6; // 14px @default - line-height: 140%; + @include typography('h6'); } @mixin Paragraph { - font-style: normal; - font-weight: normal; - font-size: $font-size-paragraph; - line-height: 140%; + @include typography('paragraph'); } @mixin H7 { - font-style: normal; - font-weight: normal; - font-size: $font-size-h7; - line-height: 140%; + @include typography('h7'); } @mixin H8 { - font-style: normal; - font-weight: normal; - font-size: $font-size-h8; - line-height: 140%; + @include typography('h8'); } @mixin H9 { - font-style: normal; - font-weight: normal; - font-size: $font-size-h9; - line-height: 140%; + @include typography('h9'); } diff --git a/ui/app/ducks/gas/gas.duck.js b/ui/app/ducks/gas/gas.duck.js index 83b15ecf1..1bcc5d417 100644 --- a/ui/app/ducks/gas/gas.duck.js +++ b/ui/app/ducks/gas/gas.duck.js @@ -1,8 +1,10 @@ import { cloneDeep } from 'lodash' import BigNumber from 'bignumber.js' import { getStorageItem, setStorageItem } from '../../../lib/storage-helpers' - import { decGWEIToHexWEI } from '../../helpers/utils/conversions.util' +import getFetchWithTimeout from '../../../../shared/modules/fetch-with-timeout' + +const fetchWithTimeout = getFetchWithTimeout(30000) // Actions const BASIC_GAS_ESTIMATE_LOADING_FINISHED = @@ -97,7 +99,7 @@ export function basicGasEstimatesLoadingFinished() { async function basicGasPriceQuery() { const url = `https://api.metaswap.codefi.network/gasPrices` - return await window.fetch(url, { + return await fetchWithTimeout(url, { headers: {}, referrer: 'https://api.metaswap.codefi.network/gasPrices', referrerPolicy: 'no-referrer-when-downgrade', diff --git a/ui/app/ducks/metamask/metamask.js b/ui/app/ducks/metamask/metamask.js index 24180f0d3..cdc644a02 100644 --- a/ui/app/ducks/metamask/metamask.js +++ b/ui/app/ducks/metamask/metamask.js @@ -1,5 +1,6 @@ import * as actionConstants from '../../store/actionConstants' import { ALERT_TYPES } from '../../../../shared/constants/alerts' +import { NETWORK_TYPE_RPC } from '../../../../shared/constants/network' export default function reduceMetamask(state = {}, action) { const metamaskState = { @@ -63,7 +64,7 @@ export default function reduceMetamask(state = {}, action) { return { ...metamaskState, provider: { - type: 'rpc', + type: NETWORK_TYPE_RPC, rpcUrl: action.value, }, } diff --git a/ui/app/helpers/constants/common.js b/ui/app/helpers/constants/common.js index 573bab820..7a0503112 100644 --- a/ui/app/helpers/constants/common.js +++ b/ui/app/helpers/constants/common.js @@ -5,14 +5,6 @@ export const WEI = 'WEI' export const PRIMARY = 'PRIMARY' export const SECONDARY = 'SECONDARY' -export const NETWORK_TYPES = { - KOVAN: 'kovan', - MAINNET: 'mainnet', - RINKEBY: 'rinkeby', - ROPSTEN: 'ropsten', - GOERLI: 'goerli', -} - export const GAS_ESTIMATE_TYPES = { SLOW: 'SLOW', AVERAGE: 'AVERAGE', diff --git a/ui/app/helpers/constants/design-system.js b/ui/app/helpers/constants/design-system.js new file mode 100644 index 000000000..6d6512eba --- /dev/null +++ b/ui/app/helpers/constants/design-system.js @@ -0,0 +1,41 @@ +export const COLORS = { + UI1: 'ui-1', + UI2: 'ui-2', + UI3: 'ui-3', + UI4: 'ui-4', + BLACK: 'black', + WHITE: 'white', + PRIMARY1: 'primary-1', + PRIMARY2: 'primary-2', + PRIMARY3: 'primary-3', + SECONDARY1: 'secondary-1', + SECONDARY2: 'secondary-2', + SECONDARY3: 'secondary-3', + SUCCESS1: 'success-1', + SUCCESS2: 'success-2', + SUCCESS3: 'success-3', + ERROR1: 'error1', + ERROR2: 'error2', + ERROR3: 'error3', + ALERT1: 'alert-1', + ALERT2: 'alert-2', + ALERT3: 'alert-3', + MAINNET: 'mainnet', + ROPSTEN: 'ropsten', + KOVAN: 'kovan', + RINKEBY: 'rinkeby', + GOERLI: 'goerli', +} + +export const TYPOGRAPHY = { + H1: 'h1', + H2: 'h2', + H3: 'h3', + H4: 'h4', + H5: 'h5', + H6: 'h6', + H7: 'h7', + H8: 'h8', + H9: 'h9', + Paragraph: 'paragraph', +} diff --git a/ui/app/helpers/utils/fetch-with-cache.js b/ui/app/helpers/utils/fetch-with-cache.js index ca2bbd7f0..a903680c4 100644 --- a/ui/app/helpers/utils/fetch-with-cache.js +++ b/ui/app/helpers/utils/fetch-with-cache.js @@ -1,5 +1,5 @@ import { getStorageItem, setStorageItem } from '../../../lib/storage-helpers' -import fetchWithTimeout from '../../../../app/scripts/lib/fetch-with-timeout' +import getFetchWithTimeout from '../../../../shared/modules/fetch-with-timeout' const fetchWithCache = async ( url, @@ -29,8 +29,8 @@ const fetchWithCache = async ( return cachedResponse } fetchOptions.headers.set('Content-Type', 'application/json') - const _fetch = timeout ? fetchWithTimeout({ timeout }) : window.fetch - const response = await _fetch(url, { + const fetchWithTimeout = getFetchWithTimeout(timeout) + const response = await fetchWithTimeout(url, { referrerPolicy: 'no-referrer-when-downgrade', body: null, method: 'GET', diff --git a/ui/app/helpers/utils/i18n-helper.js b/ui/app/helpers/utils/i18n-helper.js index 140a12fff..bb8932683 100644 --- a/ui/app/helpers/utils/i18n-helper.js +++ b/ui/app/helpers/utils/i18n-helper.js @@ -1,9 +1,12 @@ // cross-browser connection to extension i18n API import React from 'react' import log from 'loglevel' - import * as Sentry from '@sentry/browser' +import getFetchWithTimeout from '../../../../shared/modules/fetch-with-timeout' + +const fetchWithTimeout = getFetchWithTimeout(30000) + const warned = {} const missingMessageErrors = {} const missingSubstitutionErrors = {} @@ -95,7 +98,7 @@ export const getMessage = (localeCode, localeMessages, key, substitutions) => { export async function fetchLocale(localeCode) { try { - const response = await window.fetch( + const response = await fetchWithTimeout( `./_locales/${localeCode}/messages.json`, ) return await response.json() @@ -120,7 +123,7 @@ export async function loadRelativeTimeFormatLocaleData(localeCode) { } async function fetchRelativeTimeFormatData(languageTag) { - const response = await window.fetch( + const response = await fetchWithTimeout( `./intl/${languageTag}/relative-time-format-data.json`, ) return await response.json() diff --git a/ui/app/helpers/utils/util.js b/ui/app/helpers/utils/util.js index 020ed9325..b88abc876 100644 --- a/ui/app/helpers/utils/util.js +++ b/ui/app/helpers/utils/util.js @@ -4,6 +4,9 @@ import BigNumber from 'bignumber.js' import ethUtil from 'ethereumjs-util' import { DateTime } from 'luxon' import { addHexPrefix } from '../../../../app/scripts/lib/util' +import getFetchWithTimeout from '../../../../shared/modules/fetch-with-timeout' + +const fetchWithTimeout = getFetchWithTimeout(30000) // formatData :: ( date: ) -> String export function formatDate(date, format = "M/d/y 'at' T") { @@ -478,19 +481,17 @@ export async function jsonRpcRequest(rpcUrl, rpcMethod, rpcParams = []) { headers.Authorization = `Basic ${encodedAuth}` fetchUrl = `${origin}${pathname}${search}` } - const jsonRpcResponse = await window - .fetch(fetchUrl, { - method: 'POST', - body: JSON.stringify({ - id: Date.now().toString(), - jsonrpc: '2.0', - method: rpcMethod, - params: rpcParams, - }), - headers, - cache: 'default', - }) - .then((httpResponse) => httpResponse.json()) + const jsonRpcResponse = await fetchWithTimeout(fetchUrl, { + method: 'POST', + body: JSON.stringify({ + id: Date.now().toString(), + jsonrpc: '2.0', + method: rpcMethod, + params: rpcParams, + }), + headers, + cache: 'default', + }).then((httpResponse) => httpResponse.json()) if ( !jsonRpcResponse || 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 2ef4e0ea3..b65af863b 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 @@ -4,7 +4,7 @@ import Button from '../../components/ui/button' import Identicon from '../../components/ui/identicon' import TokenBalance from '../../components/ui/token-balance' import { getEnvironmentType } from '../../../../app/scripts/lib/util' -import { ENVIRONMENT_TYPE_NOTIFICATION } from '../../../../app/scripts/lib/enums' +import { ENVIRONMENT_TYPE_NOTIFICATION } from '../../../../shared/constants/app' export default class ConfirmAddSuggestedToken extends Component { static contextTypes = { 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 a9f68d388..bb5366bfd 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 @@ -9,7 +9,7 @@ import Identicon from '../../components/ui/identicon' import Tooltip from '../../components/ui/tooltip' import Copy from '../../components/ui/icon/copy-icon.component' -import { ENVIRONMENT_TYPE_NOTIFICATION } from '../../../../app/scripts/lib/enums' +import { ENVIRONMENT_TYPE_NOTIFICATION } from '../../../../shared/constants/app' import { getEnvironmentType } from '../../../../app/scripts/lib/util' import { conversionUtil } from '../../helpers/utils/conversion-util' 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 c3d1dfaa2..a1c1178f7 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 @@ -5,7 +5,7 @@ import AccountListItem from '../../components/app/account-list-item' import Button from '../../components/ui/button' import Identicon from '../../components/ui/identicon' -import { ENVIRONMENT_TYPE_NOTIFICATION } from '../../../../app/scripts/lib/enums' +import { ENVIRONMENT_TYPE_NOTIFICATION } from '../../../../shared/constants/app' import { getEnvironmentType } from '../../../../app/scripts/lib/util' import { conversionUtil } from '../../helpers/utils/conversion-util' 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 24f452182..0b7d82ae0 100644 --- a/ui/app/pages/confirm-transaction-base/confirm-transaction-base.component.js +++ b/ui/app/pages/confirm-transaction-base/confirm-transaction-base.component.js @@ -1,7 +1,7 @@ import ethUtil from 'ethereumjs-util' import React, { Component } from 'react' import PropTypes from 'prop-types' -import { ENVIRONMENT_TYPE_NOTIFICATION } from '../../../../app/scripts/lib/enums' +import { ENVIRONMENT_TYPE_NOTIFICATION } from '../../../../shared/constants/app' import { getEnvironmentType } from '../../../../app/scripts/lib/util' import ConfirmPageContainer, { ConfirmDetailRow, diff --git a/ui/app/pages/confirm-transaction-switch/confirm-transaction-switch.component.js b/ui/app/pages/confirm-transaction-switch/confirm-transaction-switch.component.js index 88dd10084..0de4f2951 100644 --- a/ui/app/pages/confirm-transaction-switch/confirm-transaction-switch.component.js +++ b/ui/app/pages/confirm-transaction-switch/confirm-transaction-switch.component.js @@ -14,7 +14,7 @@ import { DECRYPT_MESSAGE_REQUEST_PATH, ENCRYPTION_PUBLIC_KEY_REQUEST_PATH, } from '../../helpers/constants/routes' -import { MESSAGE_TYPE } from '../../../../app/scripts/lib/enums' +import { MESSAGE_TYPE } from '../../../../shared/constants/app' import { TRANSACTION_CATEGORIES } from '../../../../shared/constants/transaction' export default class ConfirmTransactionSwitch extends Component { diff --git a/ui/app/pages/confirm-transaction/conf-tx.js b/ui/app/pages/confirm-transaction/conf-tx.js index cbf700548..3298baae6 100644 --- a/ui/app/pages/confirm-transaction/conf-tx.js +++ b/ui/app/pages/confirm-transaction/conf-tx.js @@ -10,7 +10,7 @@ import SignatureRequest from '../../components/app/signature-request' import SignatureRequestOriginal from '../../components/app/signature-request-original' import Loading from '../../components/ui/loading-screen' import { getMostRecentOverviewPage } from '../../ducks/history/history' -import { MESSAGE_TYPE } from '../../../../app/scripts/lib/enums' +import { MESSAGE_TYPE } from '../../../../shared/constants/app' import { TRANSACTION_STATUSES } from '../../../../shared/constants/transaction' function mapStateToProps(state) { 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 b819c81be..2cf315ae7 100644 --- a/ui/app/pages/create-account/connect-hardware/account-list.js +++ b/ui/app/pages/create-account/connect-hardware/account-list.js @@ -90,7 +90,7 @@ class AccountList extends Component { name="selectedAccount" id={`address-${idx}`} value={account.index} - onChange={(e) => this.props.onAccountChange(e.target.value)} + onClick={(e) => this.props.onAccountChange(e.target.value)} checked={ this.props.selectedAccount === account.index.toString() } diff --git a/ui/app/pages/error/error.component.js b/ui/app/pages/error/error.component.js index d3fe6f756..e7e9ff6ed 100644 --- a/ui/app/pages/error/error.component.js +++ b/ui/app/pages/error/error.component.js @@ -1,7 +1,7 @@ import React, { PureComponent } from 'react' import PropTypes from 'prop-types' import { getEnvironmentType } from '../../../../app/scripts/lib/util' -import { ENVIRONMENT_TYPE_POPUP } from '../../../../app/scripts/lib/enums' +import { ENVIRONMENT_TYPE_POPUP } from '../../../../shared/constants/app' class ErrorPage extends PureComponent { static contextTypes = { diff --git a/ui/app/pages/home/home.container.js b/ui/app/pages/home/home.container.js index fedebf4ad..ba4b9e6d4 100644 --- a/ui/app/pages/home/home.container.js +++ b/ui/app/pages/home/home.container.js @@ -33,7 +33,7 @@ import { getEnvironmentType } from '../../../../app/scripts/lib/util' import { ENVIRONMENT_TYPE_NOTIFICATION, ENVIRONMENT_TYPE_POPUP, -} from '../../../../app/scripts/lib/enums' +} from '../../../../shared/constants/app' import { ALERT_TYPES, WEB3_SHIM_USAGE_ALERT_STATES, diff --git a/ui/app/pages/permissions-connect/permissions-connect.component.js b/ui/app/pages/permissions-connect/permissions-connect.component.js index bb16d1425..06a4f136c 100644 --- a/ui/app/pages/permissions-connect/permissions-connect.component.js +++ b/ui/app/pages/permissions-connect/permissions-connect.component.js @@ -2,7 +2,7 @@ import PropTypes from 'prop-types' import React, { Component } from 'react' import { Switch, Route } from 'react-router-dom' import { getEnvironmentType } from '../../../../app/scripts/lib/util' -import { ENVIRONMENT_TYPE_NOTIFICATION } from '../../../../app/scripts/lib/enums' +import { ENVIRONMENT_TYPE_NOTIFICATION } from '../../../../shared/constants/app' import { DEFAULT_ROUTE } from '../../helpers/constants/routes' import PermissionPageContainer from '../../components/app/permission-page-container' import ChooseAccount from './choose-account' diff --git a/ui/app/pages/routes/routes.component.js b/ui/app/pages/routes/routes.component.js index 04db4f0e9..5aaf80124 100644 --- a/ui/app/pages/routes/routes.component.js +++ b/ui/app/pages/routes/routes.component.js @@ -58,7 +58,7 @@ import { import { ENVIRONMENT_TYPE_NOTIFICATION, ENVIRONMENT_TYPE_POPUP, -} from '../../../../app/scripts/lib/enums' +} from '../../../../shared/constants/app' import { getEnvironmentType } from '../../../../app/scripts/lib/util' import { TRANSACTION_STATUSES } from '../../../../shared/constants/transaction' 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 e8c498060..a1d884e79 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 @@ -13,7 +13,7 @@ import { isValidAddress, isValidAddressHead, } from '../../../../helpers/utils/util' -import { MAINNET_NETWORK_ID } from '../../../../../../app/scripts/controllers/network/enums' +import { MAINNET_NETWORK_ID } from '../../../../../../shared/constants/network' // Local Constants const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000' 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 5d9139014..101daf7ab 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 @@ -2,7 +2,7 @@ import { compose } from 'redux' import { connect } from 'react-redux' import { withRouter } from 'react-router-dom' import { getAddressBook } from '../../../selectors' -import { ENVIRONMENT_TYPE_POPUP } from '../../../../../app/scripts/lib/enums' +import { ENVIRONMENT_TYPE_POPUP } from '../../../../../shared/constants/app' import { getEnvironmentType } from '../../../../../app/scripts/lib/util' import { diff --git a/ui/app/pages/settings/info-tab/index.scss b/ui/app/pages/settings/info-tab/index.scss index 88216c64a..41187cc37 100644 --- a/ui/app/pages/settings/info-tab/index.scss +++ b/ui/app/pages/settings/info-tab/index.scss @@ -6,7 +6,10 @@ &__logo { max-height: 100%; - max-width: 100%; + max-width: 50%; + display: block; + margin-left: auto; + margin-right: auto; } &__item { 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 0e8118910..08e4777df 100644 --- a/ui/app/pages/settings/info-tab/info-tab.component.js +++ b/ui/app/pages/settings/info-tab/info-tab.component.js @@ -95,13 +95,6 @@ export default class InfoTab extends PureComponent {
-
- -
{t('metamaskVersion')} @@ -116,6 +109,9 @@ export default class InfoTab extends PureComponent {
{this.renderInfoLinks()}
+
+ +
) } 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 df2c0c029..00e66cca8 100644 --- a/ui/app/pages/settings/networks-tab/networks-tab.component.js +++ b/ui/app/pages/settings/networks-tab/networks-tab.component.js @@ -1,6 +1,7 @@ import React, { PureComponent } from 'react' import PropTypes from 'prop-types' import classnames from 'classnames' +import { NETWORK_TYPE_RPC } from '../../../../../shared/constants/network' import Button from '../../../components/ui/button' import LockIcon from '../../../components/ui/lock-icon' import { @@ -90,7 +91,7 @@ export default class NetworksTab extends PureComponent { const listItemNetworkIsSelected = selectRpcUrl && selectRpcUrl === rpcUrl const listItemUrlIsProviderUrl = rpcUrl === providerUrl const listItemTypeIsProviderNonRpcType = - providerType !== 'rpc' && currentProviderType === providerType + providerType !== NETWORK_TYPE_RPC && currentProviderType === providerType const listItemNetworkIsCurrentProvider = !networkIsSelected && !networksTabIsInAddMode && @@ -118,12 +119,12 @@ export default class NetworksTab extends PureComponent { className={classnames('networks-tab__networks-list-name', { 'networks-tab__networks-list-name--selected': displayNetworkListItemAsSelected, 'networks-tab__networks-list-name--disabled': - currentProviderType !== 'rpc' && + currentProviderType !== NETWORK_TYPE_RPC && !displayNetworkListItemAsSelected, })} > {label || this.context.t(labelKey)} - {currentProviderType !== 'rpc' && ( + {currentProviderType !== NETWORK_TYPE_RPC && ( )}
diff --git a/ui/app/pages/settings/networks-tab/networks-tab.constants.js b/ui/app/pages/settings/networks-tab/networks-tab.constants.js index 0271abcfc..9a9eb9699 100644 --- a/ui/app/pages/settings/networks-tab/networks-tab.constants.js +++ b/ui/app/pages/settings/networks-tab/networks-tab.constants.js @@ -9,7 +9,7 @@ import { RINKEBY_CHAIN_ID, ROPSTEN, ROPSTEN_CHAIN_ID, -} from '../../../../../app/scripts/controllers/network/enums' +} from '../../../../../shared/constants/network' const defaultNetworksData = [ { diff --git a/ui/app/pages/settings/networks-tab/networks-tab.container.js b/ui/app/pages/settings/networks-tab/networks-tab.container.js index 94fcddc81..14f5d3929 100644 --- a/ui/app/pages/settings/networks-tab/networks-tab.container.js +++ b/ui/app/pages/settings/networks-tab/networks-tab.container.js @@ -10,7 +10,8 @@ import { showModal, } from '../../../store/actions' import { NETWORKS_FORM_ROUTE } from '../../../helpers/constants/routes' -import { ENVIRONMENT_TYPE_FULLSCREEN } from '../../../../../app/scripts/lib/enums' +import { ENVIRONMENT_TYPE_FULLSCREEN } from '../../../../../shared/constants/app' +import { NETWORK_TYPE_RPC } from '../../../../../shared/constants/network' import { getEnvironmentType } from '../../../../../app/scripts/lib/util' import NetworksTab from './networks-tab.component' import { defaultNetworksData } from './networks-tab.constants' @@ -37,7 +38,7 @@ const mapStateToProps = (state, ownProps) => { return { label: rpc.nickname, iconColor: '#6A737D', - providerType: 'rpc', + providerType: NETWORK_TYPE_RPC, rpcUrl: rpc.rpcUrl, chainId: rpc.chainId, ticker: rpc.ticker, @@ -61,7 +62,7 @@ const mapStateToProps = (state, ownProps) => { networksToRender.find((network) => { return ( network.rpcUrl === provider.rpcUrl || - (network.providerType !== 'rpc' && + (network.providerType !== NETWORK_TYPE_RPC && network.providerType === provider.type) ) }) || {} diff --git a/ui/app/pages/settings/settings.container.js b/ui/app/pages/settings/settings.container.js index ffade71da..d35fbbe6d 100644 --- a/ui/app/pages/settings/settings.container.js +++ b/ui/app/pages/settings/settings.container.js @@ -3,7 +3,7 @@ import { connect } from 'react-redux' import { withRouter } from 'react-router-dom' import { getAddressBookEntryName } from '../../selectors' import { isValidAddress } from '../../helpers/utils/util' -import { ENVIRONMENT_TYPE_POPUP } from '../../../../app/scripts/lib/enums' +import { ENVIRONMENT_TYPE_POPUP } from '../../../../shared/constants/app' import { getEnvironmentType } from '../../../../app/scripts/lib/util' import { getMostRecentOverviewPage } from '../../ducks/history/history' diff --git a/ui/app/pages/swaps/index.js b/ui/app/pages/swaps/index.js index 01c1f8f78..ca720910d 100644 --- a/ui/app/pages/swaps/index.js +++ b/ui/app/pages/swaps/index.js @@ -48,7 +48,7 @@ import { SWAP_FAILED_ERROR, OFFLINE_FOR_MAINTENANCE, } from '../../helpers/constants/swaps' -import { MAINNET_CHAIN_ID } from '../../../../app/scripts/controllers/network/enums' +import { MAINNET_CHAIN_ID } from '../../../../shared/constants/network' import { resetBackgroundSwapsState, diff --git a/ui/app/pages/swaps/swaps.util.js b/ui/app/pages/swaps/swaps.util.js index 81876d947..0fcc5d8a2 100644 --- a/ui/app/pages/swaps/swaps.util.js +++ b/ui/app/pages/swaps/swaps.util.js @@ -467,11 +467,11 @@ export function quotesToRenderableData( } = quote const sourceValue = calcTokenAmount( sourceAmount, - sourceTokenInfo.decimals || 18, + sourceTokenInfo.decimals, ).toString(10) const destinationValue = calcTokenAmount( destinationAmount, - destinationTokenInfo.decimals || 18, + destinationTokenInfo.decimals, ).toPrecision(8) const { @@ -501,14 +501,11 @@ export function quotesToRenderableData( destinationTokenInfo.symbol === 'ETH' ? calcTokenAmount( destinationAmount, - destinationTokenInfo.decimals || 18, + destinationTokenInfo.decimals, ).minus(rawEthFee, 10) : new BigNumber(tokenConversionRate || 0, 10) .times( - calcTokenAmount( - destinationAmount, - destinationTokenInfo.decimals || 18, - ), + calcTokenAmount(destinationAmount, destinationTokenInfo.decimals), 10, ) .minus(rawEthFee, 10) diff --git a/ui/app/pages/swaps/view-quote/tests/view-quote-price-difference.test.js b/ui/app/pages/swaps/view-quote/tests/view-quote-price-difference.test.js index d32cc5759..bf37e0061 100644 --- a/ui/app/pages/swaps/view-quote/tests/view-quote-price-difference.test.js +++ b/ui/app/pages/swaps/view-quote/tests/view-quote-price-difference.test.js @@ -3,6 +3,7 @@ import React from 'react' import { shallow } from 'enzyme' import { Provider } from 'react-redux' import configureMockStore from 'redux-mock-store' +import { NETWORK_TYPE_RPC } from '../../../../../../shared/constants/network' import ViewQuotePriceDifference from '../view-quote-price-difference' describe('View Price Quote Difference', function () { @@ -11,7 +12,7 @@ describe('View Price Quote Difference', function () { const state = { metamask: { tokens: [], - provider: { type: 'rpc', nickname: '', rpcUrl: '' }, + provider: { type: NETWORK_TYPE_RPC, nickname: '', rpcUrl: '' }, preferences: { showFiatInTestnets: true }, currentCurrency: 'usd', conversionRate: 600.0, diff --git a/ui/app/pages/swaps/view-quote/view-quote.js b/ui/app/pages/swaps/view-quote/view-quote.js index bdceee91f..6a9ab838f 100644 --- a/ui/app/pages/swaps/view-quote/view-quote.js +++ b/ui/app/pages/swaps/view-quote/view-quote.js @@ -83,6 +83,7 @@ export default function ViewQuote() { const metaMetricsEvent = useContext(MetaMetricsContext) const [dispatchedSafeRefetch, setDispatchedSafeRefetch] = useState(false) + const [submitClicked, setSubmitClicked] = useState(false) const [selectQuotePopoverShown, setSelectQuotePopoverShown] = useState(false) const [warningHidden, setWarningHidden] = useState(false) const [originalApproveAmount, setOriginalApproveAmount] = useState(null) @@ -570,6 +571,7 @@ export default function ViewQuote() {
{ + setSubmitClicked(true) if (!balanceError) { dispatch(signAndSendTransactions(history, metaMetricsEvent)) } else if (destinationToken.symbol === 'ETH') { @@ -580,7 +582,12 @@ export default function ViewQuote() { }} submitText={t('swap')} onCancel={async () => await dispatch(navigateBackToBuildQuote(history))} - disabled={balanceError || gasPrice === null || gasPrice === undefined} + disabled={ + submitClicked || + balanceError || + gasPrice === null || + gasPrice === undefined + } className={isShowingWarning && 'view-quote__thin-swaps-footer'} showTopBorder /> diff --git a/ui/app/pages/unlock-page/unlock-page.container.js b/ui/app/pages/unlock-page/unlock-page.container.js index 222d8b04a..9284ebeba 100644 --- a/ui/app/pages/unlock-page/unlock-page.container.js +++ b/ui/app/pages/unlock-page/unlock-page.container.js @@ -2,7 +2,7 @@ import { connect } from 'react-redux' import { withRouter } from 'react-router-dom' import { compose } from 'redux' import { getEnvironmentType } from '../../../../app/scripts/lib/util' -import { ENVIRONMENT_TYPE_POPUP } from '../../../../app/scripts/lib/enums' +import { ENVIRONMENT_TYPE_POPUP } from '../../../../shared/constants/app' import { DEFAULT_ROUTE, RESTORE_VAULT_ROUTE, diff --git a/ui/app/selectors/permissions.js b/ui/app/selectors/permissions.js index a463d09d0..e6dfa4db5 100644 --- a/ui/app/selectors/permissions.js +++ b/ui/app/selectors/permissions.js @@ -1,5 +1,5 @@ import { forOwn } from 'lodash' -import { CAVEAT_NAMES } from '../../../app/scripts/controllers/permissions/enums' +import { CAVEAT_NAMES } from '../../../shared/constants/permissions' import { getMetaMaskAccountsOrdered, getOriginOfCurrentTab, diff --git a/ui/app/selectors/selectors.js b/ui/app/selectors/selectors.js index 5607476a8..9db335a85 100644 --- a/ui/app/selectors/selectors.js +++ b/ui/app/selectors/selectors.js @@ -1,7 +1,7 @@ import { stripHexPrefix } from 'ethereumjs-util' import { createSelector } from 'reselect' import { addHexPrefix } from '../../../app/scripts/lib/util' -import { NETWORK_TYPES } from '../helpers/constants/common' +import { MAINNET, NETWORK_TYPE_RPC } from '../../../shared/constants/network' import { shortenAddress, checksumAddress, @@ -21,7 +21,7 @@ export function getNetworkIdentifier(state) { export function getMetricsNetworkIdentifier(state) { const { provider } = state.metamask - return provider.type === 'rpc' ? provider.rpcUrl : provider.type + return provider.type === NETWORK_TYPE_RPC ? provider.rpcUrl : provider.type } export function getCurrentChainId(state) { @@ -281,7 +281,7 @@ function getSuggestedTokenCount(state) { export function getIsMainnet(state) { const networkType = getNetworkIdentifier(state) - return networkType === NETWORK_TYPES.MAINNET + return networkType === MAINNET } export function getPreferences({ metamask }) { diff --git a/ui/app/store/actions.js b/ui/app/store/actions.js index 780bb81c1..0dd31dc9f 100644 --- a/ui/app/store/actions.js +++ b/ui/app/store/actions.js @@ -12,7 +12,7 @@ import { import { getMethodDataAsync } from '../helpers/utils/transactions.util' import { fetchSymbolAndDecimals } from '../helpers/utils/token-util' import switchDirection from '../helpers/utils/switch-direction' -import { ENVIRONMENT_TYPE_NOTIFICATION } from '../../../app/scripts/lib/enums' +import { ENVIRONMENT_TYPE_NOTIFICATION } from '../../../shared/constants/app' import { hasUnconfirmedTransactions } from '../helpers/utils/confirm-tx.util' import { setCustomGasLimit } from '../ducks/gas/gas.duck' import txHelper from '../../lib/tx-helper' diff --git a/ui/index.js b/ui/index.js index 6c4541f17..3f0e172f8 100644 --- a/ui/index.js +++ b/ui/index.js @@ -6,7 +6,7 @@ import { render } from 'react-dom' import { getEnvironmentType } from '../app/scripts/lib/util' import { ALERT_TYPES } from '../shared/constants/alerts' import { SENTRY_STATE } from '../app/scripts/lib/setupSentry' -import { ENVIRONMENT_TYPE_POPUP } from '../app/scripts/lib/enums' +import { ENVIRONMENT_TYPE_POPUP } from '../shared/constants/app' import Root from './app/pages' import * as actions from './app/store/actions' import configureStore from './app/store/store' diff --git a/ui/lib/etherscan-prefix-for-network.js b/ui/lib/etherscan-prefix-for-network.js index 32183d1bc..82e92f3b1 100644 --- a/ui/lib/etherscan-prefix-for-network.js +++ b/ui/lib/etherscan-prefix-for-network.js @@ -1,4 +1,4 @@ -import * as networkEnums from '../../app/scripts/controllers/network/enums' +import * as networkEnums from '../../shared/constants/network' /** * Gets the etherscan.io URL prefix for a given network ID. diff --git a/ui/lib/webcam-utils.js b/ui/lib/webcam-utils.js index a242186df..6c451fd21 100644 --- a/ui/lib/webcam-utils.js +++ b/ui/lib/webcam-utils.js @@ -4,7 +4,7 @@ import { ENVIRONMENT_TYPE_POPUP, PLATFORM_BRAVE, PLATFORM_FIREFOX, -} from '../../app/scripts/lib/enums' +} from '../../shared/constants/app' import { getEnvironmentType, getPlatform } from '../../app/scripts/lib/util' class WebcamUtils { diff --git a/yarn.lock b/yarn.lock index f7a2f4e6e..411f8b64c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6708,6 +6708,21 @@ chokidar@3.3.0: optionalDependencies: fsevents "~2.1.1" +"chokidar@>=2.0.0 <4.0.0": + version "3.5.1" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.1.tgz#ee9ce7bbebd2b79f49f304799d5468e31e14e68a" + integrity sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw== + dependencies: + anymatch "~3.1.1" + braces "~3.0.2" + glob-parent "~5.1.0" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.5.0" + optionalDependencies: + fsevents "~2.3.1" + chokidar@^2.0.0, chokidar@^2.1.1, chokidar@^2.1.8: version "2.1.8" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917" @@ -11633,6 +11648,11 @@ fsevents@~2.1.1, fsevents@~2.1.2: resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.3.tgz#fb738703ae8d2f9fe900c33836ddebee8b97f23e" integrity sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ== +fsevents@~2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.1.tgz#b209ab14c61012636c8863507edf7fb68cc54e9f" + integrity sha512-YR47Eg4hChJGAB1O3yEAOkGO+rlzutoICGqGo9EZ4lKWokzZRSyIW1QmTzqjtw8MJdj9srP869CuWw/hyzSiBw== + fsm-event@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fsm-event/-/fsm-event-2.1.0.tgz#d385716ed38f9c92feab2ba601e2aac6c0ba5a92" @@ -12586,13 +12606,13 @@ gulp-rtlcss@^1.4.0: through2 "^2.0.5" vinyl-sourcemaps-apply "^0.2.1" -gulp-sass@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/gulp-sass/-/gulp-sass-4.0.1.tgz#7f43d117eb2d303524968a1b48494af1bc64d1d9" - integrity sha512-OMQEgWNggpog8Tc5v1MuI6eo+5iiPkVeLL76iBhDoEEScLUPfZlpvzmgTnLkpcqdrNodZxpz5qcv6mS2rulk3g== +gulp-sass@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/gulp-sass/-/gulp-sass-4.1.0.tgz#486d7443c32d42bf31a6b1573ebbdaa361de7427" + integrity sha512-xIiwp9nkBLcJDpmYHbEHdoWZv+j+WtYaKD6Zil/67F3nrAaZtWYN5mDwerdo7EvcdBenSAj7Xb2hx2DqURLGdA== dependencies: chalk "^2.3.0" - lodash.clonedeep "^4.3.2" + lodash "^4.17.11" node-sass "^4.8.3" plugin-error "^1.0.1" replace-ext "^1.0.0" @@ -15644,6 +15664,11 @@ klaw@^1.0.0: optionalDependencies: graceful-fs "^4.1.9" +klona@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.4.tgz#7bb1e3affb0cb8624547ef7e8f6708ea2e39dfc0" + integrity sha512-ZRbnvdg/NxqzC7L9Uyqzf4psi1OM4Cuc+sJAkQPjO6XkQIJTNbfK2Rsmbw8fx1p2mkZdp2FZYo2+LwXYY/uwIA== + knex@^0.15.2: version "0.15.2" resolved "https://registry.yarnpkg.com/knex/-/knex-0.15.2.tgz#6059b87489605f4cc87599a6d2a9d265709e9340" @@ -16545,7 +16570,7 @@ loader-runner@^2.4.0: resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357" integrity sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw== -loader-utils@1.2.3, loader-utils@^1.0.1, loader-utils@^1.0.2, loader-utils@^1.1.0, loader-utils@^1.2.3: +loader-utils@1.2.3, loader-utils@^1.0.2, loader-utils@^1.1.0, loader-utils@^1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.2.3.tgz#1ff5dc6911c9f0a062531a4c04b609406108c2c7" integrity sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA== @@ -16646,7 +16671,7 @@ lodash.assign@^4.2.0: resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7" integrity sha1-DZnzzNem0mHRm9rrkkUAXShYCOc= -lodash.clonedeep@4.5.0, lodash.clonedeep@^4.3.2: +lodash.clonedeep@4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8= @@ -16746,11 +16771,6 @@ lodash.sortby@^4.7.0: resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg= -lodash.tail@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/lodash.tail/-/lodash.tail-4.1.1.tgz#d2333a36d9e7717c8ad2f7cacafec7c32b444664" - integrity sha1-0jM6NtnncXyK0vfKyv7HwytERmQ= - lodash.throttle@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4" @@ -18025,6 +18045,11 @@ neo-async@^2.5.0, neo-async@^2.6.1: resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.1.tgz#ac27ada66167fa8849a6addd837f6b189ad2081c" integrity sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw== +neo-async@^2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" + integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== + nested-error-stacks@^2.0.0, nested-error-stacks@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/nested-error-stacks/-/nested-error-stacks-2.1.0.tgz#0fbdcf3e13fe4994781280524f8b96b0cdff9c61" @@ -18255,7 +18280,7 @@ node-releases@^1.1.52, node-releases@^1.1.66: resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.67.tgz#28ebfcccd0baa6aad8e8d4d8fe4cbc49ae239c12" integrity sha512-V5QF9noGFl3EymEwUYzO+3NTDpGfQB4ve6Qfnzf3UNydMhjQRVPR1DZTuvWiLzaFJYw2fmDwAfnRNEVb64hSIg== -node-sass@^4.14.1, node-sass@^4.8.3: +node-sass@^4.8.3: version "4.14.1" resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.14.1.tgz#99c87ec2efb7047ed638fb4c9db7f3a42e2217b5" integrity sha512-sjCuOlvGyCJS40R8BscF5vhVlQjNN069NtQ1gSxyK1u9iqvn6tf7O1R4GNowVZfiZUCRt5MmMs1xd+4V/7Yr0g== @@ -22428,16 +22453,23 @@ sass-graph@2.2.5: scss-tokenizer "^0.2.3" yargs "^13.3.2" -sass-loader@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-7.0.1.tgz#fd937259ccba3a9cfe0d5f8a98746d48adfcc261" - integrity sha512-MeVVJFejJELlAbA7jrRchi88PGP6U9yIfqyiG+bBC4a9s2PX+ulJB9h8bbEohtPBfZmlLhNZ0opQM9hovRXvlw== +sass-loader@^10.1.1: + version "10.1.1" + resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-10.1.1.tgz#4ddd5a3d7638e7949065dd6e9c7c04037f7e663d" + integrity sha512-W6gVDXAd5hR/WHsPicvZdjAWHBcEJ44UahgxcIE196fW2ong0ZHMPO1kZuI5q0VlvMQZh32gpv69PLWQm70qrw== dependencies: - clone-deep "^2.0.1" - loader-utils "^1.0.1" - lodash.tail "^4.1.1" - neo-async "^2.5.0" - pify "^3.0.0" + klona "^2.0.4" + loader-utils "^2.0.0" + neo-async "^2.6.2" + schema-utils "^3.0.0" + semver "^7.3.2" + +sass@^1.32.4: + version "1.32.4" + resolved "https://registry.yarnpkg.com/sass/-/sass-1.32.4.tgz#308bf29dd7f53d44ae4f06580e9a910ad9aa411e" + integrity sha512-N0BT0PI/t3+gD8jKa83zJJUb7ssfQnRRfqN+GIErokW6U4guBpfYl8qYB+OFLEho+QvnV5ZH1R9qhUC/Z2Ch9w== + dependencies: + chokidar ">=2.0.0 <4.0.0" sax@^1.2.1, sax@^1.2.4, sax@~1.2.4: version "1.2.4"