Merge remote-tracking branch 'origin/develop' into sync-master

* origin/develop: (29 commits)
  Reset swaps routeState in navigateBackToBuildQuote (#10166)
  Fix decrypt message confirmation UI crash (#10252)
  Fix site metadata JSON-RPC handler (#10243)
  Fix design system error constants (#10246)
  Remove unused environment variables (#10234)
  Update `yarn.lock` (#10241)
  Update postMessage structure for TrezorConnect 8 (#10192)
  Increase minimum Firefox version to v68 (#10195)
  Bump socket.io from 2.2.0 to 2.4.1 (#10232)
  Update `@reduxjs/toolkit` from v1.3.2 to v1.5.0 (#10228)
  eth-rpc-errors@4.0.2 (#10226)
  Add MAX_SAFE_CHAIN_ID and refactor chain ID validation (#10224)
  add chip component (#10199)
  add new typography component (#10197)
  @metamask/inpage-provider@8.0.3 (#10219)
  Add NETWORK_TYPE_RPC constant (#10203)
  Further improve organization of constants (#10200)
  add includePaths to sass-loader in storybook (#10213)
  Disable the swaps submit button after the first time it is clicked (#10162)
  Remove default to 18 decimals in quotesToRenderableData method (#10212)
  ...
feature/default_network_editable
Mark Stacey 4 years ago
commit 74ee13f7c3
  1. 1
      .prettierignore
  2. 19
      .storybook/main.js
  3. 3
      README.md
  4. 3
      app/_locales/en/messages.json
  5. 2
      app/manifest/firefox.json
  6. 12
      app/scripts/background.js
  7. 0
      app/scripts/constants/contracts.js
  8. 5
      app/scripts/controllers/detect-tokens.js
  9. 10
      app/scripts/controllers/incoming-transactions.js
  10. 2
      app/scripts/controllers/metametrics.js
  11. 2
      app/scripts/controllers/network/createInfuraClient.js
  12. 40
      app/scripts/controllers/network/network.js
  13. 2
      app/scripts/controllers/network/util.js
  14. 5
      app/scripts/controllers/permissions/enums.js
  15. 11
      app/scripts/controllers/permissions/index.js
  16. 2
      app/scripts/controllers/permissions/permissionsLog.js
  17. 2
      app/scripts/controllers/permissions/permissionsMethodMiddleware.js
  18. 6
      app/scripts/controllers/preferences.js
  19. 5
      app/scripts/controllers/token-rates.js
  20. 2
      app/scripts/controllers/transactions/index.js
  21. 2
      app/scripts/controllers/transactions/lib/util.js
  22. 4
      app/scripts/lib/account-tracker.js
  23. 4
      app/scripts/lib/decrypt-message-manager.js
  24. 4
      app/scripts/lib/encryption-public-key-manager.js
  25. 7
      app/scripts/lib/ens-ipfs/setup.js
  26. 4
      app/scripts/lib/message-manager.js
  27. 5
      app/scripts/lib/network-store.js
  28. 4
      app/scripts/lib/personal-message-manager.js
  29. 2
      app/scripts/lib/rpc-method-middleware/handlers/get-provider-state.js
  30. 2
      app/scripts/lib/rpc-method-middleware/handlers/log-web3-shim-usage.js
  31. 2
      app/scripts/lib/rpc-method-middleware/handlers/watch-asset.js
  32. 4
      app/scripts/lib/typed-message-manager.js
  33. 18
      app/scripts/lib/util.js
  34. 8
      app/scripts/metamask-controller.js
  35. 2
      app/scripts/migrations/051.js
  36. 2
      app/scripts/platforms/extension.js
  37. 6
      app/scripts/ui.js
  38. 2
      app/vendor/trezor/content-script.js
  39. 2
      babel.config.js
  40. 2
      development/build/scripts.js
  41. 2
      development/build/styles.js
  42. 12
      package.json
  43. 34
      shared/constants/app.js
  44. 2
      shared/constants/metametrics.js
  45. 7
      shared/constants/network.js
  46. 4
      shared/constants/permissions.js
  47. 3
      shared/modules/README.md
  48. 12
      shared/modules/fetch-with-timeout.js
  49. 30
      shared/modules/utils.js
  50. 3
      test/unit/actions/config_test.js
  51. 5
      test/unit/app/controllers/detect-tokens-test.js
  52. 2
      test/unit/app/controllers/incoming-transactions-test.js
  53. 2
      test/unit/app/controllers/metametrics-test.js
  54. 6
      test/unit/app/controllers/permissions/mocks.js
  55. 2
      test/unit/app/controllers/swaps-test.js
  56. 29
      test/unit/app/fetch-with-timeout.test.js
  57. 4
      test/unit/app/util-test.js
  58. 4
      test/unit/localhostState.js
  59. 2
      test/unit/migrations/051-test.js
  60. 2
      ui/app/components/app/account-menu/account-menu.component.js
  61. 2
      ui/app/components/app/confirm-page-container/confirm-page-container-header/confirm-page-container-header.component.js
  62. 11
      ui/app/components/app/dropdowns/network-dropdown.js
  63. 5
      ui/app/components/app/loading-network-screen/loading-network-screen.container.js
  64. 2
      ui/app/components/app/menu-bar/account-options-menu.js
  65. 2
      ui/app/components/app/menu-bar/menu-bar.js
  66. 2
      ui/app/components/app/modals/modal.js
  67. 2
      ui/app/components/app/modals/qr-scanner/qr-scanner.component.js
  68. 46
      ui/app/components/app/network-display/network-display.component.js
  69. 10
      ui/app/components/app/network-display/network-display.container.js
  70. 2
      ui/app/components/app/signature-request-original/signature-request-original.component.js
  71. 2
      ui/app/components/app/signature-request-original/signature-request-original.container.js
  72. 2
      ui/app/components/app/signature-request/signature-request.constants.js
  73. 2
      ui/app/components/app/signature-request/signature-request.container.js
  74. 2
      ui/app/components/app/wallet-overview/eth-overview.js
  75. 2
      ui/app/components/app/wallet-overview/token-overview.js
  76. 55
      ui/app/components/ui/chip/chip.js
  77. 48
      ui/app/components/ui/chip/chip.scss
  78. 82
      ui/app/components/ui/chip/chip.stories.js
  79. 1
      ui/app/components/ui/chip/index.js
  80. 1
      ui/app/components/ui/typography/index.js
  81. 58
      ui/app/components/ui/typography/typography.js
  82. 38
      ui/app/components/ui/typography/typography.scss
  83. 53
      ui/app/components/ui/typography/typography.stories.js
  84. 2
      ui/app/components/ui/ui-components.scss
  85. 64
      ui/app/css/design-system/colors.scss
  86. 10
      ui/app/css/design-system/index.scss
  87. 101
      ui/app/css/design-system/typography.scss
  88. 6
      ui/app/ducks/gas/gas.duck.js
  89. 3
      ui/app/ducks/metamask/metamask.js
  90. 2
      ui/app/ducks/swaps/swaps.js
  91. 8
      ui/app/helpers/constants/common.js
  92. 42
      ui/app/helpers/constants/design-system.js
  93. 6
      ui/app/helpers/utils/fetch-with-cache.js
  94. 9
      ui/app/helpers/utils/i18n-helper.js
  95. 9
      ui/app/helpers/utils/util.js
  96. 2
      ui/app/pages/confirm-add-suggested-token/confirm-add-suggested-token.component.js
  97. 2
      ui/app/pages/confirm-decrypt-message/confirm-decrypt-message.component.js
  98. 2
      ui/app/pages/confirm-encryption-public-key/confirm-encryption-public-key.component.js
  99. 2
      ui/app/pages/confirm-transaction-base/confirm-transaction-base.component.js
  100. 2
      ui/app/pages/confirm-transaction-switch/confirm-transaction-switch.component.js
  101. Some files were not shown because too many files have changed in this diff Show More

@ -7,3 +7,4 @@ app/vendor/**
.nyc_output/** .nyc_output/**
.vscode/** .vscode/**
test/e2e/send-eth-with-private-key-test/** test/e2e/send-eth-with-private-key-test/**
*.scss

@ -7,7 +7,7 @@ module.exports = {
addons: [ addons: [
'@storybook/addon-knobs', '@storybook/addon-knobs',
'@storybook/addon-actions', '@storybook/addon-actions',
'@storybook/addon-backgrounds' '@storybook/addon-backgrounds',
], ],
webpackFinal: async (config) => { webpackFinal: async (config) => {
config.module.strictExportPresence = true config.module.strictExportPresence = true
@ -27,18 +27,29 @@ module.exports = {
loader: 'sass-loader', loader: 'sass-loader',
options: { options: {
sourceMap: true, sourceMap: true,
implementation: require('sass'),
sassOptions: {
includePaths: ['ui/app/css/'],
},
}, },
}, },
], ],
}) })
config.plugins.push(new CopyWebpackPlugin({ config.plugins.push(
new CopyWebpackPlugin({
patterns: [ patterns: [
{ {
from: path.join('node_modules', '@fortawesome', 'fontawesome-free', 'webfonts'), from: path.join(
'node_modules',
'@fortawesome',
'fontawesome-free',
'webfonts',
),
to: path.join('fonts', 'fontawesome'), to: path.join('fonts', 'fontawesome'),
}, },
], ],
})) }),
)
return config return config
}, },
} }

@ -1,5 +1,8 @@
# MetaMask Browser Extension # 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). 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). 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).

@ -845,6 +845,9 @@
"invalidBlockExplorerURL": { "invalidBlockExplorerURL": {
"message": "Invalid Block Explorer URL" "message": "Invalid Block Explorer URL"
}, },
"invalidChainIdTooBig": {
"message": "Invalid chain ID. The chain ID is too big."
},
"invalidCustomNetworkAlertContent1": { "invalidCustomNetworkAlertContent1": {
"message": "The chain ID for custom network '$1' has to be re-entered.", "message": "The chain ID for custom network '$1' has to be re-entered.",
"description": "$1 is the name/identifier of the network." "description": "$1 is the name/identifier of the network."

@ -2,7 +2,7 @@
"applications": { "applications": {
"gecko": { "gecko": {
"id": "webextension@metamask.io", "id": "webextension@metamask.io",
"strict_min_version": "56.0" "strict_min_version": "68.0"
} }
} }
} }

@ -19,6 +19,12 @@ import extension from 'extensionizer'
import { storeAsStream, storeTransformStream } from '@metamask/obs-store' import { storeAsStream, storeTransformStream } from '@metamask/obs-store'
import PortStream from 'extension-port-stream' import PortStream from 'extension-port-stream'
import { captureException } from '@sentry/browser' import { captureException } from '@sentry/browser'
import {
ENVIRONMENT_TYPE_POPUP,
ENVIRONMENT_TYPE_NOTIFICATION,
ENVIRONMENT_TYPE_FULLSCREEN,
} from '../../shared/constants/app'
import migrations from './migrations' import migrations from './migrations'
import Migrator from './lib/migrator' import Migrator from './lib/migrator'
import ExtensionPlatform from './platforms/extension' 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 getFirstPreferredLangCode from './lib/get-first-preferred-lang-code'
import getObjStructure from './lib/getObjStructure' import getObjStructure from './lib/getObjStructure'
import setupEnsIpfsResolver from './lib/ens-ipfs/setup' import setupEnsIpfsResolver from './lib/ens-ipfs/setup'
import {
ENVIRONMENT_TYPE_POPUP,
ENVIRONMENT_TYPE_NOTIFICATION,
ENVIRONMENT_TYPE_FULLSCREEN,
} from './lib/enums'
/* eslint-enable import/first */ /* eslint-enable import/first */
const { sentry } = global const { sentry } = global

@ -2,12 +2,11 @@ import Web3 from 'web3'
import contracts from '@metamask/contract-metadata' import contracts from '@metamask/contract-metadata'
import { warn } from 'loglevel' import { warn } from 'loglevel'
import SINGLE_CALL_BALANCES_ABI from 'single-call-balance-checker-abi' 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 // By default, poll every 3 minutes
const DEFAULT_INTERVAL = 180 * 1000 const DEFAULT_INTERVAL = 180 * 1000
const SINGLE_CALL_BALANCES_ADDRESS =
'0xb1f8e55c7f64d203c1400b9d8555d050f94adf39'
/** /**
* A controller that polls for token exchange * A controller that polls for token exchange

@ -3,7 +3,7 @@ import log from 'loglevel'
import BN from 'bn.js' import BN from 'bn.js'
import createId from '../lib/random-id' import createId from '../lib/random-id'
import { bnToHex } from '../lib/util' import { bnToHex } from '../lib/util'
import fetchWithTimeout from '../lib/fetch-with-timeout' import getFetchWithTimeout from '../../../shared/modules/fetch-with-timeout'
import { import {
TRANSACTION_CATEGORIES, TRANSACTION_CATEGORIES,
@ -22,11 +22,9 @@ import {
RINKEBY_CHAIN_ID, RINKEBY_CHAIN_ID,
ROPSTEN, ROPSTEN,
ROPSTEN_CHAIN_ID, ROPSTEN_CHAIN_ID,
} from './network/enums' } from '../../../shared/constants/network'
const fetch = fetchWithTimeout({ const fetchWithTimeout = getFetchWithTimeout(30000)
timeout: 30000,
})
/** /**
* This controller is responsible for retrieving incoming transactions. Etherscan is polled once every block to check * 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) { if (fromBlock) {
url += `&startBlock=${parseInt(fromBlock, 10)}` url += `&startBlock=${parseInt(fromBlock, 10)}`
} }
const response = await fetch(url) const response = await fetchWithTimeout(url)
const parsedResponse = await response.json() const parsedResponse = await response.json()
return { return {

@ -1,7 +1,7 @@
import { merge, omit } from 'lodash' import { merge, omit } from 'lodash'
import { ObservableStore } from '@metamask/obs-store' import { ObservableStore } from '@metamask/obs-store'
import { bufferToHex, sha3 } from 'ethereumjs-util' import { bufferToHex, sha3 } from 'ethereumjs-util'
import { ENVIRONMENT_TYPE_BACKGROUND } from '../lib/enums' import { ENVIRONMENT_TYPE_BACKGROUND } from '../../../shared/constants/app'
import { import {
METAMETRICS_ANONYMOUS_ID, METAMETRICS_ANONYMOUS_ID,
METAMETRICS_BACKGROUND_PAGE_OBJECT, METAMETRICS_BACKGROUND_PAGE_OBJECT,

@ -8,7 +8,7 @@ import providerFromMiddleware from 'eth-json-rpc-middleware/providerFromMiddlewa
import createInfuraMiddleware from 'eth-json-rpc-infura' import createInfuraMiddleware from 'eth-json-rpc-infura'
import BlockTracker from 'eth-block-tracker' 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 }) { export default function createInfuraClient({ network, projectId }) {
const infuraMiddleware = createInfuraMiddleware({ const infuraMiddleware = createInfuraMiddleware({

@ -9,25 +9,29 @@ import {
createEventEmitterProxy, createEventEmitterProxy,
} from 'swappable-obj-proxy' } from 'swappable-obj-proxy'
import EthQuery from 'eth-query' import EthQuery from 'eth-query'
import createMetamaskMiddleware from './createMetamaskMiddleware'
import createInfuraClient from './createInfuraClient'
import createJsonRpcClient from './createJsonRpcClient'
import { import {
RINKEBY, RINKEBY,
MAINNET, MAINNET,
INFURA_PROVIDER_TYPES, INFURA_PROVIDER_TYPES,
NETWORK_TYPE_RPC,
NETWORK_TYPE_TO_ID_MAP, NETWORK_TYPE_TO_ID_MAP,
MAINNET_CHAIN_ID, MAINNET_CHAIN_ID,
RINKEBY_CHAIN_ID, RINKEBY_CHAIN_ID,
} from './enums' } from '../../../../shared/constants/network'
import {
isPrefixedFormattedHexString,
isSafeChainId,
} from '../../../../shared/modules/utils'
import createMetamaskMiddleware from './createMetamaskMiddleware'
import createInfuraClient from './createInfuraClient'
import createJsonRpcClient from './createJsonRpcClient'
const env = process.env.METAMASK_ENV const env = process.env.METAMASK_ENV
let defaultProviderConfigOpts let defaultProviderConfigOpts
if (process.env.IN_TEST === 'true') { if (process.env.IN_TEST === 'true') {
defaultProviderConfigOpts = { defaultProviderConfigOpts = {
type: 'rpc', type: NETWORK_TYPE_RPC,
rpcUrl: 'http://localhost:8545', rpcUrl: 'http://localhost:8545',
chainId: '0x539', chainId: '0x539',
nickname: 'Localhost 8545', nickname: 'Localhost 8545',
@ -160,8 +164,16 @@ export default class NetworkController extends EventEmitter {
} }
setRpcTarget(rpcUrl, chainId, ticker = 'ETH', nickname = '', rpcPrefs) { setRpcTarget(rpcUrl, chainId, ticker = 'ETH', nickname = '', rpcPrefs) {
assert.ok(
isPrefixedFormattedHexString(chainId),
`Invalid chain ID "${chainId}": invalid hex string.`,
)
assert.ok(
isSafeChainId(parseInt(chainId, 16)),
`Invalid chain ID "${chainId}": numerical value greater than max safe value.`,
)
this.setProviderConfig({ this.setProviderConfig({
type: 'rpc', type: NETWORK_TYPE_RPC,
rpcUrl, rpcUrl,
chainId, chainId,
ticker, ticker,
@ -171,14 +183,14 @@ export default class NetworkController extends EventEmitter {
} }
async setProviderType(type, rpcUrl = '', ticker = 'ETH', nickname = '') { async setProviderType(type, rpcUrl = '', ticker = 'ETH', nickname = '') {
assert.notEqual( assert.notStrictEqual(
type, type,
'rpc', NETWORK_TYPE_RPC,
`NetworkController - cannot call "setProviderType" with type 'rpc'. use "setRpcTarget"`, `NetworkController - cannot call "setProviderType" with type "${NETWORK_TYPE_RPC}". Use "setRpcTarget"`,
) )
assert( assert.ok(
INFURA_PROVIDER_TYPES.includes(type), INFURA_PROVIDER_TYPES.includes(type),
`NetworkController - Unknown rpc type "${type}"`, `Unknown Infura provider type "${type}".`,
) )
const { chainId } = NETWORK_TYPE_TO_ID_MAP[type] const { chainId } = NETWORK_TYPE_TO_ID_MAP[type]
this.setProviderConfig({ type, rpcUrl, chainId, ticker, nickname }) this.setProviderConfig({ type, rpcUrl, chainId, ticker, nickname })
@ -209,7 +221,7 @@ export default class NetworkController extends EventEmitter {
getNetworkIdentifier() { getNetworkIdentifier() {
const provider = this.providerStore.getState() 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 +240,7 @@ export default class NetworkController extends EventEmitter {
if (isInfura) { if (isInfura) {
this._configureInfuraProvider(type, this._infuraProjectId) this._configureInfuraProvider(type, this._infuraProjectId)
// url-based rpc endpoints // url-based rpc endpoints
} else if (type === 'rpc') { } else if (type === NETWORK_TYPE_RPC) {
this._configureStandardProvider(rpcUrl, chainId) this._configureStandardProvider(rpcUrl, chainId)
} else { } else {
throw new Error( throw new Error(

@ -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] export const getNetworkDisplayName = (key) => NETWORK_TO_NAME_MAP[key]

@ -10,11 +10,6 @@ export const METADATA_STORE_KEY = 'domainMetadata'
export const METADATA_CACHE_MAX_SIZE = 100 export const METADATA_CACHE_MAX_SIZE = 100
export const CAVEAT_NAMES = {
exposedAccounts: 'exposedAccounts',
primaryAccountOnly: 'primaryAccountOnly',
}
export const CAVEAT_TYPES = { export const CAVEAT_TYPES = {
limitResponseLength: 'limitResponseLength', limitResponseLength: 'limitResponseLength',
filterResponse: 'filterResponse', filterResponse: 'filterResponse',

@ -3,13 +3,10 @@ import { JsonRpcEngine } from 'json-rpc-engine'
import { ObservableStore } from '@metamask/obs-store' import { ObservableStore } from '@metamask/obs-store'
import log from 'loglevel' import log from 'loglevel'
import { CapabilitiesController as RpcCap } from 'rpc-cap' import { CapabilitiesController as RpcCap } from 'rpc-cap'
import { ethErrors } from 'eth-json-rpc-errors' import { ethErrors } from 'eth-rpc-errors'
import { cloneDeep } from 'lodash' import { cloneDeep } from 'lodash'
import createPermissionsMethodMiddleware from './permissionsMethodMiddleware' import { CAVEAT_NAMES } from '../../../../shared/constants/permissions'
import PermissionsLogController from './permissionsLog'
// Methods that do not require any permissions to use:
import { import {
APPROVAL_TYPE, APPROVAL_TYPE,
SAFE_METHODS, // methods that do not require any permissions to use SAFE_METHODS, // methods that do not require any permissions to use
@ -18,11 +15,13 @@ import {
METADATA_CACHE_MAX_SIZE, METADATA_CACHE_MAX_SIZE,
LOG_STORE_KEY, LOG_STORE_KEY,
HISTORY_STORE_KEY, HISTORY_STORE_KEY,
CAVEAT_NAMES,
NOTIFICATION_NAMES, NOTIFICATION_NAMES,
CAVEAT_TYPES, CAVEAT_TYPES,
} from './enums' } from './enums'
import createPermissionsMethodMiddleware from './permissionsMethodMiddleware'
import PermissionsLogController from './permissionsLog'
// instanbul ignore next // instanbul ignore next
const noop = () => undefined const noop = () => undefined

@ -1,6 +1,6 @@
import { cloneDeep } from 'lodash' import { cloneDeep } from 'lodash'
import { CAVEAT_NAMES } from '../../../../shared/constants/permissions'
import { import {
CAVEAT_NAMES,
HISTORY_STORE_KEY, HISTORY_STORE_KEY,
LOG_IGNORE_METHODS, LOG_IGNORE_METHODS,
LOG_LIMIT, LOG_LIMIT,

@ -1,5 +1,5 @@
import { createAsyncMiddleware } from 'json-rpc-engine' import { createAsyncMiddleware } from 'json-rpc-engine'
import { ethErrors } from 'eth-json-rpc-errors' import { ethErrors } from 'eth-rpc-errors'
/** /**
* Create middleware for handling certain methods and preprocessing permissions requests. * Create middleware for handling certain methods and preprocessing permissions requests.

@ -1,13 +1,13 @@
import { strict as assert } from 'assert' import { strict as assert } from 'assert'
import { ObservableStore } from '@metamask/obs-store' import { ObservableStore } from '@metamask/obs-store'
import { ethErrors } from 'eth-json-rpc-errors' import { ethErrors } from 'eth-rpc-errors'
import { normalize as normalizeAddress } from 'eth-sig-util' import { normalize as normalizeAddress } from 'eth-sig-util'
import { isValidAddress } from 'ethereumjs-util' import { isValidAddress } from 'ethereumjs-util'
import ethers from 'ethers' import ethers from 'ethers'
import log from 'loglevel' import log from 'loglevel'
import { isPrefixedFormattedHexString } from '../lib/util'
import { LISTED_CONTRACT_ADDRESSES } from '../../../shared/constants/tokens' 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'
import { isPrefixedFormattedHexString } from '../../../shared/modules/utils'
export default class PreferencesController { export default class PreferencesController {
/** /**

@ -2,6 +2,9 @@ import { ObservableStore } from '@metamask/obs-store'
import log from 'loglevel' import log from 'loglevel'
import { normalize as normalizeAddress } from 'eth-sig-util' import { normalize as normalizeAddress } from 'eth-sig-util'
import ethUtil from 'ethereumjs-util' import ethUtil from 'ethereumjs-util'
import getFetchWithTimeout from '../../../shared/modules/fetch-with-timeout'
const fetchWithTimeout = getFetchWithTimeout(30000)
// By default, poll every 3 minutes // By default, poll every 3 minutes
const DEFAULT_INTERVAL = 180 * 1000 const DEFAULT_INTERVAL = 180 * 1000
@ -34,7 +37,7 @@ export default class TokenRatesController {
const query = `contract_addresses=${pairs}&vs_currencies=${nativeCurrency}` const query = `contract_addresses=${pairs}&vs_currencies=${nativeCurrency}`
if (this._tokens.length > 0) { if (this._tokens.length > 0) {
try { try {
const response = await window.fetch( const response = await fetchWithTimeout(
`https://api.coingecko.com/api/v3/simple/token_price/ethereum?${query}`, `https://api.coingecko.com/api/v3/simple/token_price/ethereum?${query}`,
) )
const prices = await response.json() const prices = await response.json()

@ -3,7 +3,7 @@ import { ObservableStore } from '@metamask/obs-store'
import ethUtil from 'ethereumjs-util' import ethUtil from 'ethereumjs-util'
import Transaction from 'ethereumjs-tx' import Transaction from 'ethereumjs-tx'
import EthQuery from 'ethjs-query' import EthQuery from 'ethjs-query'
import { ethErrors } from 'eth-json-rpc-errors' import { ethErrors } from 'eth-rpc-errors'
import abi from 'human-standard-token-abi' import abi from 'human-standard-token-abi'
import { ethers } from 'ethers' import { ethers } from 'ethers'
import NonceTracker from 'nonce-tracker' import NonceTracker from 'nonce-tracker'

@ -1,5 +1,5 @@
import { isValidAddress } from 'ethereumjs-util' import { isValidAddress } from 'ethereumjs-util'
import { ethErrors } from 'eth-json-rpc-errors' import { ethErrors } from 'eth-rpc-errors'
import { addHexPrefix } from '../../../lib/util' import { addHexPrefix } from '../../../lib/util'
import { TRANSACTION_STATUSES } from '../../../../../shared/constants/transaction' import { TRANSACTION_STATUSES } from '../../../../../shared/constants/transaction'

@ -19,14 +19,14 @@ import {
RINKEBY_CHAIN_ID, RINKEBY_CHAIN_ID,
ROPSTEN_CHAIN_ID, ROPSTEN_CHAIN_ID,
KOVAN_CHAIN_ID, KOVAN_CHAIN_ID,
} from '../controllers/network/enums' } from '../../../shared/constants/network'
import { import {
SINGLE_CALL_BALANCES_ADDRESS, SINGLE_CALL_BALANCES_ADDRESS,
SINGLE_CALL_BALANCES_ADDRESS_RINKEBY, SINGLE_CALL_BALANCES_ADDRESS_RINKEBY,
SINGLE_CALL_BALANCES_ADDRESS_ROPSTEN, SINGLE_CALL_BALANCES_ADDRESS_ROPSTEN,
SINGLE_CALL_BALANCES_ADDRESS_KOVAN, SINGLE_CALL_BALANCES_ADDRESS_KOVAN,
} from '../controllers/network/contract-addresses' } from '../constants/contracts'
import { bnToHex } from './util' import { bnToHex } from './util'
/** /**

@ -1,11 +1,11 @@
import EventEmitter from 'events' import EventEmitter from 'events'
import { ObservableStore } from '@metamask/obs-store' import { ObservableStore } from '@metamask/obs-store'
import ethUtil from 'ethereumjs-util' import ethUtil from 'ethereumjs-util'
import { ethErrors } from 'eth-json-rpc-errors' import { ethErrors } from 'eth-rpc-errors'
import log from 'loglevel' import log from 'loglevel'
import { MESSAGE_TYPE } from '../../../shared/constants/app'
import { addHexPrefix } from './util' import { addHexPrefix } from './util'
import createId from './random-id' import createId from './random-id'
import { MESSAGE_TYPE } from './enums'
const hexRe = /^[0-9A-Fa-f]+$/gu const hexRe = /^[0-9A-Fa-f]+$/gu

@ -1,9 +1,9 @@
import EventEmitter from 'events' import EventEmitter from 'events'
import { ObservableStore } from '@metamask/obs-store' import { ObservableStore } from '@metamask/obs-store'
import { ethErrors } from 'eth-json-rpc-errors' import { ethErrors } from 'eth-rpc-errors'
import log from 'loglevel' import log from 'loglevel'
import { MESSAGE_TYPE } from '../../../shared/constants/app'
import createId from './random-id' import createId from './random-id'
import { MESSAGE_TYPE } from './enums'
/** /**
* Represents, and contains data about, an 'eth_getEncryptionPublicKey' type request. These are created when * Represents, and contains data about, an 'eth_getEncryptionPublicKey' type request. These are created when

@ -1,6 +1,9 @@
import extension from 'extensionizer' import extension from 'extensionizer'
import getFetchWithTimeout from '../../../../shared/modules/fetch-with-timeout'
import resolveEnsToIpfsContentId from './resolver' import resolveEnsToIpfsContentId from './resolver'
const fetchWithTimeout = getFetchWithTimeout(30000)
const supportedTopLevelDomains = ['eth'] const supportedTopLevelDomains = ['eth']
export default function setupEnsIpfsResolver({ export default function setupEnsIpfsResolver({
@ -55,7 +58,9 @@ export default function setupEnsIpfsResolver({
)}.${ipfsGateway}${pathname}${search || ''}${fragment || ''}` )}.${ipfsGateway}${pathname}${search || ''}${fragment || ''}`
try { try {
// check if ipfs gateway has result // 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) { if (response.status === 200) {
url = resolvedUrl url = resolvedUrl
} }

@ -1,9 +1,9 @@
import EventEmitter from 'events' import EventEmitter from 'events'
import { ObservableStore } from '@metamask/obs-store' import { ObservableStore } from '@metamask/obs-store'
import ethUtil from 'ethereumjs-util' import ethUtil from 'ethereumjs-util'
import { ethErrors } from 'eth-json-rpc-errors' import { ethErrors } from 'eth-rpc-errors'
import { MESSAGE_TYPE } from '../../../shared/constants/app'
import createId from './random-id' 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 * Represents, and contains data about, an 'eth_sign' type signature request. These are created when a signature for

@ -1,4 +1,7 @@
import log from 'loglevel' import log from 'loglevel'
import getFetchWithTimeout from '../../../shared/modules/fetch-with-timeout'
const fetchWithTimeout = getFetchWithTimeout(30000)
const FIXTURE_SERVER_HOST = 'localhost' const FIXTURE_SERVER_HOST = 'localhost'
const FIXTURE_SERVER_PORT = 12345 const FIXTURE_SERVER_PORT = 12345
@ -24,7 +27,7 @@ export default class ReadOnlyNetworkStore {
*/ */
async _init() { async _init() {
try { try {
const response = await window.fetch(FIXTURE_SERVER_URL) const response = await fetchWithTimeout(FIXTURE_SERVER_URL)
if (response.ok) { if (response.ok) {
this._state = await response.json() this._state = await response.json()
} }

@ -1,11 +1,11 @@
import EventEmitter from 'events' import EventEmitter from 'events'
import { ObservableStore } from '@metamask/obs-store' import { ObservableStore } from '@metamask/obs-store'
import ethUtil from 'ethereumjs-util' import ethUtil from 'ethereumjs-util'
import { ethErrors } from 'eth-json-rpc-errors' import { ethErrors } from 'eth-rpc-errors'
import log from 'loglevel' import log from 'loglevel'
import { MESSAGE_TYPE } from '../../../shared/constants/app'
import { addHexPrefix } from './util' import { addHexPrefix } from './util'
import createId from './random-id' import createId from './random-id'
import { MESSAGE_TYPE } from './enums'
const hexRe = /^[0-9A-Fa-f]+$/gu const hexRe = /^[0-9A-Fa-f]+$/gu

@ -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. * This RPC method gets background state relevant to the provider.

@ -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 * This RPC method is called by the inpage provider whenever it detects the

@ -1,4 +1,4 @@
import { MESSAGE_TYPE } from '../../enums' import { MESSAGE_TYPE } from '../../../../../shared/constants/app'
const watchAsset = { const watchAsset = {
methodNames: [MESSAGE_TYPE.WATCH_ASSET, MESSAGE_TYPE.WATCH_ASSET_LEGACY], methodNames: [MESSAGE_TYPE.WATCH_ASSET, MESSAGE_TYPE.WATCH_ASSET_LEGACY],

@ -1,13 +1,13 @@
import EventEmitter from 'events' import EventEmitter from 'events'
import assert from 'assert' import assert from 'assert'
import { ObservableStore } from '@metamask/obs-store' import { ObservableStore } from '@metamask/obs-store'
import { ethErrors } from 'eth-json-rpc-errors' import { ethErrors } from 'eth-rpc-errors'
import { typedSignatureHash, TYPED_MESSAGE_SCHEMA } from 'eth-sig-util' import { typedSignatureHash, TYPED_MESSAGE_SCHEMA } from 'eth-sig-util'
import { isValidAddress } from 'ethereumjs-util' import { isValidAddress } from 'ethereumjs-util'
import log from 'loglevel' import log from 'loglevel'
import jsonschema from 'jsonschema' import jsonschema from 'jsonschema'
import { MESSAGE_TYPE } from '../../../shared/constants/app'
import createId from './random-id' 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 * Represents, and contains data about, an 'eth_signTypedData' type signature request. These are created when a

@ -14,7 +14,7 @@ import {
PLATFORM_CHROME, PLATFORM_CHROME,
PLATFORM_EDGE, PLATFORM_EDGE,
PLATFORM_BRAVE, PLATFORM_BRAVE,
} from './enums' } from '../../../shared/constants/app'
/** /**
* @see {@link getEnvironmentType} * @see {@link getEnvironmentType}
@ -147,21 +147,6 @@ function checkForError() {
return new Error(lastError.message) return new Error(lastError.message)
} }
/**
* Checks whether the given value is a 0x-prefixed, non-zero, non-zero-padded,
* hexadecimal string.
*
* @param {any} value - The value to check.
* @returns {boolean} True if the value is a correctly formatted hex string,
* false otherwise.
*/
function isPrefixedFormattedHexString(value) {
if (typeof value !== 'string') {
return false
}
return /^0x[1-9a-f]+[0-9a-f]*$/iu.test(value)
}
/** /**
* Prefixes a hex string with '0x' or '-0x' and returns it. Idempotent. * Prefixes a hex string with '0x' or '-0x' and returns it. Idempotent.
* *
@ -202,7 +187,6 @@ export {
hexToBn, hexToBn,
BnMultiplyByFraction, BnMultiplyByFraction,
checkForError, checkForError,
isPrefixedFormattedHexString,
addHexPrefix, addHexPrefix,
bnToHex, bnToHex,
} }

@ -2402,20 +2402,20 @@ export default class MetamaskController extends EventEmitter {
nickname, nickname,
rpcPrefs, rpcPrefs,
) { ) {
await this.preferencesController.updateRpc({ this.networkController.setRpcTarget(
rpcUrl, rpcUrl,
chainId, chainId,
ticker, ticker,
nickname, nickname,
rpcPrefs, rpcPrefs,
}) )
this.networkController.setRpcTarget( await this.preferencesController.updateRpc({
rpcUrl, rpcUrl,
chainId, chainId,
ticker, ticker,
nickname, nickname,
rpcPrefs, rpcPrefs,
) })
return rpcUrl return rpcUrl
} }

@ -1,5 +1,5 @@
import { cloneDeep } from 'lodash' 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 const version = 51

@ -1,7 +1,7 @@
import extension from 'extensionizer' import extension from 'extensionizer'
import { createExplorerLink as explorerLink } from '@metamask/etherscan-link' import { createExplorerLink as explorerLink } from '@metamask/etherscan-link'
import { getEnvironmentType, checkForError } from '../lib/util' 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' import { TRANSACTION_STATUSES } from '../../../shared/constants/transaction'
export default class ExtensionPlatform { export default class ExtensionPlatform {

@ -12,12 +12,12 @@ import EthQuery from 'eth-query'
import StreamProvider from 'web3-stream-provider' import StreamProvider from 'web3-stream-provider'
import log from 'loglevel' import log from 'loglevel'
import launchMetaMaskUi from '../../ui' import launchMetaMaskUi from '../../ui'
import ExtensionPlatform from './platforms/extension'
import { setupMultiplex } from './lib/stream-utils'
import { import {
ENVIRONMENT_TYPE_FULLSCREEN, ENVIRONMENT_TYPE_FULLSCREEN,
ENVIRONMENT_TYPE_POPUP, 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' import { getEnvironmentType } from './lib/util'
start().catch(log.error) start().catch(log.error)

@ -16,6 +16,6 @@ Passing messages from popup to background script
window.addEventListener('message', event => { window.addEventListener('message', event => {
if (port && event.source === window && event.data) { if (port && event.source === window && event.data) {
port.postMessage(event.data); port.postMessage({ data: event.data });
} }
}); });

@ -6,7 +6,7 @@ module.exports = function (api) {
'@babel/preset-env', '@babel/preset-env',
{ {
targets: { targets: {
browsers: ['chrome >= 63', 'firefox >= 56.2'], browsers: ['chrome >= 63', 'firefox >= 68'],
}, },
}, },
], ],

@ -375,12 +375,10 @@ function createScriptTasks({ browserPlatforms, livereload }) {
METAMASK_DEBUG: opts.devMode, METAMASK_DEBUG: opts.devMode,
METAMASK_ENVIRONMENT: environment, METAMASK_ENVIRONMENT: environment,
METAMASK_VERSION: baseManifest.version, METAMASK_VERSION: baseManifest.version,
METAMETRICS_PROJECT_ID: process.env.METAMETRICS_PROJECT_ID,
NODE_ENV: opts.devMode ? 'development' : 'production', NODE_ENV: opts.devMode ? 'development' : 'production',
IN_TEST: opts.testing ? 'true' : false, IN_TEST: opts.testing ? 'true' : false,
PUBNUB_SUB_KEY: process.env.PUBNUB_SUB_KEY || '', PUBNUB_SUB_KEY: process.env.PUBNUB_SUB_KEY || '',
PUBNUB_PUB_KEY: process.env.PUBNUB_PUB_KEY || '', PUBNUB_PUB_KEY: process.env.PUBNUB_PUB_KEY || '',
ETH_GAS_STATION_API_KEY: process.env.ETH_GAS_STATION_API_KEY || '',
CONF: opts.devMode ? conf : {}, CONF: opts.devMode ? conf : {},
SENTRY_DSN: process.env.SENTRY_DSN, SENTRY_DSN: process.env.SENTRY_DSN,
INFURA_PROJECT_ID: opts.testing INFURA_PROJECT_ID: opts.testing

@ -1,7 +1,7 @@
const pify = require('pify') const pify = require('pify')
const gulp = require('gulp') const gulp = require('gulp')
const sass = require('gulp-sass') const sass = require('gulp-sass')
sass.compiler = require('node-sass') sass.compiler = require('sass')
const autoprefixer = require('gulp-autoprefixer') const autoprefixer = require('gulp-autoprefixer')
const gulpStylelint = require('gulp-stylelint') const gulpStylelint = require('gulp-stylelint')
const watch = require('gulp-watch') const watch = require('gulp-watch')

@ -86,7 +86,7 @@
"@metamask/logo": "^2.5.0", "@metamask/logo": "^2.5.0",
"@metamask/obs-store": "^5.0.0", "@metamask/obs-store": "^5.0.0",
"@popperjs/core": "^2.4.0", "@popperjs/core": "^2.4.0",
"@reduxjs/toolkit": "^1.3.2", "@reduxjs/toolkit": "^1.5.0",
"@sentry/browser": "^5.26.0", "@sentry/browser": "^5.26.0",
"@sentry/integrations": "^5.26.0", "@sentry/integrations": "^5.26.0",
"@zxing/library": "^0.8.0", "@zxing/library": "^0.8.0",
@ -105,7 +105,6 @@
"end-of-stream": "^1.4.4", "end-of-stream": "^1.4.4",
"eth-block-tracker": "^4.4.2", "eth-block-tracker": "^4.4.2",
"eth-ens-namehash": "^2.0.8", "eth-ens-namehash": "^2.0.8",
"eth-json-rpc-errors": "^2.0.2",
"eth-json-rpc-filters": "^4.2.1", "eth-json-rpc-filters": "^4.2.1",
"eth-json-rpc-infura": "^5.1.0", "eth-json-rpc-infura": "^5.1.0",
"eth-json-rpc-middleware": "^6.0.0", "eth-json-rpc-middleware": "^6.0.0",
@ -113,8 +112,9 @@
"eth-method-registry": "^2.0.0", "eth-method-registry": "^2.0.0",
"eth-phishing-detect": "^1.1.14", "eth-phishing-detect": "^1.1.14",
"eth-query": "^2.1.2", "eth-query": "^2.1.2",
"eth-rpc-errors": "^4.0.2",
"eth-sig-util": "^3.0.0", "eth-sig-util": "^3.0.0",
"eth-trezor-keyring": "^0.4.0", "eth-trezor-keyring": "^0.5.2",
"ethereum-ens-network-map": "^1.0.2", "ethereum-ens-network-map": "^1.0.2",
"ethereumjs-abi": "^0.6.4", "ethereumjs-abi": "^0.6.4",
"ethereumjs-tx": "1.3.7", "ethereumjs-tx": "1.3.7",
@ -246,7 +246,7 @@
"gulp-rename": "^2.0.0", "gulp-rename": "^2.0.0",
"gulp-replace": "^1.0.0", "gulp-replace": "^1.0.0",
"gulp-rtlcss": "^1.4.0", "gulp-rtlcss": "^1.4.0",
"gulp-sass": "^4.0.0", "gulp-sass": "^4.1.0",
"gulp-sourcemaps": "^2.6.0", "gulp-sourcemaps": "^2.6.0",
"gulp-stylelint": "^13.0.0", "gulp-stylelint": "^13.0.0",
"gulp-terser-js": "^5.2.2", "gulp-terser-js": "^5.2.2",
@ -259,7 +259,6 @@
"mocha": "^7.2.0", "mocha": "^7.2.0",
"nock": "^9.0.14", "nock": "^9.0.14",
"node-fetch": "^2.6.1", "node-fetch": "^2.6.1",
"node-sass": "^4.14.1",
"nyc": "^15.0.0", "nyc": "^15.0.0",
"polyfill-crypto.getrandomvalues": "^1.0.0", "polyfill-crypto.getrandomvalues": "^1.0.0",
"prettier": "^2.1.1", "prettier": "^2.1.1",
@ -275,7 +274,8 @@
"remote-redux-devtools": "^0.5.16", "remote-redux-devtools": "^0.5.16",
"remotedev-server": "^0.3.1", "remotedev-server": "^0.3.1",
"resolve-url-loader": "^3.1.2", "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", "selenium-webdriver": "4.0.0-alpha.7",
"serve-handler": "^6.1.2", "serve-handler": "^6.1.2",
"ses": "0.11.0", "ses": "0.11.0",

@ -6,19 +6,18 @@
* background - The background process that powers the extension * background - The background process that powers the extension
* @typedef {'popup' | 'notification' | 'fullscreen' | 'background'} EnvironmentType * @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' export const PLATFORM_BRAVE = 'Brave'
const ENVIRONMENT_TYPE_NOTIFICATION = 'notification' export const PLATFORM_CHROME = 'Chrome'
const ENVIRONMENT_TYPE_FULLSCREEN = 'fullscreen' export const PLATFORM_EDGE = 'Edge'
const ENVIRONMENT_TYPE_BACKGROUND = 'background' export const PLATFORM_FIREFOX = 'Firefox'
export const PLATFORM_OPERA = 'Opera'
const PLATFORM_BRAVE = 'Brave' export const MESSAGE_TYPE = {
const PLATFORM_CHROME = 'Chrome'
const PLATFORM_EDGE = 'Edge'
const PLATFORM_FIREFOX = 'Firefox'
const PLATFORM_OPERA = 'Opera'
const MESSAGE_TYPE = {
ETH_DECRYPT: 'eth_decrypt', ETH_DECRYPT: 'eth_decrypt',
ETH_GET_ENCRYPTION_PUBLIC_KEY: 'eth_getEncryptionPublicKey', ETH_GET_ENCRYPTION_PUBLIC_KEY: 'eth_getEncryptionPublicKey',
ETH_SIGN: 'eth_sign', ETH_SIGN: 'eth_sign',
@ -29,16 +28,3 @@ const MESSAGE_TYPE = {
WATCH_ASSET: 'wallet_watchAsset', WATCH_ASSET: 'wallet_watchAsset',
WATCH_ASSET_LEGACY: 'metamask_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,
}

@ -1,6 +1,6 @@
// Type Imports // Type Imports
/** /**
* @typedef {import('../../app/scripts/lib/enums').EnvironmentType} EnvironmentType * @typedef {import('../../shared/constants/app').EnvironmentType} EnvironmentType
*/ */
// Type Declarations // Type Declarations

@ -3,6 +3,7 @@ export const RINKEBY = 'rinkeby'
export const KOVAN = 'kovan' export const KOVAN = 'kovan'
export const MAINNET = 'mainnet' export const MAINNET = 'mainnet'
export const GOERLI = 'goerli' export const GOERLI = 'goerli'
export const NETWORK_TYPE_RPC = 'rpc'
export const MAINNET_NETWORK_ID = '1' export const MAINNET_NETWORK_ID = '1'
export const ROPSTEN_NETWORK_ID = '3' export const ROPSTEN_NETWORK_ID = '3'
@ -16,6 +17,12 @@ export const RINKEBY_CHAIN_ID = '0x4'
export const GOERLI_CHAIN_ID = '0x5' export const GOERLI_CHAIN_ID = '0x5'
export const KOVAN_CHAIN_ID = '0x2a' export const KOVAN_CHAIN_ID = '0x2a'
/**
* The largest possible chain ID we can handle.
* Explanation: https://gist.github.com/rekmarks/a47bd5f2525936c4b8eee31a16345553
*/
export const MAX_SAFE_CHAIN_ID = 4503599627370476
export const ROPSTEN_DISPLAY_NAME = 'Ropsten' export const ROPSTEN_DISPLAY_NAME = 'Ropsten'
export const RINKEBY_DISPLAY_NAME = 'Rinkeby' export const RINKEBY_DISPLAY_NAME = 'Rinkeby'
export const KOVAN_DISPLAY_NAME = 'Kovan' export const KOVAN_DISPLAY_NAME = 'Kovan'

@ -0,0 +1,4 @@
export const CAVEAT_NAMES = {
exposedAccounts: 'exposedAccounts',
primaryAccountOnly: 'primaryAccountOnly',
}

@ -1,3 +0,0 @@
### Shared Modules
This folder is reserved for modules that can be used globally within both the background and ui applications.

@ -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) { return async function _fetch(url, opts) {
const abortController = new window.AbortController() const abortController = new window.AbortController()
const { signal } = abortController const { signal } = abortController
@ -18,6 +24,6 @@ const fetchWithTimeout = ({ timeout = 120000 } = {}) => {
throw e throw e
} }
} }
} })
export default fetchWithTimeout export default getFetchWithTimeout

@ -0,0 +1,30 @@
import { MAX_SAFE_CHAIN_ID } from '../constants/network'
/**
* Checks whether the given number primitive chain ID is safe.
* Because some cryptographic libraries we use expect the chain ID to be a
* number primitive, it must not exceed a certain size.
*
* @param {number} chainId - The chain ID to check for safety.
* @returns {boolean} Whether the given chain ID is safe.
*/
export function isSafeChainId(chainId) {
return (
Number.isSafeInteger(chainId) && chainId > 0 && chainId <= MAX_SAFE_CHAIN_ID
)
}
/**
* Checks whether the given value is a 0x-prefixed, non-zero, non-zero-padded,
* hexadecimal string.
*
* @param {any} value - The value to check.
* @returns {boolean} True if the value is a correctly formatted hex string,
* false otherwise.
*/
export function isPrefixedFormattedHexString(value) {
if (typeof value !== 'string') {
return false
}
return /^0x[1-9a-f]+[0-9a-f]*$/iu.test(value)
}

@ -2,6 +2,7 @@ import assert from 'assert'
import freeze from 'deep-freeze-strict' import freeze from 'deep-freeze-strict'
import reducers from '../../../ui/app/ducks' import reducers from '../../../ui/app/ducks'
import * as actionConstants from '../../../ui/app/store/actionConstants' import * as actionConstants from '../../../ui/app/store/actionConstants'
import { NETWORK_TYPE_RPC } from '../../../shared/constants/network'
describe('config view actions', function () { describe('config view actions', function () {
const initialState = { const initialState = {
@ -25,7 +26,7 @@ describe('config view actions', function () {
} }
const result = reducers(initialState, action) 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') assert.equal(result.metamask.provider.rpcUrl, 'foo')
}) })
}) })

@ -7,10 +7,7 @@ import BigNumber from 'bignumber.js'
import DetectTokensController from '../../../../app/scripts/controllers/detect-tokens' import DetectTokensController from '../../../../app/scripts/controllers/detect-tokens'
import NetworkController from '../../../../app/scripts/controllers/network/network' import NetworkController from '../../../../app/scripts/controllers/network/network'
import PreferencesController from '../../../../app/scripts/controllers/preferences' import PreferencesController from '../../../../app/scripts/controllers/preferences'
import { import { MAINNET, ROPSTEN } from '../../../../shared/constants/network'
MAINNET,
ROPSTEN,
} from '../../../../app/scripts/controllers/network/enums'
describe('DetectTokensController', function () { describe('DetectTokensController', function () {
const sandbox = sinon.createSandbox() const sandbox = sinon.createSandbox()

@ -14,7 +14,7 @@ import {
ROPSTEN, ROPSTEN,
ROPSTEN_CHAIN_ID, ROPSTEN_CHAIN_ID,
ROPSTEN_NETWORK_ID, ROPSTEN_NETWORK_ID,
} from '../../../../app/scripts/controllers/network/enums' } from '../../../../shared/constants/network'
import { import {
TRANSACTION_CATEGORIES, TRANSACTION_CATEGORIES,
TRANSACTION_STATUSES, TRANSACTION_STATUSES,

@ -1,7 +1,7 @@
import { strict as assert } from 'assert' import { strict as assert } from 'assert'
import sinon from 'sinon' import sinon from 'sinon'
import MetaMetricsController from '../../../../app/scripts/controllers/metametrics' 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 { createSegmentMock } from '../../../../app/scripts/lib/segment'
import { import {
METAMETRICS_ANONYMOUS_ID, METAMETRICS_ANONYMOUS_ID,

@ -1,12 +1,12 @@
import { ethErrors, ERROR_CODES } from 'eth-json-rpc-errors' import { ethErrors, errorCodes } from 'eth-rpc-errors'
import deepFreeze from 'deep-freeze-strict' import deepFreeze from 'deep-freeze-strict'
import { ApprovalController } from '@metamask/controllers' import { ApprovalController } from '@metamask/controllers'
import _getRestrictedMethods from '../../../../../app/scripts/controllers/permissions/restrictedMethods' import _getRestrictedMethods from '../../../../../app/scripts/controllers/permissions/restrictedMethods'
import { CAVEAT_NAMES } from '../../../../../shared/constants/permissions'
import { import {
CAVEAT_NAMES,
CAVEAT_TYPES, CAVEAT_TYPES,
NOTIFICATION_NAMES, NOTIFICATION_NAMES,
} from '../../../../../app/scripts/controllers/permissions/enums' } from '../../../../../app/scripts/controllers/permissions/enums'
@ -336,7 +336,7 @@ export const getters = deepFreeze({
return { return {
// name: 'EthereumRpcError', // name: 'EthereumRpcError',
message: `Failed to add 'eth_accounts' to '${origin}'.`, message: `Failed to add 'eth_accounts' to '${origin}'.`,
code: ERROR_CODES.rpc.internal, code: errorCodes.rpc.internal,
} }
}, },
}, },

@ -8,7 +8,7 @@ import { ObservableStore } from '@metamask/obs-store'
import { import {
ROPSTEN_NETWORK_ID, ROPSTEN_NETWORK_ID,
MAINNET_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 { ETH_SWAPS_TOKEN_ADDRESS } from '../../../../ui/app/helpers/constants/swaps'
import { createTestProviderTools } from '../../../stub/provider' import { createTestProviderTools } from '../../../stub/provider'
import SwapsController, { import SwapsController, {

@ -1,14 +1,16 @@
import assert from 'assert' import assert from 'assert'
import nock from 'nock' 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 () { it('fetches a url', async function () {
nock('https://api.infura.io').get('/money').reply(200, '{"hodl": false}') nock('https://api.infura.io').get('/money').reply(200, '{"hodl": false}')
const fetch = fetchWithTimeout() const fetchWithTimeout = getFetchWithTimeout(30000)
const response = await (await fetch('https://api.infura.io/money')).json() const response = await (
await fetchWithTimeout('https://api.infura.io/money')
).json()
assert.deepEqual(response, { assert.deepEqual(response, {
hodl: false, hodl: false,
}) })
@ -20,12 +22,10 @@ describe('fetchWithTimeout', function () {
.delay(2000) .delay(2000)
.reply(200, '{"moon": "2012-12-21T11:11:11Z"}') .reply(200, '{"moon": "2012-12-21T11:11:11Z"}')
const fetch = fetchWithTimeout({ const fetchWithTimeout = getFetchWithTimeout(123)
timeout: 123,
})
try { 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') assert.fail('Request should throw')
} catch (e) { } catch (e) {
assert.ok(e) assert.ok(e)
@ -38,15 +38,20 @@ describe('fetchWithTimeout', function () {
.delay(2000) .delay(2000)
.reply(200, '{"moon": "2012-12-21T11:11:11Z"}') .reply(200, '{"moon": "2012-12-21T11:11:11Z"}')
const fetch = fetchWithTimeout({ const fetchWithTimeout = getFetchWithTimeout(123)
timeout: 123,
})
try { 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') assert.fail('Request should be aborted')
} catch (e) { } catch (e) {
assert.deepEqual(e.message, 'Aborted') assert.deepEqual(e.message, 'Aborted')
} }
}) })
it('throws on invalid timeout', async function () {
assert.throws(() => getFetchWithTimeout(), 'should throw')
assert.throws(() => getFetchWithTimeout(-1), 'should throw')
assert.throws(() => getFetchWithTimeout({}), 'should throw')
assert.throws(() => getFetchWithTimeout(true), 'should throw')
})
}) })

@ -2,15 +2,15 @@ import { strict as assert } from 'assert'
import { import {
getEnvironmentType, getEnvironmentType,
sufficientBalance, sufficientBalance,
isPrefixedFormattedHexString,
} from '../../../app/scripts/lib/util' } from '../../../app/scripts/lib/util'
import { isPrefixedFormattedHexString } from '../../../shared/modules/utils'
import { import {
ENVIRONMENT_TYPE_POPUP, ENVIRONMENT_TYPE_POPUP,
ENVIRONMENT_TYPE_NOTIFICATION, ENVIRONMENT_TYPE_NOTIFICATION,
ENVIRONMENT_TYPE_FULLSCREEN, ENVIRONMENT_TYPE_FULLSCREEN,
ENVIRONMENT_TYPE_BACKGROUND, ENVIRONMENT_TYPE_BACKGROUND,
} from '../../../app/scripts/lib/enums' } from '../../../shared/constants/app'
describe('app utils', function () { describe('app utils', function () {
describe('getEnvironmentType', function () { describe('getEnvironmentType', function () {

@ -1,3 +1,5 @@
import { NETWORK_TYPE_RPC } from '../../shared/constants/network'
/** /**
* @typedef {Object} FirstTimeState * @typedef {Object} FirstTimeState
* @property {Object} config Initial configuration parameters * @property {Object} config Initial configuration parameters
@ -11,7 +13,7 @@ const initialState = {
config: {}, config: {},
NetworkController: { NetworkController: {
provider: { provider: {
type: 'rpc', type: NETWORK_TYPE_RPC,
rpcUrl: 'http://localhost:8545', rpcUrl: 'http://localhost:8545',
chainId: '0x539', chainId: '0x539',
}, },

@ -3,7 +3,7 @@ import migration51 from '../../../app/scripts/migrations/051'
import { import {
INFURA_PROVIDER_TYPES, INFURA_PROVIDER_TYPES,
NETWORK_TYPE_TO_ID_MAP, NETWORK_TYPE_TO_ID_MAP,
} from '../../../app/scripts/controllers/network/enums' } from '../../../shared/constants/network'
describe('migration #51', function () { describe('migration #51', function () {
it('should update the version metadata', async function () { it('should update the version metadata', async function () {

@ -4,7 +4,7 @@ import { debounce } from 'lodash'
import Fuse from 'fuse.js' import Fuse from 'fuse.js'
import InputAdornment from '@material-ui/core/InputAdornment' import InputAdornment from '@material-ui/core/InputAdornment'
import classnames from 'classnames' 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 { getEnvironmentType } from '../../../../../app/scripts/lib/util'
import Identicon from '../../ui/identicon' import Identicon from '../../ui/identicon'
import SiteIcon from '../../ui/site-icon' import SiteIcon from '../../ui/site-icon'

@ -3,7 +3,7 @@ import PropTypes from 'prop-types'
import { import {
ENVIRONMENT_TYPE_POPUP, ENVIRONMENT_TYPE_POPUP,
ENVIRONMENT_TYPE_NOTIFICATION, ENVIRONMENT_TYPE_NOTIFICATION,
} from '../../../../../../app/scripts/lib/enums' } from '../../../../../../shared/constants/app'
import { getEnvironmentType } from '../../../../../../app/scripts/lib/util' import { getEnvironmentType } from '../../../../../../app/scripts/lib/util'
import NetworkDisplay from '../../network-display' import NetworkDisplay from '../../network-display'
import Identicon from '../../../ui/identicon' import Identicon from '../../../ui/identicon'

@ -9,11 +9,10 @@ import {
NETWORKS_ROUTE, NETWORKS_ROUTE,
NETWORKS_FORM_ROUTE, NETWORKS_FORM_ROUTE,
} from '../../../helpers/constants/routes' } from '../../../helpers/constants/routes'
import { ENVIRONMENT_TYPE_FULLSCREEN } from '../../../../../app/scripts/lib/enums' import { ENVIRONMENT_TYPE_FULLSCREEN } from '../../../../../shared/constants/app'
import { import { NETWORK_TYPE_RPC } from '../../../../../shared/constants/network'
getEnvironmentType, import { isPrefixedFormattedHexString } from '../../../../../shared/modules/utils'
isPrefixedFormattedHexString, import { getEnvironmentType } from '../../../../../app/scripts/lib/util'
} from '../../../../../app/scripts/lib/util'
import { Dropdown, DropdownMenuItem } from './components/dropdown' import { Dropdown, DropdownMenuItem } from './components/dropdown'
import NetworkDropdownIcon from './components/network-dropdown-icon' import NetworkDropdownIcon from './components/network-dropdown-icon'
@ -117,7 +116,7 @@ class NetworkDropdown extends Component {
return reversedRpcListDetail.map((entry) => { return reversedRpcListDetail.map((entry) => {
const { rpcUrl, chainId, ticker = 'ETH', nickname = '' } = entry const { rpcUrl, chainId, ticker = 'ETH', nickname = '' } = entry
const isCurrentRpcTarget = const isCurrentRpcTarget =
provider.type === 'rpc' && rpcUrl === provider.rpcUrl provider.type === NETWORK_TYPE_RPC && rpcUrl === provider.rpcUrl
return ( return (
<DropdownMenuItem <DropdownMenuItem

@ -1,4 +1,5 @@
import { connect } from 'react-redux' import { connect } from 'react-redux'
import { NETWORK_TYPE_RPC } from '../../../../../shared/constants/network'
import * as actions from '../../../store/actions' import * as actions from '../../../store/actions'
import { getNetworkIdentifier } from '../../../selectors' import { getNetworkIdentifier } from '../../../selectors'
import LoadingNetworkScreen from './loading-network-screen.component' import LoadingNetworkScreen from './loading-network-screen.component'
@ -9,7 +10,9 @@ const mapStateToProps = (state) => {
const { rpcUrl, chainId, ticker, nickname, type } = provider const { rpcUrl, chainId, ticker, nickname, type } = provider
const setProviderArgs = const setProviderArgs =
type === 'rpc' ? [rpcUrl, chainId, ticker, nickname] : [provider.type] type === NETWORK_TYPE_RPC
? [rpcUrl, chainId, ticker, nickname]
: [provider.type]
return { return {
isLoadingNetwork: network === 'loading', isLoadingNetwork: network === 'loading',

@ -16,7 +16,7 @@ import {
import { useI18nContext } from '../../../hooks/useI18nContext' import { useI18nContext } from '../../../hooks/useI18nContext'
import { useMetricEvent } from '../../../hooks/useMetricEvent' import { useMetricEvent } from '../../../hooks/useMetricEvent'
import { getEnvironmentType } from '../../../../../app/scripts/lib/util' 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 }) { export default function AccountOptionsMenu({ anchorElement, onClose }) {
const t = useI18nContext() const t = useI18nContext()

@ -5,7 +5,7 @@ import { useSelector } from 'react-redux'
import SelectedAccount from '../selected-account' import SelectedAccount from '../selected-account'
import ConnectedStatusIndicator from '../connected-status-indicator' import ConnectedStatusIndicator from '../connected-status-indicator'
import { getEnvironmentType } from '../../../../../app/scripts/lib/util' 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 { CONNECTED_ACCOUNTS_ROUTE } from '../../../helpers/constants/routes'
import { useI18nContext } from '../../../hooks/useI18nContext' import { useI18nContext } from '../../../hooks/useI18nContext'
import { useMetricEvent } from '../../../hooks/useMetricEvent' import { useMetricEvent } from '../../../hooks/useMetricEvent'

@ -6,7 +6,7 @@ import * as actions from '../../../store/actions'
import { resetCustomData as resetCustomGasData } from '../../../ducks/gas/gas.duck' import { resetCustomData as resetCustomGasData } from '../../../ducks/gas/gas.duck'
import isMobileView from '../../../../lib/is-mobile-view' import isMobileView from '../../../../lib/is-mobile-view'
import { getEnvironmentType } from '../../../../../app/scripts/lib/util' 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 // Modal Components
import ConfirmCustomizeGasModal from '../gas-customization/gas-modal-page-container' import ConfirmCustomizeGasModal from '../gas-customization/gas-modal-page-container'

@ -3,7 +3,7 @@ import PropTypes from 'prop-types'
import log from 'loglevel' import log from 'loglevel'
import { BrowserQRCodeReader } from '@zxing/library' import { BrowserQRCodeReader } from '@zxing/library'
import { getEnvironmentType } from '../../../../../../app/scripts/lib/util' 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 Spinner from '../../../ui/spinner'
import WebcamUtils from '../../../../../lib/webcam-utils' import WebcamUtils from '../../../../../lib/webcam-utils'
import PageContainerFooter from '../../../ui/page-container/page-container-footer/page-container-footer.component' import PageContainerFooter from '../../../ui/page-container/page-container-footer/page-container-footer.component'

@ -1,21 +1,7 @@
import React, { Component } from 'react' import React, { Component } from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import classnames from 'classnames' import classnames from 'classnames'
import { import { NETWORK_TYPE_RPC } from '../../../../../shared/constants/network'
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',
}
export default class NetworkDisplay extends Component { export default class NetworkDisplay extends Component {
static defaultProps = { static defaultProps = {
@ -23,9 +9,9 @@ export default class NetworkDisplay extends Component {
} }
static propTypes = { static propTypes = {
networkNickname: PropTypes.string.isRequired,
networkType: PropTypes.string.isRequired,
colored: PropTypes.bool, colored: PropTypes.bool,
network: PropTypes.string,
provider: PropTypes.object,
} }
static contextTypes = { static contextTypes = {
@ -33,12 +19,11 @@ export default class NetworkDisplay extends Component {
} }
renderNetworkIcon() { renderNetworkIcon() {
const { network } = this.props const { networkType } = this.props
const networkClass = networkIdToTypeMap[network]
return networkClass ? ( return networkType ? (
<div <div
className={`network-display__icon network-display__icon--${networkClass}`} className={`network-display__icon network-display__icon--${networkType}`}
/> />
) : ( ) : (
<div <div
@ -52,24 +37,19 @@ export default class NetworkDisplay extends Component {
} }
render() { render() {
const { const { colored, networkNickname, networkType } = this.props
colored,
network,
provider: { type, nickname },
} = this.props
const networkClass = networkIdToTypeMap[network]
return ( return (
<div <div
className={classnames('network-display__container', { className={classnames('network-display__container', {
'network-display__container--colored': colored, 'network-display__container--colored': colored,
[`network-display__container--${networkClass}`]: [`network-display__container--${networkType}`]:
colored && networkClass, colored && networkType,
})} })}
> >
{networkClass ? ( {networkType ? (
<div <div
className={`network-display__icon network-display__icon--${networkClass}`} className={`network-display__icon network-display__icon--${networkType}`}
/> />
) : ( ) : (
<div <div
@ -81,7 +61,9 @@ export default class NetworkDisplay extends Component {
/> />
)} )}
<div className="network-display__name"> <div className="network-display__name">
{type === 'rpc' && nickname ? nickname : this.context.t(type)} {networkType === NETWORK_TYPE_RPC && networkNickname
? networkNickname
: this.context.t(networkType)}
</div> </div>
</div> </div>
) )

@ -1,10 +1,14 @@
import { connect } from 'react-redux' import { connect } from 'react-redux'
import NetworkDisplay from './network-display.component' import NetworkDisplay from './network-display.component'
const mapStateToProps = ({ metamask: { network, provider } }) => { const mapStateToProps = ({
metamask: {
provider: { nickname, type },
},
}) => {
return { return {
network, networkNickname: nickname,
provider, networkType: type,
} }
} }

@ -7,7 +7,7 @@ import { ObjectInspector } from 'react-inspector'
import { import {
ENVIRONMENT_TYPE_NOTIFICATION, ENVIRONMENT_TYPE_NOTIFICATION,
MESSAGE_TYPE, MESSAGE_TYPE,
} from '../../../../../app/scripts/lib/enums' } from '../../../../../shared/constants/app'
import { getEnvironmentType } from '../../../../../app/scripts/lib/util' import { getEnvironmentType } from '../../../../../app/scripts/lib/util'
import Identicon from '../../ui/identicon' import Identicon from '../../ui/identicon'
import AccountListItem from '../account-list-item' import AccountListItem from '../account-list-item'

@ -2,7 +2,7 @@ import { connect } from 'react-redux'
import { compose } from 'redux' import { compose } from 'redux'
import { withRouter } from 'react-router-dom' 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 { goHome } from '../../../store/actions'
import { import {
accountsWithSendEtherInfoSelector, accountsWithSendEtherInfoSelector,

@ -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 } export { ENVIRONMENT_TYPE_NOTIFICATION }

@ -2,7 +2,7 @@ import { connect } from 'react-redux'
import { clearConfirmTransaction } from '../../../ducks/confirm-transaction/confirm-transaction.duck' import { clearConfirmTransaction } from '../../../ducks/confirm-transaction/confirm-transaction.duck'
import { accountsWithSendEtherInfoSelector } from '../../../selectors' import { accountsWithSendEtherInfoSelector } from '../../../selectors'
import { getAccountByAddress } from '../../../helpers/utils/util' 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' import SignatureRequest from './signature-request.component'
function mapStateToProps(state) { function mapStateToProps(state) {

@ -34,7 +34,7 @@ import {
setSwapsFromToken, setSwapsFromToken,
} from '../../../ducks/swaps/swaps' } from '../../../ducks/swaps/swaps'
import IconButton from '../../ui/icon-button' 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' import WalletOverview from './wallet-overview'
const EthOverview = ({ className }) => { const EthOverview = ({ className }) => {

@ -27,7 +27,7 @@ import {
getCurrentKeyring, getCurrentKeyring,
getCurrentChainId, getCurrentChainId,
} from '../../../selectors/selectors' } 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 SwapIcon from '../../ui/icon/swap-icon.component'
import SendIcon from '../../ui/icon/overview-send-icon.component' import SendIcon from '../../ui/icon/overview-send-icon.component'

@ -0,0 +1,55 @@
import React from 'react'
import PropTypes from 'prop-types'
import classnames from 'classnames'
import { omit } from 'lodash'
import Typography from '../typography'
import { COLORS } from '../../../helpers/constants/design-system'
export default function Chip({
className,
children,
borderColor = COLORS.UI1,
label,
labelProps = {},
leftIcon,
rightIcon,
onClick,
}) {
return (
<div
onClick={onClick}
className={classnames(className, 'chip', {
'chip--with-left-icon': Boolean(leftIcon),
'chip--with-right-icon': Boolean(rightIcon),
[`chip--${borderColor}`]: true,
})}
role="button"
tabIndex={0}
>
{leftIcon && <div className="chip__left-icon">{leftIcon}</div>}
{children ?? (
<Typography
className="chip__label"
variant="h6"
tag="span"
color="UI4"
{...labelProps}
>
{label}
</Typography>
)}
{rightIcon && <div className="chip__right-icon">{rightIcon}</div>}
</div>
)
}
Chip.propTypes = {
borderColor: PropTypes.oneOf(Object.values(COLORS)),
label: PropTypes.string,
children: PropTypes.node,
labelProps: PropTypes.shape(omit(Typography.propTypes, ['className'])),
leftIcon: PropTypes.node,
rightIcon: PropTypes.node,
className: PropTypes.string,
onClick: PropTypes.func,
}

@ -0,0 +1,48 @@
@use "design-system";
.chip {
$self: &;
border-radius: 100px;
border: 1px solid design-system.$ui-1;
padding: 8px 16px;
margin: 0 4px;
display: flex;
align-items: center;
width: max-content;
&__left-icon,
&__right-icon {
display: flex;
align-items: center;
}
@each $variant, $color in design-system.$color-map {
&--#{$variant} {
border-color: $color;
}
}
&--with-left-icon,
&--with-right-icon {
padding-top: 4px;
padding-bottom: 4px;
}
&--with-left-icon {
padding-left: 4px;
#{$self}__label {
margin-left: 8px;
}
}
&--with-right-icon {
padding-right: 4px;
#{$self}__label {
margin-right: 8px;
}
}
}

@ -0,0 +1,82 @@
/* eslint-disable react/prop-types */
import React from 'react'
import { select, text } from '@storybook/addon-knobs'
import { COLORS, TYPOGRAPHY } from '../../../helpers/constants/design-system'
import ApproveIcon from '../icon/approve-icon.component'
import Identicon from '../identicon/identicon.component'
import Chip from '.'
export default {
title: 'Chip',
}
export const Plain = ({
leftIcon,
rightIcon,
label = 'Hello',
borderColor = COLORS.UI1,
fontColor = COLORS.BLACK,
}) => (
<Chip
leftIcon={leftIcon}
rightIcon={rightIcon}
label={text('label', label)}
labelProps={{
color: select('color', COLORS, fontColor),
variant: select('typography', TYPOGRAPHY, TYPOGRAPHY.H6),
}}
borderColor={select('borderColor', COLORS, borderColor)}
/>
)
export const WithLeftIcon = () => (
<Plain
label="Done!"
borderColor={COLORS.SUCCESS3}
fontColor={COLORS.SUCCESS3}
leftIcon={<ApproveIcon size={24} color="#4cd964" />}
/>
)
export const WithRightIcon = () => (
<Plain
label="0x5CfE73b6021E818B776b421B1c4Db2474086a7e1"
borderColor={COLORS.UI4}
fontColor={COLORS.UI4}
rightIcon={
<Identicon
address="0x5CfE73b6021E818B776b421B1c4Db2474086a7e1"
diameter={25}
/>
}
/>
)
export const WithBothIcons = () => (
<Plain
label="Account 1"
borderColor={COLORS.UI4}
fontColor={COLORS.UI4}
rightIcon={
<svg
width="10"
height="6"
viewBox="0 0 10 6"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M9.45759 0.857142C9.45759 0.785714 9.42188 0.705357 9.3683 0.651785L8.92188 0.205357C8.8683 0.151785 8.78795 0.116071 8.71652 0.116071C8.64509 0.116071 8.56473 0.151785 8.51116 0.205357L5.00223 3.71429L1.4933 0.205357C1.43973 0.151785 1.35938 0.116071 1.28795 0.116071C1.20759 0.116071 1.13616 0.151785 1.08259 0.205357L0.636161 0.651785C0.582589 0.705357 0.546875 0.785714 0.546875 0.857142C0.546875 0.928571 0.582589 1.00893 0.636161 1.0625L4.79688 5.22321C4.85045 5.27679 4.9308 5.3125 5.00223 5.3125C5.07366 5.3125 5.15402 5.27679 5.20759 5.22321L9.3683 1.0625C9.42188 1.00893 9.45759 0.928571 9.45759 0.857142Z"
fill="#24292E"
/>
</svg>
}
leftIcon={
<Identicon
address="0x5CfE73b6021E818B776b421B1c4Db2474086a7e1"
diameter={25}
/>
}
/>
)

@ -0,0 +1 @@
export { default } from './chip'

@ -0,0 +1 @@
export { default } from './typography'

@ -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 <Tag className={computedClassName}>{children}</Tag>
}
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',
]),
}

@ -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;
}
}
}

@ -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 = () => (
<div style={{ width: '80%', flexDirection: 'column' }}>
{Object.values(TYPOGRAPHY).map((variant) => (
<div key={variant} style={{ width: '100%' }}>
<Typography
variant={variant}
color={select('color', COLORS, COLORS.BLACK)}
spacing={number('spacing', 1, { range: true, min: 1, max: 8 })}
align={select('align', alignOptions, undefined)}
fontWeight={select('font weight', fontWeightOptions, 'normal')}
>
{variant}
</Typography>
</div>
))}
</div>
)
export const TheQuickOrangeFox = () => (
<div style={{ width: '80%', flexDirection: 'column' }}>
<div style={{ width: '100%' }}>
<Typography
color={select('color', COLORS, COLORS.BLACK)}
variant={select('variant', TYPOGRAPHY, TYPOGRAPHY.Paragraph)}
spacing={number('spacing', 1, { range: true, min: 1, max: 8 })}
align={select('align', alignOptions, undefined)}
fontWeight={select('font weight', fontWeightOptions, 'normal')}
>
{text('content', 'The quick orange fox jumped over the lazy dog.')}
</Typography>
</div>
</div>
)

@ -7,6 +7,7 @@
@import 'button/buttons'; @import 'button/buttons';
@import 'card/index'; @import 'card/index';
@import 'check-box/index'; @import 'check-box/index';
@import 'chip/chip';
@import 'circle-icon/index'; @import 'circle-icon/index';
@import 'currency-display/index'; @import 'currency-display/index';
@import 'currency-input/index'; @import 'currency-input/index';
@ -37,5 +38,6 @@
@import 'toggle-button/index'; @import 'toggle-button/index';
@import 'token-balance/index'; @import 'token-balance/index';
@import 'tooltip/index'; @import 'tooltip/index';
@import 'typography/typography';
@import 'unit-input/index'; @import 'unit-input/index';
@import 'url-icon/index'; @import 'url-icon/index';

@ -74,3 +74,67 @@ $accent-pink: #ff45d8;
$neutral-white: #fff; $neutral-white: #fff;
$neutral-black: $Black-100; $neutral-black: $Black-100;
$neutral-grey: $Grey-500; $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,
'transparent': transparent,
);

@ -1,5 +1,5 @@
@import 'breakpoints'; @forward 'breakpoints';
@import 'colors'; @forward 'colors';
@import 'deprecated-colors'; @forward 'deprecated-colors';
@import 'typography'; @forward 'typography';
@import 'z-index'; @forward 'z-index';

@ -69,89 +69,80 @@ $fa-font-path: 'fonts/fontawesome';
$font-family: Euclid, Roboto, Helvetica, Arial, sans-serif; $font-family: Euclid, Roboto, Helvetica, Arial, sans-serif;
$font-size-h1: 2.5rem; $typography-variants: (
$font-size-h2: 2rem; 'h1': 2.5rem,
$font-size-h3: 1.5rem; 'h2': 2rem,
$font-size-h4: 1.125rem; 'h3': 1.5rem,
$font-size-h5: 1rem; 'h4': 1.125rem,
$font-size-h6: 0.875rem; 'h5': 1rem,
$font-size-paragraph: 1rem; 'h6': 0.875rem,
$font-size-h7: 0.75rem; 'paragraph': 1rem,
$font-size-h8: 0.625rem; 'h7': 0.75rem,
$font-size-h9: 0.5rem; 'h8': 0.625rem,
'h9': 0.5rem,
// Typography );
@mixin H1 {
font-style: normal; $typography-font-weights: (
font-weight: normal; 'bold': 700,
font-size: $font-size-h1; '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; font-family: $font-family;
line-height: 140%; line-height: 140%;
font-style: normal;
font-weight: normal;
} }
// Typography
@mixin H1 {
@include typography('h1');
}
@mixin H2 { @mixin H2 {
font-style: normal; @include typography('h2');
font-weight: normal;
font-size: $font-size-h2;
font-family: $font-family;
line-height: 140%;
} }
@mixin H3 { @mixin H3 {
font-style: normal; @include typography('h3');
font-weight: normal;
font-size: $font-size-h3;
font-family: $font-family;
line-height: 140%;
} }
@mixin H4 { @mixin H4 {
font-style: normal; @include typography('h4');
font-weight: normal;
font-size: $font-size-h4;
font-family: $font-family;
line-height: 140%;
} }
@mixin H5 { @mixin H5 {
font-style: normal; @include typography('h5');
font-weight: normal;
font-size: $font-size-h5;
line-height: 140%;
} }
@mixin H6 { @mixin H6 {
font-style: normal; @include typography('h6');
font-weight: normal;
font-size: $font-size-h6; // 14px @default
line-height: 140%;
} }
@mixin Paragraph { @mixin Paragraph {
font-style: normal; @include typography('paragraph');
font-weight: normal;
font-size: $font-size-paragraph;
line-height: 140%;
} }
@mixin H7 { @mixin H7 {
font-style: normal; @include typography('h7');
font-weight: normal;
font-size: $font-size-h7;
line-height: 140%;
} }
@mixin H8 { @mixin H8 {
font-style: normal; @include typography('h8');
font-weight: normal;
font-size: $font-size-h8;
line-height: 140%;
} }
@mixin H9 { @mixin H9 {
font-style: normal; @include typography('h9');
font-weight: normal;
font-size: $font-size-h9;
line-height: 140%;
} }

@ -1,8 +1,10 @@
import { cloneDeep } from 'lodash' import { cloneDeep } from 'lodash'
import BigNumber from 'bignumber.js' import BigNumber from 'bignumber.js'
import { getStorageItem, setStorageItem } from '../../../lib/storage-helpers' import { getStorageItem, setStorageItem } from '../../../lib/storage-helpers'
import { decGWEIToHexWEI } from '../../helpers/utils/conversions.util' import { decGWEIToHexWEI } from '../../helpers/utils/conversions.util'
import getFetchWithTimeout from '../../../../shared/modules/fetch-with-timeout'
const fetchWithTimeout = getFetchWithTimeout(30000)
// Actions // Actions
const BASIC_GAS_ESTIMATE_LOADING_FINISHED = const BASIC_GAS_ESTIMATE_LOADING_FINISHED =
@ -97,7 +99,7 @@ export function basicGasEstimatesLoadingFinished() {
async function basicGasPriceQuery() { async function basicGasPriceQuery() {
const url = `https://api.metaswap.codefi.network/gasPrices` const url = `https://api.metaswap.codefi.network/gasPrices`
return await window.fetch(url, { return await fetchWithTimeout(url, {
headers: {}, headers: {},
referrer: 'https://api.metaswap.codefi.network/gasPrices', referrer: 'https://api.metaswap.codefi.network/gasPrices',
referrerPolicy: 'no-referrer-when-downgrade', referrerPolicy: 'no-referrer-when-downgrade',

@ -1,5 +1,6 @@
import * as actionConstants from '../../store/actionConstants' import * as actionConstants from '../../store/actionConstants'
import { ALERT_TYPES } from '../../../../shared/constants/alerts' import { ALERT_TYPES } from '../../../../shared/constants/alerts'
import { NETWORK_TYPE_RPC } from '../../../../shared/constants/network'
export default function reduceMetamask(state = {}, action) { export default function reduceMetamask(state = {}, action) {
const metamaskState = { const metamaskState = {
@ -63,7 +64,7 @@ export default function reduceMetamask(state = {}, action) {
return { return {
...metamaskState, ...metamaskState,
provider: { provider: {
type: 'rpc', type: NETWORK_TYPE_RPC,
rpcUrl: action.value, rpcUrl: action.value,
}, },
} }

@ -329,8 +329,8 @@ export {
export const navigateBackToBuildQuote = (history) => { export const navigateBackToBuildQuote = (history) => {
return async (dispatch) => { return async (dispatch) => {
// TODO: Ensure any fetch in progress is cancelled // TODO: Ensure any fetch in progress is cancelled
await dispatch(setBackgroundSwapRouteState(''))
dispatch(navigatedBackToBuildQuote()) dispatch(navigatedBackToBuildQuote())
history.push(BUILD_QUOTE_ROUTE) history.push(BUILD_QUOTE_ROUTE)
} }
} }

@ -5,14 +5,6 @@ export const WEI = 'WEI'
export const PRIMARY = 'PRIMARY' export const PRIMARY = 'PRIMARY'
export const SECONDARY = 'SECONDARY' export const SECONDARY = 'SECONDARY'
export const NETWORK_TYPES = {
KOVAN: 'kovan',
MAINNET: 'mainnet',
RINKEBY: 'rinkeby',
ROPSTEN: 'ropsten',
GOERLI: 'goerli',
}
export const GAS_ESTIMATE_TYPES = { export const GAS_ESTIMATE_TYPES = {
SLOW: 'SLOW', SLOW: 'SLOW',
AVERAGE: 'AVERAGE', AVERAGE: 'AVERAGE',

@ -0,0 +1,42 @@
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: 'error-1',
ERROR2: 'error-2',
ERROR3: 'error-3',
ALERT1: 'alert-1',
ALERT2: 'alert-2',
ALERT3: 'alert-3',
MAINNET: 'mainnet',
ROPSTEN: 'ropsten',
KOVAN: 'kovan',
RINKEBY: 'rinkeby',
GOERLI: 'goerli',
TRANSPARENT: 'transparent',
}
export const TYPOGRAPHY = {
H1: 'h1',
H2: 'h2',
H3: 'h3',
H4: 'h4',
H5: 'h5',
H6: 'h6',
H7: 'h7',
H8: 'h8',
H9: 'h9',
Paragraph: 'paragraph',
}

@ -1,5 +1,5 @@
import { getStorageItem, setStorageItem } from '../../../lib/storage-helpers' 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 ( const fetchWithCache = async (
url, url,
@ -29,8 +29,8 @@ const fetchWithCache = async (
return cachedResponse return cachedResponse
} }
fetchOptions.headers.set('Content-Type', 'application/json') fetchOptions.headers.set('Content-Type', 'application/json')
const _fetch = timeout ? fetchWithTimeout({ timeout }) : window.fetch const fetchWithTimeout = getFetchWithTimeout(timeout)
const response = await _fetch(url, { const response = await fetchWithTimeout(url, {
referrerPolicy: 'no-referrer-when-downgrade', referrerPolicy: 'no-referrer-when-downgrade',
body: null, body: null,
method: 'GET', method: 'GET',

@ -1,9 +1,12 @@
// cross-browser connection to extension i18n API // cross-browser connection to extension i18n API
import React from 'react' import React from 'react'
import log from 'loglevel' import log from 'loglevel'
import * as Sentry from '@sentry/browser' import * as Sentry from '@sentry/browser'
import getFetchWithTimeout from '../../../../shared/modules/fetch-with-timeout'
const fetchWithTimeout = getFetchWithTimeout(30000)
const warned = {} const warned = {}
const missingMessageErrors = {} const missingMessageErrors = {}
const missingSubstitutionErrors = {} const missingSubstitutionErrors = {}
@ -95,7 +98,7 @@ export const getMessage = (localeCode, localeMessages, key, substitutions) => {
export async function fetchLocale(localeCode) { export async function fetchLocale(localeCode) {
try { try {
const response = await window.fetch( const response = await fetchWithTimeout(
`./_locales/${localeCode}/messages.json`, `./_locales/${localeCode}/messages.json`,
) )
return await response.json() return await response.json()
@ -120,7 +123,7 @@ export async function loadRelativeTimeFormatLocaleData(localeCode) {
} }
async function fetchRelativeTimeFormatData(languageTag) { async function fetchRelativeTimeFormatData(languageTag) {
const response = await window.fetch( const response = await fetchWithTimeout(
`./intl/${languageTag}/relative-time-format-data.json`, `./intl/${languageTag}/relative-time-format-data.json`,
) )
return await response.json() return await response.json()

@ -4,6 +4,9 @@ import BigNumber from 'bignumber.js'
import ethUtil from 'ethereumjs-util' import ethUtil from 'ethereumjs-util'
import { DateTime } from 'luxon' import { DateTime } from 'luxon'
import { addHexPrefix } from '../../../../app/scripts/lib/util' import { addHexPrefix } from '../../../../app/scripts/lib/util'
import getFetchWithTimeout from '../../../../shared/modules/fetch-with-timeout'
const fetchWithTimeout = getFetchWithTimeout(30000)
// formatData :: ( date: <Unix Timestamp> ) -> String // formatData :: ( date: <Unix Timestamp> ) -> String
export function formatDate(date, format = "M/d/y 'at' T") { export function formatDate(date, format = "M/d/y 'at' T") {
@ -478,8 +481,7 @@ export async function jsonRpcRequest(rpcUrl, rpcMethod, rpcParams = []) {
headers.Authorization = `Basic ${encodedAuth}` headers.Authorization = `Basic ${encodedAuth}`
fetchUrl = `${origin}${pathname}${search}` fetchUrl = `${origin}${pathname}${search}`
} }
const jsonRpcResponse = await window const jsonRpcResponse = await fetchWithTimeout(fetchUrl, {
.fetch(fetchUrl, {
method: 'POST', method: 'POST',
body: JSON.stringify({ body: JSON.stringify({
id: Date.now().toString(), id: Date.now().toString(),
@ -489,8 +491,7 @@ export async function jsonRpcRequest(rpcUrl, rpcMethod, rpcParams = []) {
}), }),
headers, headers,
cache: 'default', cache: 'default',
}) }).then((httpResponse) => httpResponse.json())
.then((httpResponse) => httpResponse.json())
if ( if (
!jsonRpcResponse || !jsonRpcResponse ||

@ -4,7 +4,7 @@ import Button from '../../components/ui/button'
import Identicon from '../../components/ui/identicon' import Identicon from '../../components/ui/identicon'
import TokenBalance from '../../components/ui/token-balance' import TokenBalance from '../../components/ui/token-balance'
import { getEnvironmentType } from '../../../../app/scripts/lib/util' 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 { export default class ConfirmAddSuggestedToken extends Component {
static contextTypes = { static contextTypes = {

@ -9,7 +9,7 @@ import Identicon from '../../components/ui/identicon'
import Tooltip from '../../components/ui/tooltip' import Tooltip from '../../components/ui/tooltip'
import Copy from '../../components/ui/icon/copy-icon.component' 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 { getEnvironmentType } from '../../../../app/scripts/lib/util'
import { conversionUtil } from '../../helpers/utils/conversion-util' import { conversionUtil } from '../../helpers/utils/conversion-util'

@ -5,7 +5,7 @@ import AccountListItem from '../../components/app/account-list-item'
import Button from '../../components/ui/button' import Button from '../../components/ui/button'
import Identicon from '../../components/ui/identicon' 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 { getEnvironmentType } from '../../../../app/scripts/lib/util'
import { conversionUtil } from '../../helpers/utils/conversion-util' import { conversionUtil } from '../../helpers/utils/conversion-util'

@ -1,7 +1,7 @@
import ethUtil from 'ethereumjs-util' import ethUtil from 'ethereumjs-util'
import React, { Component } from 'react' import React, { Component } from 'react'
import PropTypes from 'prop-types' 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 { getEnvironmentType } from '../../../../app/scripts/lib/util'
import ConfirmPageContainer, { import ConfirmPageContainer, {
ConfirmDetailRow, ConfirmDetailRow,

@ -14,7 +14,7 @@ import {
DECRYPT_MESSAGE_REQUEST_PATH, DECRYPT_MESSAGE_REQUEST_PATH,
ENCRYPTION_PUBLIC_KEY_REQUEST_PATH, ENCRYPTION_PUBLIC_KEY_REQUEST_PATH,
} from '../../helpers/constants/routes' } 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' import { TRANSACTION_CATEGORIES } from '../../../../shared/constants/transaction'
export default class ConfirmTransactionSwitch extends Component { export default class ConfirmTransactionSwitch extends Component {

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save