mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-22 09:57:02 +01:00
Merge remote-tracking branch 'origin/develop' into sync-master
* origin/develop: (137 commits) Use @metamask/eslint-config@3.1.0 (#9275) Standardize scss import practices (#9183) Update ESLint shared config to v3 (#9274) Add lock icon to default networks (#9269) Adds toPrecisionWithoutTrailingZeros utility (#9270) Hide gas estimate on non-main network (#9189) Move the mascot component to its own directory (#9272) Use @metamask/controllers@2.0.5 (#9266) Fix padding, alignment of actionable-message; add left aligned story Code cleanup and simplification for actionable-message component Adds actionable message component and stories Fix lint issues (#9265) Fix prefer-destructuring issues (#9263) colocate confirm-decrypt-message page styles (#9252) Tidy up Migrator tests (#9264) Adds pulse loader component (#9259) Fix import/order issues (#9239) Fix radix issues (#9247) New info tooltip component (#9180) Improve scss naming ...
This commit is contained in:
commit
0c72d0bc3d
@ -3,14 +3,9 @@
|
||||
node_modules/**
|
||||
dist/**
|
||||
builds/**
|
||||
test-builds/**
|
||||
test-*/**
|
||||
docs/**
|
||||
coverage/
|
||||
|
||||
app/scripts/lib/extension-instance.js
|
||||
app/scripts/chromereload.js
|
||||
app/vendor/**
|
||||
|
||||
ui/lib/blockies.js
|
||||
|
||||
package-lock.json
|
||||
|
89
.eslintrc.js
89
.eslintrc.js
@ -41,34 +41,22 @@ module.exports = {
|
||||
},
|
||||
|
||||
rules: {
|
||||
/* TODO: Remove these when upgrading to `@metamask/eslint-config@2` */
|
||||
'array-callback-return': 'error',
|
||||
'callback-return': 'error',
|
||||
'global-require': 'error',
|
||||
'guard-for-in': 'error',
|
||||
/* End v2 rules */
|
||||
'arrow-parens': 'error',
|
||||
'no-tabs': 'error',
|
||||
'no-mixed-operators': 'error',
|
||||
'import/default': 'error',
|
||||
'import/export': 'error',
|
||||
'import/named': 'error',
|
||||
'import/namespace': 'error',
|
||||
'import/newline-after-import': 'error',
|
||||
'import/no-absolute-path': 'error',
|
||||
'import/no-amd': 'error',
|
||||
'import/no-anonymous-default-export': 'error',
|
||||
'import/no-duplicates': 'error',
|
||||
'import/no-dynamic-require': 'error',
|
||||
'import/no-mutable-exports': 'error',
|
||||
'import/no-named-as-default': 'error',
|
||||
'import/no-named-as-default-member': 'error',
|
||||
'import/no-named-default': 'error',
|
||||
'import/no-self-import': 'error',
|
||||
'import/no-unresolved': ['error', { 'commonjs': true }],
|
||||
'import/no-unused-modules': 'error',
|
||||
'import/no-useless-path-segments': ['error', { 'commonjs': true }],
|
||||
'import/no-webpack-loader-syntax': 'error',
|
||||
'default-param-last': 'off',
|
||||
'require-atomic-updates': 'off',
|
||||
'import/no-unassigned-import': 'off',
|
||||
'prefer-destructuring': ['error', {
|
||||
'VariableDeclarator': {
|
||||
'array': false,
|
||||
'object': true,
|
||||
},
|
||||
'AssignmentExpression': {
|
||||
'array': false,
|
||||
'object': false,
|
||||
},
|
||||
}, {
|
||||
'enforceForRenamedProperties': false,
|
||||
}],
|
||||
'prefer-object-spread': 'error',
|
||||
'react/no-unused-prop-types': 'error',
|
||||
'react/no-unused-state': 'error',
|
||||
'react/jsx-boolean-value': 'error',
|
||||
@ -80,7 +68,7 @@ module.exports = {
|
||||
'react/jsx-no-duplicate-props': 'error',
|
||||
'react/jsx-closing-bracket-location': 'error',
|
||||
'react/jsx-first-prop-new-line': ['error', 'multiline'],
|
||||
'react/jsx-max-props-per-line': ['error', { 'maximum': 1, 'when': 'multiline' } ],
|
||||
'react/jsx-max-props-per-line': ['error', { 'maximum': 1, 'when': 'multiline' }],
|
||||
'react/jsx-tag-spacing': ['error', {
|
||||
'closingSlash': 'never',
|
||||
'beforeSelfClosing': 'always',
|
||||
@ -95,11 +83,22 @@ module.exports = {
|
||||
'logical': 'parens-new-line',
|
||||
'prop': 'parens-new-line',
|
||||
}],
|
||||
|
||||
'no-invalid-this': 'off',
|
||||
'babel/no-invalid-this': 'error',
|
||||
|
||||
'babel/semi': ['error', 'never'],
|
||||
'mocha/no-setup-in-describe': 'off',
|
||||
},
|
||||
|
||||
overrides: [{
|
||||
files: [
|
||||
'test/e2e/**/*.js',
|
||||
],
|
||||
rules: {
|
||||
'mocha/no-hooks-for-single-case': 'off',
|
||||
},
|
||||
}, {
|
||||
files: [
|
||||
'app/scripts/migrations/*.js',
|
||||
'*.stories.js',
|
||||
@ -114,6 +113,38 @@ module.exports = {
|
||||
rules: {
|
||||
'global-require': 'off',
|
||||
},
|
||||
}, {
|
||||
files: [
|
||||
'test/**/*-test.js',
|
||||
'test/**/*.spec.js',
|
||||
],
|
||||
rules: {
|
||||
// Mocha will re-assign `this` in a test context
|
||||
'babel/no-invalid-this': 'off',
|
||||
},
|
||||
}, {
|
||||
files: [
|
||||
'development/**/*.js',
|
||||
'test/e2e/benchmark.js',
|
||||
'test/helper.js',
|
||||
],
|
||||
rules: {
|
||||
'no-process-exit': 'off',
|
||||
},
|
||||
}, {
|
||||
files: [
|
||||
'.eslintrc.js',
|
||||
'babel.config.js',
|
||||
'nyc.config.js',
|
||||
'stylelint.config.js',
|
||||
'development/**/*.js',
|
||||
'test/e2e/**/*.js',
|
||||
'test/env.js',
|
||||
'test/setup.js',
|
||||
],
|
||||
parserOptions: {
|
||||
sourceType: 'script',
|
||||
},
|
||||
}],
|
||||
|
||||
settings: {
|
||||
|
@ -1,5 +1,5 @@
|
||||
module.exports = {
|
||||
stories: ['../ui/app/components/**/*.stories.js'],
|
||||
stories: ['../ui/app/**/*.stories.js'],
|
||||
addons: [
|
||||
'@storybook/addon-knobs',
|
||||
'@storybook/addon-actions',
|
||||
|
@ -29,11 +29,13 @@ module.exports = {
|
||||
],
|
||||
},
|
||||
plugins: [
|
||||
new CopyWebpackPlugin([
|
||||
{
|
||||
from: path.join('node_modules', '@fortawesome', 'fontawesome-free', 'webfonts'),
|
||||
to: path.join('fonts', 'fontawesome'),
|
||||
},
|
||||
]),
|
||||
new CopyWebpackPlugin({
|
||||
patterns: [
|
||||
{
|
||||
from: path.join('node_modules', '@fortawesome', 'fontawesome-free', 'webfonts'),
|
||||
to: path.join('fonts', 'fontawesome'),
|
||||
},
|
||||
],
|
||||
}),
|
||||
],
|
||||
}
|
||||
|
BIN
app/fonts/Euclid/EuclidCircularB-Bold-WebXL.ttf
Normal file
BIN
app/fonts/Euclid/EuclidCircularB-Bold-WebXL.ttf
Normal file
Binary file not shown.
BIN
app/fonts/Euclid/EuclidCircularB-Regular-WebXL.ttf
Normal file
BIN
app/fonts/Euclid/EuclidCircularB-Regular-WebXL.ttf
Normal file
Binary file not shown.
BIN
app/fonts/Euclid/EuclidCircularB-RegularItalic-WebXL.ttf
Normal file
BIN
app/fonts/Euclid/EuclidCircularB-RegularItalic-WebXL.ttf
Normal file
Binary file not shown.
@ -8,7 +8,7 @@ const accountImporter = {
|
||||
importAccount (strategy, args) {
|
||||
try {
|
||||
const importer = this.strategies[strategy]
|
||||
const privateKeyHex = importer.apply(null, args)
|
||||
const privateKeyHex = importer(...args)
|
||||
return Promise.resolve(privateKeyHex)
|
||||
} catch (e) {
|
||||
return Promise.reject(e)
|
||||
|
@ -1,11 +1,11 @@
|
||||
/**
|
||||
* @file The entry point for the web extension singleton process.
|
||||
*/
|
||||
|
||||
|
||||
// these need to run before anything else
|
||||
/* eslint-disable import/first,import/order */
|
||||
import './lib/freezeGlobals'
|
||||
import setupFetchDebugging from './lib/setupFetchDebugging'
|
||||
/* eslint-enable import/order */
|
||||
|
||||
setupFetchDebugging()
|
||||
|
||||
@ -17,16 +17,16 @@ import pump from 'pump'
|
||||
import debounce from 'debounce-stream'
|
||||
import log from 'loglevel'
|
||||
import extension from 'extensionizer'
|
||||
import ReadOnlyNetworkStore from './lib/network-store'
|
||||
import LocalStore from './lib/local-store'
|
||||
import storeTransform from 'obs-store/lib/transform'
|
||||
import asStream from 'obs-store/lib/asStream'
|
||||
import ExtensionPlatform from './platforms/extension'
|
||||
import Migrator from './lib/migrator'
|
||||
import migrations from './migrations'
|
||||
import PortStream from 'extension-port-stream'
|
||||
import migrations from './migrations'
|
||||
import Migrator from './lib/migrator'
|
||||
import ExtensionPlatform from './platforms/extension'
|
||||
import LocalStore from './lib/local-store'
|
||||
import ReadOnlyNetworkStore from './lib/network-store'
|
||||
import createStreamSink from './lib/createStreamSink'
|
||||
import NotificationManager from './lib/notification-manager.js'
|
||||
import NotificationManager from './lib/notification-manager'
|
||||
import MetamaskController from './metamask-controller'
|
||||
import rawFirstTimeState from './first-time-state'
|
||||
import setupSentry from './lib/setupSentry'
|
||||
@ -39,9 +39,10 @@ import {
|
||||
ENVIRONMENT_TYPE_NOTIFICATION,
|
||||
ENVIRONMENT_TYPE_FULLSCREEN,
|
||||
} from './lib/enums'
|
||||
/* eslint-enable import/first */
|
||||
|
||||
// METAMASK_TEST_CONFIG is used in e2e tests to set the default network to localhost
|
||||
const firstTimeState = Object.assign({}, rawFirstTimeState, global.METAMASK_TEST_CONFIG)
|
||||
const firstTimeState = { ...rawFirstTimeState, ...global.METAMASK_TEST_CONFIG }
|
||||
|
||||
log.setDefaultLevel(process.env.METAMASK_DEBUG ? 'debug' : 'warn')
|
||||
|
||||
@ -327,7 +328,7 @@ function setupController (initState, initLangCode) {
|
||||
const isMetaMaskInternalProcess = metamaskInternalProcessHash[processName]
|
||||
|
||||
if (metamaskBlockedPorts.includes(remotePort.name)) {
|
||||
return false
|
||||
return
|
||||
}
|
||||
|
||||
if (isMetaMaskInternalProcess) {
|
||||
@ -406,11 +407,11 @@ function setupController (initState, initLangCode) {
|
||||
function updateBadge () {
|
||||
let label = ''
|
||||
const unapprovedTxCount = controller.txController.getUnapprovedTxCount()
|
||||
const unapprovedMsgCount = controller.messageManager.unapprovedMsgCount
|
||||
const unapprovedPersonalMsgCount = controller.personalMessageManager.unapprovedPersonalMsgCount
|
||||
const unapprovedDecryptMsgCount = controller.decryptMessageManager.unapprovedDecryptMsgCount
|
||||
const unapprovedEncryptionPublicKeyMsgCount = controller.encryptionPublicKeyManager.unapprovedEncryptionPublicKeyMsgCount
|
||||
const unapprovedTypedMessagesCount = controller.typedMessageManager.unapprovedTypedMessagesCount
|
||||
const { unapprovedMsgCount } = controller.messageManager
|
||||
const { unapprovedPersonalMsgCount } = controller.personalMessageManager
|
||||
const { unapprovedDecryptMsgCount } = controller.decryptMessageManager
|
||||
const { unapprovedEncryptionPublicKeyMsgCount } = controller.encryptionPublicKeyManager
|
||||
const { unapprovedTypedMessagesCount } = controller.typedMessageManager
|
||||
const pendingPermissionRequests = Object.keys(controller.permissionsController.permissions.state.permissionsRequests).length
|
||||
const waitingForUnlockCount = controller.appStateController.waitingForUnlock.length
|
||||
const count = unapprovedTxCount + unapprovedMsgCount + unapprovedPersonalMsgCount + unapprovedDecryptMsgCount + unapprovedEncryptionPublicKeyMsgCount +
|
||||
|
@ -1,5 +1,5 @@
|
||||
import pump from 'pump'
|
||||
import querystring from 'querystring'
|
||||
import pump from 'pump'
|
||||
import LocalMessageDuplexStream from 'post-message-stream'
|
||||
import ObjectMultiplex from 'obj-multiplex'
|
||||
import extension from 'extensionizer'
|
||||
@ -10,7 +10,7 @@ const fs = require('fs')
|
||||
const path = require('path')
|
||||
|
||||
const inpageContent = fs.readFileSync(path.join(__dirname, '..', '..', 'dist', 'chrome', 'inpage.js'), 'utf8')
|
||||
const inpageSuffix = '//# sourceURL=' + extension.runtime.getURL('inpage.js') + '\n'
|
||||
const inpageSuffix = `//# sourceURL=${extension.runtime.getURL('inpage.js')}\n`
|
||||
const inpageBundle = inpageContent + inpageSuffix
|
||||
|
||||
// Eventually this streaming injection could be replaced with:
|
||||
@ -115,7 +115,7 @@ function forwardTrafficBetweenMuxers (channelName, muxA, muxB) {
|
||||
function logStreamDisconnectWarning (remoteLabel, err) {
|
||||
let warningMsg = `MetamaskContentscript - lost connection to ${remoteLabel}`
|
||||
if (err) {
|
||||
warningMsg += '\n' + err.stack
|
||||
warningMsg += `\n${err.stack}`
|
||||
}
|
||||
console.warn(warningMsg)
|
||||
}
|
||||
@ -136,12 +136,11 @@ function shouldInjectProvider () {
|
||||
* @returns {boolean} {@code true} - if the doctype is html or if none exists
|
||||
*/
|
||||
function doctypeCheck () {
|
||||
const doctype = window.document.doctype
|
||||
const { doctype } = window.document
|
||||
if (doctype) {
|
||||
return doctype.name === 'html'
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
@ -155,8 +154,8 @@ function doctypeCheck () {
|
||||
*/
|
||||
function suffixCheck () {
|
||||
const prohibitedTypes = [
|
||||
/\.xml$/,
|
||||
/\.pdf$/,
|
||||
/\.xml$/u,
|
||||
/\.pdf$/u,
|
||||
]
|
||||
const currentUrl = window.location.pathname
|
||||
for (let i = 0; i < prohibitedTypes.length; i++) {
|
||||
@ -202,7 +201,7 @@ function blockedDomainCheck () {
|
||||
let currentRegex
|
||||
for (let i = 0; i < blockedDomains.length; i++) {
|
||||
const blockedDomain = blockedDomains[i].replace('.', '\\.')
|
||||
currentRegex = new RegExp(`(?:https?:\\/\\/)(?:(?!${blockedDomain}).)*$`)
|
||||
currentRegex = new RegExp(`(?:https?:\\/\\/)(?:(?!${blockedDomain}).)*$`, 'u')
|
||||
if (!currentRegex.test(currentUrl)) {
|
||||
return true
|
||||
}
|
||||
@ -228,7 +227,7 @@ function redirectToPhishingWarning () {
|
||||
async function domIsReady () {
|
||||
// already loaded
|
||||
if (['interactive', 'complete'].includes(document.readyState)) {
|
||||
return
|
||||
return undefined
|
||||
}
|
||||
// wait for load
|
||||
return new Promise((resolve) => window.addEventListener('DOMContentLoaded', resolve, { once: true }))
|
||||
|
@ -32,24 +32,21 @@ const defaultState = {
|
||||
* alert related state
|
||||
*/
|
||||
export default class AlertController {
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @param {AlertControllerOptions} [opts] - Controller configuration parameters
|
||||
*/
|
||||
constructor (opts = {}) {
|
||||
const { initState, preferencesStore } = opts
|
||||
const state = Object.assign(
|
||||
{},
|
||||
defaultState,
|
||||
initState,
|
||||
{
|
||||
unconnectedAccountAlertShownOrigins: {},
|
||||
},
|
||||
)
|
||||
const state = {
|
||||
...defaultState,
|
||||
...initState,
|
||||
unconnectedAccountAlertShownOrigins: {},
|
||||
}
|
||||
this.store = new ObservableStore(state)
|
||||
|
||||
const { selectedAddress } = preferencesStore.getState()
|
||||
this.selectedAddress = selectedAddress
|
||||
this.selectedAddress = preferencesStore.getState().selectedAddress
|
||||
|
||||
preferencesStore.subscribe(({ selectedAddress }) => {
|
||||
const currentState = this.store.getState()
|
||||
|
@ -1,7 +1,8 @@
|
||||
import ObservableStore from 'obs-store'
|
||||
import EventEmitter from 'events'
|
||||
import ObservableStore from 'obs-store'
|
||||
|
||||
export default class AppStateController extends EventEmitter {
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @param opts
|
||||
@ -15,16 +16,14 @@ export default class AppStateController extends EventEmitter {
|
||||
showUnlockRequest,
|
||||
preferencesStore,
|
||||
} = opts
|
||||
const { preferences } = preferencesStore.getState()
|
||||
|
||||
super()
|
||||
|
||||
this.onInactiveTimeout = onInactiveTimeout || (() => {})
|
||||
this.store = new ObservableStore(Object.assign({
|
||||
this.onInactiveTimeout = onInactiveTimeout || (() => undefined)
|
||||
this.store = new ObservableStore({
|
||||
timeoutMinutes: 0,
|
||||
connectedStatusPopoverHasBeenShown: true,
|
||||
defaultHomeActiveTabName: null,
|
||||
}, initState))
|
||||
defaultHomeActiveTabName: null, ...initState,
|
||||
})
|
||||
this.timer = null
|
||||
|
||||
this.isUnlocked = isUnlocked
|
||||
@ -40,6 +39,7 @@ export default class AppStateController extends EventEmitter {
|
||||
}
|
||||
})
|
||||
|
||||
const { preferences } = preferencesStore.getState()
|
||||
this._setInactiveTimeout(preferences.autoLockTimeLimit)
|
||||
}
|
||||
|
||||
|
@ -12,6 +12,7 @@ import ObservableStore from 'obs-store'
|
||||
* a cache of account balances in local storage
|
||||
*/
|
||||
export default class CachedBalancesController {
|
||||
|
||||
/**
|
||||
* Creates a new controller instance
|
||||
*
|
||||
@ -23,9 +24,7 @@ export default class CachedBalancesController {
|
||||
this.accountTracker = accountTracker
|
||||
this.getNetwork = getNetwork
|
||||
|
||||
const initState = Object.assign({
|
||||
cachedBalances: {},
|
||||
}, opts.initState)
|
||||
const initState = { cachedBalances: {}, ...opts.initState }
|
||||
this.store = new ObservableStore(initState)
|
||||
|
||||
this._registerUpdates()
|
||||
|
@ -1,17 +1,19 @@
|
||||
import Web3 from 'web3'
|
||||
import contracts from 'eth-contract-metadata'
|
||||
import { warn } from 'loglevel'
|
||||
import SINGLE_CALL_BALANCES_ABI from 'single-call-balance-checker-abi'
|
||||
import { MAINNET } from './network/enums'
|
||||
|
||||
// By default, poll every 3 minutes
|
||||
const DEFAULT_INTERVAL = 180 * 1000
|
||||
import SINGLE_CALL_BALANCES_ABI from 'single-call-balance-checker-abi'
|
||||
|
||||
const SINGLE_CALL_BALANCES_ADDRESS = '0xb1f8e55c7f64d203c1400b9d8555d050f94adf39'
|
||||
|
||||
/**
|
||||
* A controller that polls for token exchange
|
||||
* rates based on a user's current token list
|
||||
*/
|
||||
export default class DetectTokensController {
|
||||
|
||||
/**
|
||||
* Creates a DetectTokensController
|
||||
*
|
||||
|
@ -1,6 +1,6 @@
|
||||
import punycode from 'punycode'
|
||||
import ethUtil from 'ethereumjs-util'
|
||||
import ObservableStore from 'obs-store'
|
||||
import punycode from 'punycode'
|
||||
import log from 'loglevel'
|
||||
import Ens from './ens'
|
||||
|
||||
|
@ -40,7 +40,7 @@ export default class IncomingTransactionsController {
|
||||
})
|
||||
}
|
||||
|
||||
const initState = Object.assign({
|
||||
const initState = {
|
||||
incomingTransactions: {},
|
||||
incomingTxLastFetchedBlocksByNetwork: {
|
||||
[ROPSTEN]: null,
|
||||
@ -48,8 +48,8 @@ export default class IncomingTransactionsController {
|
||||
[KOVAN]: null,
|
||||
[GOERLI]: null,
|
||||
[MAINNET]: null,
|
||||
},
|
||||
}, opts.initState)
|
||||
}, ...opts.initState,
|
||||
}
|
||||
this.store = new ObservableStore(initState)
|
||||
|
||||
this.preferencesController.store.subscribe(pairwise((prevState, currState) => {
|
||||
@ -265,9 +265,8 @@ function pairwise (fn) {
|
||||
if (first) {
|
||||
first = false
|
||||
return fn(value, value)
|
||||
} else {
|
||||
return fn(cache, value)
|
||||
}
|
||||
return fn(cache, value)
|
||||
} finally {
|
||||
cache = value
|
||||
}
|
||||
|
@ -26,7 +26,6 @@ function delay (time) {
|
||||
return new Promise((resolve) => setTimeout(resolve, time))
|
||||
}
|
||||
|
||||
|
||||
function createEstimateGasMiddleware () {
|
||||
return createAsyncMiddleware(async (req, _, next) => {
|
||||
if (req.method === 'eth_estimateGas' && inTest) {
|
||||
|
@ -1,15 +1,17 @@
|
||||
import { formatTxMetaForRpcResult } from '../util'
|
||||
import createAsyncMiddleware from 'json-rpc-engine/src/createAsyncMiddleware'
|
||||
import { formatTxMetaForRpcResult } from '../util'
|
||||
|
||||
export function createPendingNonceMiddleware ({ getPendingNonce }) {
|
||||
return createAsyncMiddleware(async (req, res, next) => {
|
||||
const { method, params } = req
|
||||
if (method !== 'eth_getTransactionCount') {
|
||||
return next()
|
||||
next()
|
||||
return
|
||||
}
|
||||
const [param, blockRef] = params
|
||||
if (blockRef !== 'pending') {
|
||||
return next()
|
||||
next()
|
||||
return
|
||||
}
|
||||
res.result = await getPendingNonce(param)
|
||||
})
|
||||
@ -19,12 +21,14 @@ export function createPendingTxMiddleware ({ getPendingTransactionByHash }) {
|
||||
return createAsyncMiddleware(async (req, res, next) => {
|
||||
const { method, params } = req
|
||||
if (method !== 'eth_getTransactionByHash') {
|
||||
return next()
|
||||
next()
|
||||
return
|
||||
}
|
||||
const [hash] = params
|
||||
const txMeta = getPendingTransactionByHash(hash)
|
||||
if (!txMeta) {
|
||||
return next()
|
||||
next()
|
||||
return
|
||||
}
|
||||
res.result = formatTxMetaForRpcResult(txMeta)
|
||||
})
|
||||
|
@ -6,13 +6,11 @@ import EthQuery from 'eth-query'
|
||||
import JsonRpcEngine from 'json-rpc-engine'
|
||||
import providerFromEngine from 'eth-json-rpc-middleware/providerFromEngine'
|
||||
import log from 'loglevel'
|
||||
import { createSwappableProxy, createEventEmitterProxy } from 'swappable-obj-proxy'
|
||||
import createMetamaskMiddleware from './createMetamaskMiddleware'
|
||||
import createInfuraClient from './createInfuraClient'
|
||||
import createJsonRpcClient from './createJsonRpcClient'
|
||||
import createLocalhostClient from './createLocalhostClient'
|
||||
import { createSwappableProxy, createEventEmitterProxy } from 'swappable-obj-proxy'
|
||||
|
||||
const networks = { networkList: {} }
|
||||
|
||||
import {
|
||||
RINKEBY,
|
||||
@ -21,8 +19,10 @@ import {
|
||||
INFURA_PROVIDER_TYPES,
|
||||
} from './enums'
|
||||
|
||||
const networks = { networkList: {} }
|
||||
|
||||
const env = process.env.METAMASK_ENV
|
||||
const METAMASK_DEBUG = process.env.METAMASK_DEBUG
|
||||
const { METAMASK_DEBUG } = process.env
|
||||
|
||||
let defaultProviderConfigType
|
||||
if (process.env.IN_TEST === 'true') {
|
||||
@ -93,15 +93,15 @@ export default class NetworkController extends EventEmitter {
|
||||
|
||||
setNetworkState (network, type) {
|
||||
if (network === 'loading') {
|
||||
return this.networkStore.putState(network)
|
||||
this.networkStore.putState(network)
|
||||
return
|
||||
}
|
||||
|
||||
// type must be defined
|
||||
if (!type) {
|
||||
return
|
||||
}
|
||||
network = networks.networkList[type]?.chainId || network
|
||||
return this.networkStore.putState(network)
|
||||
this.networkStore.putState(networks.networkList[type]?.chainId || network)
|
||||
}
|
||||
|
||||
isNetworkLoading () {
|
||||
@ -111,7 +111,8 @@ export default class NetworkController extends EventEmitter {
|
||||
lookupNetwork () {
|
||||
// Prevent firing when provider is not defined.
|
||||
if (!this._provider) {
|
||||
return log.warn('NetworkController - lookupNetwork aborted due to missing provider')
|
||||
log.warn('NetworkController - lookupNetwork aborted due to missing provider')
|
||||
return
|
||||
}
|
||||
const { type } = this.providerStore.getState()
|
||||
const ethQuery = new EthQuery(this._provider)
|
||||
@ -120,9 +121,10 @@ export default class NetworkController extends EventEmitter {
|
||||
const currentNetwork = this.getNetworkState()
|
||||
if (initialNetwork === currentNetwork) {
|
||||
if (err) {
|
||||
return this.setNetworkState('loading')
|
||||
this.setNetworkState('loading')
|
||||
return
|
||||
}
|
||||
log.info('web3.getNetwork returned ' + network)
|
||||
log.info(`web3.getNetwork returned ${network}`)
|
||||
this.setNetworkState(network, type)
|
||||
}
|
||||
})
|
||||
@ -210,7 +212,7 @@ export default class NetworkController extends EventEmitter {
|
||||
log.info('NetworkController - configureStandardProvider', rpcUrl)
|
||||
const networkClient = createJsonRpcClient({ rpcUrl })
|
||||
// hack to add a 'rpc' network with chainId
|
||||
networks.networkList['rpc'] = {
|
||||
networks.networkList.rpc = {
|
||||
chainId,
|
||||
rpcUrl,
|
||||
ticker: ticker || 'ETH',
|
||||
@ -220,7 +222,7 @@ export default class NetworkController extends EventEmitter {
|
||||
let settings = {
|
||||
network: chainId,
|
||||
}
|
||||
settings = Object.assign(settings, networks.networkList['rpc'])
|
||||
settings = Object.assign(settings, networks.networkList.rpc)
|
||||
this.networkConfig.putState(settings)
|
||||
this._setNetworkClient(networkClient)
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ import log from 'loglevel'
|
||||
* state related to onboarding
|
||||
*/
|
||||
export default class OnboardingController {
|
||||
|
||||
/**
|
||||
* Creates a new controller instance
|
||||
*
|
||||
@ -26,13 +27,11 @@ export default class OnboardingController {
|
||||
const initialTransientState = {
|
||||
onboardingTabs: {},
|
||||
}
|
||||
const initState = Object.assign(
|
||||
{
|
||||
seedPhraseBackedUp: true,
|
||||
},
|
||||
opts.initState,
|
||||
initialTransientState,
|
||||
)
|
||||
const initState = {
|
||||
seedPhraseBackedUp: true,
|
||||
...opts.initState,
|
||||
...initialTransientState,
|
||||
}
|
||||
this.store = new ObservableStore(initState)
|
||||
this.preferencesController = opts.preferencesController
|
||||
this.completedOnboarding = this.preferencesController.store.getState().completedOnboarding
|
||||
@ -64,7 +63,7 @@ export default class OnboardingController {
|
||||
log.debug('Ignoring registerOnboarding; user already onboarded')
|
||||
return
|
||||
}
|
||||
const onboardingTabs = Object.assign({}, this.store.getState().onboardingTabs)
|
||||
const onboardingTabs = { ...this.store.getState().onboardingTabs }
|
||||
if (!onboardingTabs[location] || onboardingTabs[location] !== tabId) {
|
||||
log.debug(`Registering onboarding tab at location '${location}' with tabId '${tabId}'`)
|
||||
onboardingTabs[location] = tabId
|
||||
|
@ -36,7 +36,8 @@ export class PermissionsController {
|
||||
showPermissionRequest,
|
||||
} = {},
|
||||
restoredPermissions = {},
|
||||
restoredState = {}) {
|
||||
restoredState = {},
|
||||
) {
|
||||
|
||||
// additional top-level store key set in _initializeMetadataStore
|
||||
this.store = new ObservableStore({
|
||||
@ -132,7 +133,7 @@ export class PermissionsController {
|
||||
const req = { method: 'eth_accounts' }
|
||||
const res = {}
|
||||
this.permissions.providerMiddlewareFunction(
|
||||
{ origin }, req, res, () => {}, _end,
|
||||
{ origin }, req, res, () => undefined, _end,
|
||||
)
|
||||
|
||||
function _end () {
|
||||
@ -187,7 +188,7 @@ export class PermissionsController {
|
||||
const res = {}
|
||||
|
||||
this.permissions.providerMiddlewareFunction(
|
||||
domain, req, res, () => {}, _end,
|
||||
domain, req, res, () => undefined, _end,
|
||||
)
|
||||
|
||||
function _end (_err) {
|
||||
@ -334,7 +335,7 @@ export class PermissionsController {
|
||||
.filter((acc) => acc !== account)
|
||||
|
||||
if (newPermittedAccounts.length === 0) {
|
||||
this.removePermissionsFor({ [origin]: [ 'eth_accounts' ] })
|
||||
this.removePermissionsFor({ [origin]: ['eth_accounts'] })
|
||||
} else {
|
||||
|
||||
this.permissions.updateCaveatFor(
|
||||
|
@ -113,10 +113,11 @@ export default class PermissionsLogController {
|
||||
// eth_requestAccounts is a special case; we need to extract the accounts
|
||||
// from it
|
||||
activityEntry = this.logRequest(req, isInternal)
|
||||
requestedMethods = [ 'eth_accounts' ]
|
||||
requestedMethods = ['eth_accounts']
|
||||
} else {
|
||||
// no-op
|
||||
return next()
|
||||
next()
|
||||
return
|
||||
}
|
||||
|
||||
// call next with a return handler for capturing the response
|
||||
@ -291,9 +292,9 @@ export default class PermissionsLogController {
|
||||
// eth_accounts requires special handling, because of information
|
||||
// we store about the accounts
|
||||
const existingEthAccountsEntry = (
|
||||
history[origin] && history[origin]['eth_accounts']
|
||||
history[origin] && history[origin].eth_accounts
|
||||
)
|
||||
const newEthAccountsEntry = newEntries['eth_accounts']
|
||||
const newEthAccountsEntry = newEntries.eth_accounts
|
||||
|
||||
if (existingEthAccountsEntry && newEthAccountsEntry) {
|
||||
|
||||
@ -305,7 +306,7 @@ export default class PermissionsLogController {
|
||||
)
|
||||
|
||||
// merge old and new eth_accounts history entries
|
||||
newOriginHistory['eth_accounts'] = {
|
||||
newOriginHistory.eth_accounts = {
|
||||
lastApproved,
|
||||
accounts: {
|
||||
...existingEthAccountsEntry.accounts,
|
||||
@ -363,7 +364,7 @@ export default class PermissionsLogController {
|
||||
}
|
||||
}
|
||||
}
|
||||
return [ ...accounts ]
|
||||
return [...accounts]
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,12 +24,13 @@ export default function createPermissionsMethodMiddleware ({
|
||||
// Intercepting eth_accounts requests for backwards compatibility:
|
||||
// The getAccounts call below wraps the rpc-cap middleware, and returns
|
||||
// an empty array in case of errors (such as 4100:unauthorized)
|
||||
case 'eth_accounts':
|
||||
case 'eth_accounts': {
|
||||
|
||||
res.result = await getAccounts()
|
||||
return
|
||||
}
|
||||
|
||||
case 'eth_requestAccounts':
|
||||
case 'eth_requestAccounts': {
|
||||
|
||||
if (isProcessingRequestAccounts) {
|
||||
res.error = ethErrors.rpc.resourceUnavailable(
|
||||
@ -73,19 +74,21 @@ export default function createPermissionsMethodMiddleware ({
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// custom method for getting metadata from the requesting domain,
|
||||
// sent automatically by the inpage provider when it's initialized
|
||||
case 'wallet_sendDomainMetadata':
|
||||
case 'wallet_sendDomainMetadata': {
|
||||
|
||||
if (typeof req.domainMetadata?.name === 'string') {
|
||||
addDomainMetadata(req.origin, req.domainMetadata)
|
||||
}
|
||||
res.result = true
|
||||
return
|
||||
}
|
||||
|
||||
// register return handler to send accountsChanged notification
|
||||
case 'wallet_requestPermissions':
|
||||
case 'wallet_requestPermissions': {
|
||||
|
||||
if ('eth_accounts' in req.params?.[0]) {
|
||||
|
||||
@ -101,6 +104,7 @@ export default function createPermissionsMethodMiddleware ({
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
default:
|
||||
break
|
||||
|
@ -1,7 +1,7 @@
|
||||
import ObservableStore from 'obs-store'
|
||||
import { addInternalMethodPrefix } from './permissions'
|
||||
import { normalize as normalizeAddress } from 'eth-sig-util'
|
||||
import { isValidAddress, sha3, bufferToHex } from 'ethereumjs-util'
|
||||
import { addInternalMethodPrefix } from './permissions'
|
||||
|
||||
export default class PreferencesController {
|
||||
|
||||
@ -26,7 +26,7 @@ export default class PreferencesController {
|
||||
*
|
||||
*/
|
||||
constructor (opts = {}) {
|
||||
const initState = Object.assign({
|
||||
const initState = {
|
||||
frequentRpcListDetail: [],
|
||||
accountTokens: {},
|
||||
assetImages: {},
|
||||
@ -61,8 +61,8 @@ export default class PreferencesController {
|
||||
metaMetricsSendCount: 0,
|
||||
|
||||
// ENS decentralized website resolution
|
||||
ipfsGateway: 'dweb.link',
|
||||
}, opts.initState)
|
||||
ipfsGateway: 'dweb.link', ...opts.initState,
|
||||
}
|
||||
|
||||
this.diagnostics = opts.diagnostics
|
||||
this.network = opts.network
|
||||
@ -152,7 +152,6 @@ export default class PreferencesController {
|
||||
this.store.updateState({ firstTimeFlowType: type })
|
||||
}
|
||||
|
||||
|
||||
getSuggestedTokens () {
|
||||
return this.store.getState().suggestedTokens
|
||||
}
|
||||
@ -178,7 +177,7 @@ export default class PreferencesController {
|
||||
* @param {string} methodData - Corresponding data method
|
||||
*/
|
||||
addKnownMethodData (fourBytePrefix, methodData) {
|
||||
const knownMethodData = this.store.getState().knownMethodData
|
||||
const { knownMethodData } = this.store.getState()
|
||||
knownMethodData[fourBytePrefix] = methodData
|
||||
this.store.updateState({ knownMethodData })
|
||||
}
|
||||
@ -198,7 +197,7 @@ export default class PreferencesController {
|
||||
) {
|
||||
const { type, options } = req.params
|
||||
switch (type) {
|
||||
case 'ERC20':
|
||||
case 'ERC20': {
|
||||
const result = await this._handleWatchAssetERC20(options)
|
||||
if (result instanceof Error) {
|
||||
end(result)
|
||||
@ -207,6 +206,7 @@ export default class PreferencesController {
|
||||
end()
|
||||
}
|
||||
return
|
||||
}
|
||||
default:
|
||||
end(new Error(`Asset of type ${type} not supported`))
|
||||
return
|
||||
@ -214,7 +214,6 @@ export default class PreferencesController {
|
||||
}
|
||||
|
||||
next()
|
||||
return
|
||||
}
|
||||
|
||||
/**
|
||||
@ -227,7 +226,7 @@ export default class PreferencesController {
|
||||
const textDirection = (['ar', 'dv', 'fa', 'he', 'ku'].includes(key)) ? 'rtl' : 'auto'
|
||||
this.store.updateState({
|
||||
currentLocale: key,
|
||||
textDirection: textDirection,
|
||||
textDirection,
|
||||
})
|
||||
return textDirection
|
||||
}
|
||||
@ -263,8 +262,8 @@ export default class PreferencesController {
|
||||
* @returns {string} - the address that was removed
|
||||
*/
|
||||
removeAddress (address) {
|
||||
const identities = this.store.getState().identities
|
||||
const accountTokens = this.store.getState().accountTokens
|
||||
const { identities } = this.store.getState()
|
||||
const { accountTokens } = this.store.getState()
|
||||
if (!identities[address]) {
|
||||
throw new Error(`${address} can't be deleted cause it was not found`)
|
||||
}
|
||||
@ -281,7 +280,6 @@ export default class PreferencesController {
|
||||
return address
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds addresses to the identities object without removing identities
|
||||
*
|
||||
@ -289,8 +287,7 @@ export default class PreferencesController {
|
||||
*
|
||||
*/
|
||||
addAddresses (addresses) {
|
||||
const identities = this.store.getState().identities
|
||||
const accountTokens = this.store.getState().accountTokens
|
||||
const { identities, accountTokens } = this.store.getState()
|
||||
addresses.forEach((address) => {
|
||||
// skip if already exists
|
||||
if (identities[address]) {
|
||||
@ -419,7 +416,7 @@ export default class PreferencesController {
|
||||
async addToken (rawAddress, symbol, decimals, image) {
|
||||
const address = normalizeAddress(rawAddress)
|
||||
const newEntry = { address, symbol, decimals }
|
||||
const tokens = this.store.getState().tokens
|
||||
const { tokens } = this.store.getState()
|
||||
const assetImages = this.getAssetImages()
|
||||
const previousEntry = tokens.find((token) => {
|
||||
return token.address === address
|
||||
@ -444,7 +441,7 @@ export default class PreferencesController {
|
||||
*
|
||||
*/
|
||||
removeToken (rawAddress) {
|
||||
const tokens = this.store.getState().tokens
|
||||
const { tokens } = this.store.getState()
|
||||
const assetImages = this.getAssetImages()
|
||||
const updatedTokens = tokens.filter((token) => token.address !== rawAddress)
|
||||
delete assetImages[rawAddress]
|
||||
@ -470,7 +467,7 @@ export default class PreferencesController {
|
||||
*/
|
||||
setAccountLabel (account, label) {
|
||||
if (!account) {
|
||||
throw new Error('setAccountLabel requires a valid address, got ' + String(account))
|
||||
throw new Error(`setAccountLabel requires a valid address, got ${String(account)}`)
|
||||
}
|
||||
const address = normalizeAddress(account)
|
||||
const { identities } = this.store.getState()
|
||||
@ -491,7 +488,6 @@ export default class PreferencesController {
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
updateRpc (newRpcDetails) {
|
||||
const rpcList = this.getFrequentRpcListDetail()
|
||||
const index = rpcList.findIndex((element) => {
|
||||
@ -508,6 +504,7 @@ export default class PreferencesController {
|
||||
}
|
||||
return Promise.resolve(rpcList)
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds custom RPC url to state.
|
||||
*
|
||||
@ -528,7 +525,8 @@ export default class PreferencesController {
|
||||
}
|
||||
if (url !== 'http://localhost:8545') {
|
||||
let checkedChainId
|
||||
if (!!chainId && !Number.isNaN(parseInt(chainId))) {
|
||||
// eslint-disable-next-line radix
|
||||
if (Boolean(chainId) && !Number.isNaN(parseInt(chainId))) {
|
||||
checkedChainId = chainId
|
||||
}
|
||||
rpcList.push({ rpcUrl: url, chainId: checkedChainId, ticker, nickname, rpcPrefs })
|
||||
@ -686,8 +684,9 @@ export default class PreferencesController {
|
||||
*
|
||||
*/
|
||||
_getTokenRelatedStates (selectedAddress) {
|
||||
const accountTokens = this.store.getState().accountTokens
|
||||
const { accountTokens } = this.store.getState()
|
||||
if (!selectedAddress) {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
selectedAddress = this.store.getState().selectedAddress
|
||||
}
|
||||
const providerType = this.network.providerStore.getState().type
|
||||
|
@ -1,16 +1,19 @@
|
||||
import ObservableStore from 'obs-store'
|
||||
|
||||
/* eslint-disable import/first,import/order */
|
||||
const Box = process.env.IN_TEST
|
||||
? require('../../../development/mock-3box')
|
||||
: require('3box')
|
||||
/* eslint-enable import/order */
|
||||
|
||||
import log from 'loglevel'
|
||||
import migrations from '../migrations'
|
||||
import Migrator from '../lib/migrator'
|
||||
import JsonRpcEngine from 'json-rpc-engine'
|
||||
import providerFromEngine from 'eth-json-rpc-middleware/providerFromEngine'
|
||||
import createMetamaskMiddleware from './network/createMetamaskMiddleware'
|
||||
import Migrator from '../lib/migrator'
|
||||
import migrations from '../migrations'
|
||||
import createOriginMiddleware from '../lib/createOriginMiddleware'
|
||||
import createMetamaskMiddleware from './network/createMetamaskMiddleware'
|
||||
/* eslint-enable import/first */
|
||||
|
||||
const SYNC_TIMEOUT = 60 * 1000 // one minute
|
||||
|
||||
@ -33,16 +36,15 @@ export default class ThreeBoxController {
|
||||
if (origin !== '3Box') {
|
||||
return []
|
||||
}
|
||||
const isUnlocked = getKeyringControllerState().isUnlocked
|
||||
const { isUnlocked } = getKeyringControllerState()
|
||||
|
||||
const accounts = await this.keyringController.getAccounts()
|
||||
|
||||
if (isUnlocked && accounts[0]) {
|
||||
const appKeyAddress = await this.keyringController.getAppKeyAddress(accounts[0], 'wallet://3box.metamask.io')
|
||||
return [appKeyAddress]
|
||||
} else {
|
||||
return []
|
||||
}
|
||||
return []
|
||||
},
|
||||
processPersonalMessage: async (msgParams) => {
|
||||
const accounts = await this.keyringController.getAccounts()
|
||||
@ -123,7 +125,7 @@ export default class ThreeBoxController {
|
||||
const threeBoxConfig = await Box.getConfig(this.address)
|
||||
backupExists = threeBoxConfig.spaces && threeBoxConfig.spaces.metamask
|
||||
} catch (e) {
|
||||
if (e.message.match(/^Error: Invalid response \(404\)/)) {
|
||||
if (e.message.match(/^Error: Invalid response \(404\)/u)) {
|
||||
backupExists = false
|
||||
} else {
|
||||
throw e
|
||||
|
@ -3,7 +3,6 @@ import log from 'loglevel'
|
||||
import { normalize as normalizeAddress } from 'eth-sig-util'
|
||||
import ethUtil from 'ethereumjs-util'
|
||||
|
||||
|
||||
// By default, poll every 3 minutes
|
||||
const DEFAULT_INTERVAL = 180 * 1000
|
||||
|
||||
@ -12,6 +11,7 @@ const DEFAULT_INTERVAL = 180 * 1000
|
||||
* rates based on a user's current token list
|
||||
*/
|
||||
export default class TokenRatesController {
|
||||
|
||||
/**
|
||||
* Creates a TokenRatesController
|
||||
*
|
||||
|
@ -6,9 +6,8 @@ import EthQuery from 'ethjs-query'
|
||||
import { ethErrors } from 'eth-json-rpc-errors'
|
||||
import abi from 'human-standard-token-abi'
|
||||
import abiDecoder from 'abi-decoder'
|
||||
|
||||
abiDecoder.addABI(abi)
|
||||
|
||||
import NonceTracker from 'nonce-tracker'
|
||||
import log from 'loglevel'
|
||||
import {
|
||||
TOKEN_METHOD_APPROVE,
|
||||
TOKEN_METHOD_TRANSFER,
|
||||
@ -16,16 +15,14 @@ import {
|
||||
SEND_ETHER_ACTION_KEY,
|
||||
DEPLOY_CONTRACT_ACTION_KEY,
|
||||
CONTRACT_INTERACTION_KEY,
|
||||
} from '../../../../ui/app/helpers/constants/transactions.js'
|
||||
|
||||
} from '../../../../ui/app/helpers/constants/transactions'
|
||||
import cleanErrorStack from '../../lib/cleanErrorStack'
|
||||
import { hexToBn, bnToHex, BnMultiplyByFraction } from '../../lib/util'
|
||||
import { TRANSACTION_NO_CONTRACT_ERROR_KEY } from '../../../../ui/app/helpers/constants/error-keys'
|
||||
import TransactionStateManager from './tx-state-manager'
|
||||
import TxGasUtil from './tx-gas-utils'
|
||||
import PendingTransactionTracker from './pending-tx-tracker'
|
||||
import NonceTracker from 'nonce-tracker'
|
||||
import * as txUtils from './lib/util'
|
||||
import cleanErrorStack from '../../lib/cleanErrorStack'
|
||||
import log from 'loglevel'
|
||||
|
||||
import {
|
||||
TRANSACTION_TYPE_CANCEL,
|
||||
TRANSACTION_TYPE_RETRY,
|
||||
@ -33,8 +30,7 @@ import {
|
||||
TRANSACTION_STATUS_APPROVED,
|
||||
} from './enums'
|
||||
|
||||
import { hexToBn, bnToHex, BnMultiplyByFraction } from '../../lib/util'
|
||||
import { TRANSACTION_NO_CONTRACT_ERROR_KEY } from '../../../../ui/app/helpers/constants/error-keys'
|
||||
abiDecoder.addABI(abi)
|
||||
|
||||
const SIMPLE_GAS_COST = '0x5208' // Hex for 21000, cost of a simple send.
|
||||
const MAX_MEMSTORE_TX_LIST_SIZE = 100 // Number of transactions (by unique nonces) to keep in memory
|
||||
@ -53,7 +49,6 @@ const MAX_MEMSTORE_TX_LIST_SIZE = 100 // Number of transactions (by unique nonce
|
||||
<br>- nonceTracker
|
||||
calculating nonces
|
||||
|
||||
|
||||
@class
|
||||
@param {Object} - opts
|
||||
@param {Object} opts.initState - initial transaction list default is an empty array
|
||||
@ -133,12 +128,12 @@ export default class TransactionController extends EventEmitter {
|
||||
*/
|
||||
getChainId () {
|
||||
const networkState = this.networkStore.getState()
|
||||
// eslint-disable-next-line radix
|
||||
const integerChainId = parseInt(networkState)
|
||||
if (Number.isNaN(integerChainId)) {
|
||||
return 0
|
||||
} else {
|
||||
return integerChainId
|
||||
}
|
||||
return integerChainId
|
||||
}
|
||||
|
||||
/**
|
||||
@ -200,6 +195,7 @@ export default class TransactionController extends EventEmitter {
|
||||
const normalizedTxParams = txUtils.normalizeTxParams(txParams)
|
||||
|
||||
txUtils.validateTxParams(normalizedTxParams)
|
||||
|
||||
/**
|
||||
`generateTxMeta` adds the default txMeta properties to the passed object.
|
||||
These include the tx's `id`. As we use the id for determining order of
|
||||
@ -232,7 +228,7 @@ export default class TransactionController extends EventEmitter {
|
||||
}
|
||||
}
|
||||
|
||||
txMeta['origin'] = origin
|
||||
txMeta.origin = origin
|
||||
|
||||
const { transactionCategory, getCodeResponse } = await this._determineTransactionCategory(txParams)
|
||||
txMeta.transactionCategory = transactionCategory
|
||||
@ -271,6 +267,7 @@ export default class TransactionController extends EventEmitter {
|
||||
const defaultGasPrice = await this._getDefaultGasPrice(txMeta)
|
||||
const { gasLimit: defaultGasLimit, simulationFails } = await this._getDefaultGasLimit(txMeta, getCodeResponse)
|
||||
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
txMeta = this.txStateManager.getTx(txMeta.id)
|
||||
if (simulationFails) {
|
||||
txMeta.simulationFails = simulationFails
|
||||
@ -287,11 +284,11 @@ export default class TransactionController extends EventEmitter {
|
||||
/**
|
||||
* Gets default gas price, or returns `undefined` if gas price is already set
|
||||
* @param {Object} txMeta - The txMeta object
|
||||
* @returns {Promise<string>} The default gas price
|
||||
* @returns {Promise<string|undefined>} The default gas price
|
||||
*/
|
||||
async _getDefaultGasPrice (txMeta) {
|
||||
if (txMeta.txParams.gasPrice) {
|
||||
return
|
||||
return undefined
|
||||
}
|
||||
const gasPrice = await this.query.gasPrice()
|
||||
|
||||
@ -472,8 +469,8 @@ export default class TransactionController extends EventEmitter {
|
||||
// this is try-catch wrapped so that we can guarantee that the nonceLock is released
|
||||
try {
|
||||
this.txStateManager.setTxStatusFailed(txId, err)
|
||||
} catch (err) {
|
||||
log.error(err)
|
||||
} catch (err2) {
|
||||
log.error(err2)
|
||||
}
|
||||
// must set transaction to submitted/failed before releasing lock
|
||||
if (nonceLock) {
|
||||
@ -495,7 +492,7 @@ export default class TransactionController extends EventEmitter {
|
||||
const txMeta = this.txStateManager.getTx(txId)
|
||||
// add network/chain id
|
||||
const chainId = this.getChainId()
|
||||
const txParams = Object.assign({}, txMeta.txParams, { chainId })
|
||||
const txParams = { ...txMeta.txParams, chainId }
|
||||
// sign tx
|
||||
const fromAddress = txParams.from
|
||||
const ethTx = new Transaction(txParams)
|
||||
@ -560,9 +557,9 @@ export default class TransactionController extends EventEmitter {
|
||||
|
||||
// It seems that sometimes the numerical values being returned from
|
||||
// this.query.getTransactionReceipt are BN instances and not strings.
|
||||
const gasUsed = typeof txReceipt.gasUsed !== 'string'
|
||||
? txReceipt.gasUsed.toString(16)
|
||||
: txReceipt.gasUsed
|
||||
const gasUsed = typeof txReceipt.gasUsed === 'string'
|
||||
? txReceipt.gasUsed
|
||||
: txReceipt.gasUsed.toString(16)
|
||||
|
||||
txMeta.txReceipt = {
|
||||
...txReceipt,
|
||||
@ -604,19 +601,25 @@ export default class TransactionController extends EventEmitter {
|
||||
//
|
||||
/** maps methods for convenience*/
|
||||
_mapMethods () {
|
||||
|
||||
/** @returns {Object} - the state in transaction controller */
|
||||
this.getState = () => this.memStore.getState()
|
||||
|
||||
/** @returns {string|number} - the network number stored in networkStore */
|
||||
this.getNetwork = () => this.networkStore.getState()
|
||||
|
||||
/** @returns {string} - the user selected address */
|
||||
this.getSelectedAddress = () => this.preferencesStore.getState().selectedAddress
|
||||
|
||||
/** @returns {array} - transactions whos status is unapproved */
|
||||
this.getUnapprovedTxCount = () => Object.keys(this.txStateManager.getUnapprovedTxList()).length
|
||||
|
||||
/**
|
||||
@returns {number} - number of transactions that have the status submitted
|
||||
@param {string} account - hex prefixed account
|
||||
*/
|
||||
this.getPendingTxCount = (account) => this.txStateManager.getPendingTransactions(account).length
|
||||
|
||||
/** see txStateManager */
|
||||
this.getFilteredTxList = (opts) => this.txStateManager.getFilteredTxList(opts)
|
||||
}
|
||||
@ -684,7 +687,7 @@ export default class TransactionController extends EventEmitter {
|
||||
if (!('retryCount' in txMeta)) {
|
||||
txMeta.retryCount = 0
|
||||
}
|
||||
txMeta.retryCount++
|
||||
txMeta.retryCount += 1
|
||||
this.txStateManager.updateTx(txMeta, 'transactions/pending-tx-tracker#event: tx:retry')
|
||||
})
|
||||
}
|
||||
@ -700,7 +703,7 @@ export default class TransactionController extends EventEmitter {
|
||||
TOKEN_METHOD_APPROVE,
|
||||
TOKEN_METHOD_TRANSFER,
|
||||
TOKEN_METHOD_TRANSFER_FROM,
|
||||
].find((tokenMethodName) => tokenMethodName === name && name.toLowerCase())
|
||||
].find((methodName) => methodName === name && name.toLowerCase())
|
||||
|
||||
let result
|
||||
if (txParams.data && tokenMethodName) {
|
||||
@ -754,8 +757,7 @@ export default class TransactionController extends EventEmitter {
|
||||
_setupBlockTrackerListener () {
|
||||
let listenersAreActive = false
|
||||
const latestBlockHandler = this._onLatestBlock.bind(this)
|
||||
const blockTracker = this.blockTracker
|
||||
const txStateManager = this.txStateManager
|
||||
const { blockTracker, txStateManager } = this
|
||||
|
||||
txStateManager.on('tx:status-update', updateSubscription)
|
||||
updateSubscription()
|
||||
|
@ -15,11 +15,11 @@ import EthQuery from 'ethjs-query'
|
||||
@param {function} config.getPendingTransactions a function for getting an array of transactions,
|
||||
@param {function} config.publishTransaction a async function for publishing raw transactions,
|
||||
|
||||
|
||||
@class
|
||||
*/
|
||||
|
||||
export default class PendingTransactionTracker extends EventEmitter {
|
||||
|
||||
/**
|
||||
* We wait this many blocks before emitting a 'tx:dropped' event
|
||||
*
|
||||
@ -129,7 +129,7 @@ export default class PendingTransactionTracker extends EventEmitter {
|
||||
|
||||
// Exponential backoff to limit retries at publishing
|
||||
if (txBlockDistance <= Math.pow(2, retryCount) - 1) {
|
||||
return
|
||||
return undefined
|
||||
}
|
||||
|
||||
// Only auto-submit already-signed txs:
|
||||
@ -137,7 +137,7 @@ export default class PendingTransactionTracker extends EventEmitter {
|
||||
return this.approveTransaction(txMeta.id)
|
||||
}
|
||||
|
||||
const rawTx = txMeta.rawTx
|
||||
const { rawTx } = txMeta
|
||||
const txHash = await this.publishTransaction(rawTx)
|
||||
|
||||
// Increment successful tries:
|
||||
@ -196,7 +196,6 @@ export default class PendingTransactionTracker extends EventEmitter {
|
||||
|
||||
if (await this._checkIfTxWasDropped(txMeta)) {
|
||||
this.emit('tx:dropped', txId)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
@ -239,11 +238,11 @@ export default class PendingTransactionTracker extends EventEmitter {
|
||||
async _checkIfNonceIsTaken (txMeta) {
|
||||
const address = txMeta.txParams.from
|
||||
const completed = this.getCompletedTransactions(address)
|
||||
return completed.some((other) =>
|
||||
return completed.some(
|
||||
// This is called while the transaction is in-flight, so it is possible that the
|
||||
// list of completed transactions now includes the transaction we were looking at
|
||||
// and if that is the case, don't consider the transaction to have taken its own nonce
|
||||
!(other.id === txMeta.id) && other.txParams.nonce === txMeta.txParams.nonce,
|
||||
(other) => !(other.id === txMeta.id) && other.txParams.nonce === txMeta.txParams.nonce,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import EthQuery from 'ethjs-query'
|
||||
import { hexToBn, BnMultiplyByFraction, bnToHex } from '../../lib/util'
|
||||
import log from 'loglevel'
|
||||
import { hexToBn, BnMultiplyByFraction, bnToHex } from '../../lib/util'
|
||||
|
||||
/**
|
||||
* Result of gas analysis, including either a gas estimate for a successful analysis, or
|
||||
@ -56,7 +56,7 @@ export default class TxGasUtil {
|
||||
@returns {string} - the estimated gas limit as a hex string
|
||||
*/
|
||||
async estimateTxGas (txMeta) {
|
||||
const txParams = txMeta.txParams
|
||||
const { txParams } = txMeta
|
||||
|
||||
// estimate tx gas requirements
|
||||
return await this.query.estimateGas(txParams)
|
||||
|
@ -1,9 +1,10 @@
|
||||
import EventEmitter from 'safe-event-emitter'
|
||||
import ObservableStore from 'obs-store'
|
||||
import log from 'loglevel'
|
||||
import { generateHistoryEntry, replayHistory, snapshotFromTxMeta } from './lib/tx-state-history-helpers'
|
||||
import createId from '../../lib/random-id'
|
||||
import { generateHistoryEntry, replayHistory, snapshotFromTxMeta } from './lib/tx-state-history-helpers'
|
||||
import { getFinalStates, normalizeTxParams } from './lib/util'
|
||||
|
||||
/**
|
||||
TransactionStateManager is responsible for the state of a transaction and
|
||||
storing the transaction
|
||||
@ -31,9 +32,8 @@ export default class TransactionStateManager extends EventEmitter {
|
||||
super()
|
||||
|
||||
this.store = new ObservableStore(
|
||||
Object.assign({
|
||||
transactions: [],
|
||||
}, initState))
|
||||
{ transactions: [], ...initState },
|
||||
)
|
||||
this.txHistoryLimit = txHistoryLimit
|
||||
this.getNetwork = getNetwork
|
||||
}
|
||||
@ -47,13 +47,13 @@ export default class TransactionStateManager extends EventEmitter {
|
||||
if (netId === 'loading') {
|
||||
throw new Error('MetaMask is having trouble connecting to the network')
|
||||
}
|
||||
return Object.assign({
|
||||
return {
|
||||
id: createId(),
|
||||
time: (new Date()).getTime(),
|
||||
status: 'unapproved',
|
||||
metamaskNetworkId: netId,
|
||||
loadingDefaults: true,
|
||||
}, opts)
|
||||
loadingDefaults: true, ...opts,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -164,10 +164,10 @@ export default class TransactionStateManager extends EventEmitter {
|
||||
txMeta.txParams = this.normalizeAndValidateTxParams(txMeta.txParams)
|
||||
}
|
||||
|
||||
this.once(`${txMeta.id}:signed`, function () {
|
||||
this.once(`${txMeta.id}:signed`, () => {
|
||||
this.removeAllListeners(`${txMeta.id}:rejected`)
|
||||
})
|
||||
this.once(`${txMeta.id}:rejected`, function () {
|
||||
this.once(`${txMeta.id}:rejected`, () => {
|
||||
this.removeAllListeners(`${txMeta.id}:signed`)
|
||||
})
|
||||
// initialize history
|
||||
@ -178,7 +178,7 @@ export default class TransactionStateManager extends EventEmitter {
|
||||
|
||||
const transactions = this.getFullTxList()
|
||||
const txCount = transactions.length
|
||||
const txHistoryLimit = this.txHistoryLimit
|
||||
const { txHistoryLimit } = this
|
||||
|
||||
// checks if the length of the tx history is
|
||||
// longer then desired persistence limit
|
||||
@ -202,6 +202,7 @@ export default class TransactionStateManager extends EventEmitter {
|
||||
this._saveTxList(transactions)
|
||||
return txMeta
|
||||
}
|
||||
|
||||
/**
|
||||
@param {number} txId
|
||||
@returns {Object} - the txMeta who matches the given id if none found
|
||||
@ -241,7 +242,6 @@ export default class TransactionStateManager extends EventEmitter {
|
||||
this._saveTxList(txList)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
merges txParams obj onto txMeta.txParams
|
||||
use extend to ensure that all fields are filled
|
||||
@ -262,6 +262,7 @@ export default class TransactionStateManager extends EventEmitter {
|
||||
if (typeof txParams.data === 'undefined') {
|
||||
delete txParams.data
|
||||
}
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
txParams = normalizeTxParams(txParams, false)
|
||||
this.validateTxParams(txParams)
|
||||
return txParams
|
||||
@ -325,6 +326,7 @@ export default class TransactionStateManager extends EventEmitter {
|
||||
})
|
||||
return filteredTxList
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@param {string} key - the key to check
|
||||
@ -339,9 +341,8 @@ export default class TransactionStateManager extends EventEmitter {
|
||||
return txList.filter((txMeta) => {
|
||||
if (key in txMeta.txParams) {
|
||||
return filter(txMeta.txParams[key])
|
||||
} else {
|
||||
return filter(txMeta[key])
|
||||
}
|
||||
return filter(txMeta[key])
|
||||
})
|
||||
}
|
||||
|
||||
@ -372,6 +373,7 @@ export default class TransactionStateManager extends EventEmitter {
|
||||
setTxStatusUnapproved (txId) {
|
||||
this._setTxStatus(txId, 'unapproved')
|
||||
}
|
||||
|
||||
/**
|
||||
should update the status of the tx to 'approved'.
|
||||
@param {number} txId - the txMeta Id
|
||||
@ -416,7 +418,6 @@ export default class TransactionStateManager extends EventEmitter {
|
||||
this._setTxStatus(txId, 'dropped')
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
should update the status of the tx to 'failed'.
|
||||
and put the error on the txMeta
|
||||
@ -424,7 +425,7 @@ export default class TransactionStateManager extends EventEmitter {
|
||||
@param {erroObject} err - error object
|
||||
*/
|
||||
setTxStatusFailed (txId, err) {
|
||||
const error = !err ? new Error('Internal metamask failure') : err
|
||||
const error = err || new Error('Internal metamask failure')
|
||||
|
||||
const txMeta = this.getTx(txId)
|
||||
txMeta.err = {
|
||||
|
@ -30,12 +30,14 @@ const restoreContextAfterImports = () => {
|
||||
|
||||
cleanContextForImports()
|
||||
|
||||
/* eslint-disable import/first */
|
||||
import log from 'loglevel'
|
||||
import LocalMessageDuplexStream from 'post-message-stream'
|
||||
import { initProvider } from '@metamask/inpage-provider'
|
||||
|
||||
// TODO:deprecate:2020
|
||||
import setupWeb3 from './lib/setupWeb3.js'
|
||||
import setupWeb3 from './lib/setupWeb3'
|
||||
/* eslint-enable import/first */
|
||||
|
||||
restoreContextAfterImports()
|
||||
|
||||
@ -58,7 +60,6 @@ initProvider({
|
||||
// TODO:deprecate:2020
|
||||
// Setup web3
|
||||
|
||||
|
||||
if (typeof window.web3 !== 'undefined') {
|
||||
throw new Error(`MetaMask detected another web3.
|
||||
MetaMask will not work reliably with another web3 extension.
|
||||
|
@ -5,6 +5,7 @@ import ObservableStore from 'obs-store'
|
||||
* structure of child stores based on configuration
|
||||
*/
|
||||
export default class ComposableObservableStore extends ObservableStore {
|
||||
|
||||
/**
|
||||
* Create a new store
|
||||
*
|
||||
@ -25,7 +26,7 @@ export default class ComposableObservableStore extends ObservableStore {
|
||||
this.config = config
|
||||
this.removeAllListeners()
|
||||
for (const key in config) {
|
||||
if (config.hasOwnProperty(key)) {
|
||||
if (Object.prototype.hasOwnProperty.call(config, key)) {
|
||||
config[key].subscribe((state) => {
|
||||
this.updateState({ [key]: state })
|
||||
})
|
||||
@ -42,7 +43,7 @@ export default class ComposableObservableStore extends ObservableStore {
|
||||
getFlatState () {
|
||||
let flatState = {}
|
||||
for (const key in this.config) {
|
||||
if (this.config.hasOwnProperty(key)) {
|
||||
if (Object.prototype.hasOwnProperty.call(this.config, key)) {
|
||||
const controller = this.config[key]
|
||||
const state = controller.getState ? controller.getState() : controller.state
|
||||
flatState = { ...flatState, ...state }
|
||||
|
@ -14,7 +14,6 @@ import log from 'loglevel'
|
||||
import pify from 'pify'
|
||||
import Web3 from 'web3'
|
||||
import SINGLE_CALL_BALANCES_ABI from 'single-call-balance-checker-abi'
|
||||
import { bnToHex } from './util'
|
||||
import { MAINNET_NETWORK_ID, RINKEBY_NETWORK_ID, ROPSTEN_NETWORK_ID, KOVAN_NETWORK_ID } from '../controllers/network/enums'
|
||||
|
||||
import {
|
||||
@ -23,6 +22,7 @@ import {
|
||||
SINGLE_CALL_BALANCES_ADDRESS_ROPSTEN,
|
||||
SINGLE_CALL_BALANCES_ADDRESS_KOVAN,
|
||||
} from '../controllers/network/contract-addresses'
|
||||
import { bnToHex } from './util'
|
||||
|
||||
export default class AccountTracker {
|
||||
|
||||
@ -92,7 +92,7 @@ export default class AccountTracker {
|
||||
*
|
||||
*/
|
||||
syncWithAddresses (addresses) {
|
||||
const accounts = this.store.getState().accounts
|
||||
const { accounts } = this.store.getState()
|
||||
const locals = Object.keys(accounts)
|
||||
|
||||
const accountsToAdd = []
|
||||
@ -121,7 +121,7 @@ export default class AccountTracker {
|
||||
*
|
||||
*/
|
||||
addAccounts (addresses) {
|
||||
const accounts = this.store.getState().accounts
|
||||
const { accounts } = this.store.getState()
|
||||
// add initial state for addresses
|
||||
addresses.forEach((address) => {
|
||||
accounts[address] = {}
|
||||
@ -142,7 +142,7 @@ export default class AccountTracker {
|
||||
*
|
||||
*/
|
||||
removeAccount (addresses) {
|
||||
const accounts = this.store.getState().accounts
|
||||
const { accounts } = this.store.getState()
|
||||
// remove each state object
|
||||
addresses.forEach((address) => {
|
||||
delete accounts[address]
|
||||
@ -194,7 +194,7 @@ export default class AccountTracker {
|
||||
*
|
||||
*/
|
||||
async _updateAccounts () {
|
||||
const accounts = this.store.getState().accounts
|
||||
const { accounts } = this.store.getState()
|
||||
const addresses = Object.keys(accounts)
|
||||
const currentNetwork = this.network.getNetworkState()
|
||||
|
||||
@ -248,7 +248,7 @@ export default class AccountTracker {
|
||||
* @param {*} deployedContractAddress
|
||||
*/
|
||||
async _updateAccountsViaBalanceChecker (addresses, deployedContractAddress) {
|
||||
const accounts = this.store.getState().accounts
|
||||
const { accounts } = this.store.getState()
|
||||
this.web3.setProvider(this._provider)
|
||||
const ethContract = this.web3.eth.contract(SINGLE_CALL_BALANCES_ABI).at(deployedContractAddress)
|
||||
const ethBalance = ['0x0']
|
||||
@ -256,7 +256,8 @@ export default class AccountTracker {
|
||||
ethContract.balances(addresses, ethBalance, (error, result) => {
|
||||
if (error) {
|
||||
log.warn(`MetaMask - Account Tracker single call balance fetch failed`, error)
|
||||
return Promise.all(addresses.map(this._updateAccount.bind(this)))
|
||||
Promise.all(addresses.map(this._updateAccount.bind(this)))
|
||||
return
|
||||
}
|
||||
addresses.forEach((address, index) => {
|
||||
const balance = bnToHex(result[index])
|
||||
|
@ -2,9 +2,6 @@ import { getBackgroundMetaMetricState } from '../../../ui/app/selectors'
|
||||
import { sendMetaMetricsEvent } from '../../../ui/app/helpers/utils/metametrics.util'
|
||||
|
||||
export default function backgroundMetaMetricsEvent (metaMaskState, version, eventData) {
|
||||
|
||||
eventData.eventOpts['category'] = 'Background'
|
||||
|
||||
const stateEventData = getBackgroundMetaMetricState({ metamask: metaMaskState })
|
||||
if (stateEventData.participateInMetaMetrics) {
|
||||
sendMetaMetricsEvent({
|
||||
|
@ -11,6 +11,7 @@
|
||||
export default function getBuyEthUrl ({ network, address, service }) {
|
||||
// default service by network if not specified
|
||||
if (!service) {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
service = getDefaultServiceForNetwork(network)
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
* @returns {Error} - Error with clean stack trace.
|
||||
*/
|
||||
export default function cleanErrorStack (err) {
|
||||
let name = err.name
|
||||
let { name } = err
|
||||
name = (name === undefined) ? 'Error' : String(name)
|
||||
|
||||
let msg = err.message
|
||||
@ -15,7 +15,7 @@ export default function cleanErrorStack (err) {
|
||||
} else if (msg === '') {
|
||||
err.stack = err.name
|
||||
} else {
|
||||
err.stack = err.name + ': ' + err.message
|
||||
err.stack = `${err.name}: ${err.message}`
|
||||
}
|
||||
|
||||
return err
|
||||
|
@ -14,7 +14,7 @@ export default function createMethodMiddleware ({ origin, sendMetrics }) {
|
||||
return function methodMiddleware (req, res, next, end) {
|
||||
switch (req.method) {
|
||||
|
||||
case 'metamask_logInjectedWeb3Usage':
|
||||
case 'metamask_logInjectedWeb3Usage': {
|
||||
|
||||
const { action, name } = req.params[0]
|
||||
|
||||
@ -32,6 +32,7 @@ export default function createMethodMiddleware ({ origin, sendMetrics }) {
|
||||
|
||||
res.result = true
|
||||
break
|
||||
}
|
||||
|
||||
default:
|
||||
return next()
|
||||
|
@ -4,7 +4,7 @@ import promiseToCallback from 'promise-to-callback'
|
||||
class AsyncWritableStream extends WritableStream {
|
||||
|
||||
constructor (asyncWriteFn, _opts) {
|
||||
const opts = Object.assign({ objectMode: true }, _opts)
|
||||
const opts = { objectMode: true, ..._opts }
|
||||
super(opts)
|
||||
this._asyncWriteFn = asyncWriteFn
|
||||
}
|
||||
|
@ -2,11 +2,11 @@ import EventEmitter from 'events'
|
||||
import ObservableStore from 'obs-store'
|
||||
import ethUtil from 'ethereumjs-util'
|
||||
import { ethErrors } from 'eth-json-rpc-errors'
|
||||
import log from 'loglevel'
|
||||
import createId from './random-id'
|
||||
import { MESSAGE_TYPE } from './enums'
|
||||
|
||||
const hexRe = /^[0-9A-Fa-f]+$/g
|
||||
import log from 'loglevel'
|
||||
const hexRe = /^[0-9A-Fa-f]+$/ug
|
||||
|
||||
/**
|
||||
* Represents, and contains data about, an 'eth_decrypt' type decryption request. These are created when a
|
||||
@ -26,6 +26,7 @@ import log from 'loglevel'
|
||||
*/
|
||||
|
||||
export default class DecryptMessageManager extends EventEmitter {
|
||||
|
||||
/**
|
||||
* Controller in charge of managing - storing, adding, removing, updating - DecryptMessage.
|
||||
*
|
||||
@ -65,7 +66,8 @@ export default class DecryptMessageManager extends EventEmitter {
|
||||
getUnapprovedMsgs () {
|
||||
return this.messages.filter((msg) => msg.status === 'unapproved')
|
||||
.reduce((result, msg) => {
|
||||
result[msg.id] = msg; return result
|
||||
result[msg.id] = msg
|
||||
return result
|
||||
}, {})
|
||||
}
|
||||
|
||||
@ -82,19 +84,23 @@ export default class DecryptMessageManager extends EventEmitter {
|
||||
addUnapprovedMessageAsync (msgParams, req) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!msgParams.from) {
|
||||
return reject(new Error('MetaMask Decryption: from field is required.'))
|
||||
reject(new Error('MetaMask Decryption: from field is required.'))
|
||||
return
|
||||
}
|
||||
const msgId = this.addUnapprovedMessage(msgParams, req)
|
||||
this.once(`${msgId}:finished`, (data) => {
|
||||
switch (data.status) {
|
||||
case 'decrypted':
|
||||
return resolve(data.rawData)
|
||||
resolve(data.rawData)
|
||||
return
|
||||
case 'rejected':
|
||||
return reject(ethErrors.provider.userRejectedRequest('MetaMask Decryption: User denied message decryption.'))
|
||||
reject(ethErrors.provider.userRejectedRequest('MetaMask Decryption: User denied message decryption.'))
|
||||
return
|
||||
case 'errored':
|
||||
return reject(new Error('This message cannot be decrypted'))
|
||||
reject(new Error('This message cannot be decrypted'))
|
||||
return
|
||||
default:
|
||||
return reject(new Error(`MetaMask Decryption: Unknown problem: ${JSON.stringify(msgParams)}`))
|
||||
reject(new Error(`MetaMask Decryption: Unknown problem: ${JSON.stringify(msgParams)}`))
|
||||
}
|
||||
})
|
||||
})
|
||||
@ -122,8 +128,8 @@ export default class DecryptMessageManager extends EventEmitter {
|
||||
const msgId = createId()
|
||||
const msgData = {
|
||||
id: msgId,
|
||||
msgParams: msgParams,
|
||||
time: time,
|
||||
msgParams,
|
||||
time,
|
||||
status: 'unapproved',
|
||||
type: MESSAGE_TYPE.ETH_DECRYPT,
|
||||
}
|
||||
@ -248,7 +254,7 @@ export default class DecryptMessageManager extends EventEmitter {
|
||||
_setMsgStatus (msgId, status) {
|
||||
const msg = this.getMsg(msgId)
|
||||
if (!msg) {
|
||||
throw new Error('DecryptMessageManager - Message not found for id: "${msgId}".')
|
||||
throw new Error(`DecryptMessageManager - Message not found for id: "${msgId}".`)
|
||||
}
|
||||
msg.status = status
|
||||
this._updateMsg(msg)
|
||||
|
@ -1,8 +1,8 @@
|
||||
import EventEmitter from 'events'
|
||||
import ObservableStore from 'obs-store'
|
||||
import { ethErrors } from 'eth-json-rpc-errors'
|
||||
import createId from './random-id'
|
||||
import log from 'loglevel'
|
||||
import createId from './random-id'
|
||||
import { MESSAGE_TYPE } from './enums'
|
||||
|
||||
/**
|
||||
@ -23,6 +23,7 @@ import { MESSAGE_TYPE } from './enums'
|
||||
*/
|
||||
|
||||
export default class EncryptionPublicKeyManager extends EventEmitter {
|
||||
|
||||
/**
|
||||
* Controller in charge of managing - storing, adding, removing, updating - EncryptionPublicKey.
|
||||
*
|
||||
@ -62,7 +63,8 @@ export default class EncryptionPublicKeyManager extends EventEmitter {
|
||||
getUnapprovedMsgs () {
|
||||
return this.messages.filter((msg) => msg.status === 'unapproved')
|
||||
.reduce((result, msg) => {
|
||||
result[msg.id] = msg; return result
|
||||
result[msg.id] = msg
|
||||
return result
|
||||
}, {})
|
||||
}
|
||||
|
||||
@ -79,17 +81,20 @@ export default class EncryptionPublicKeyManager extends EventEmitter {
|
||||
addUnapprovedMessageAsync (address, req) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!address) {
|
||||
return reject(new Error('MetaMask Message: address field is required.'))
|
||||
reject(new Error('MetaMask Message: address field is required.'))
|
||||
return
|
||||
}
|
||||
const msgId = this.addUnapprovedMessage(address, req)
|
||||
this.once(`${msgId}:finished`, (data) => {
|
||||
switch (data.status) {
|
||||
case 'received':
|
||||
return resolve(data.rawData)
|
||||
resolve(data.rawData)
|
||||
return
|
||||
case 'rejected':
|
||||
return reject(ethErrors.provider.userRejectedRequest('MetaMask EncryptionPublicKey: User denied message EncryptionPublicKey.'))
|
||||
reject(ethErrors.provider.userRejectedRequest('MetaMask EncryptionPublicKey: User denied message EncryptionPublicKey.'))
|
||||
return
|
||||
default:
|
||||
return reject(new Error(`MetaMask EncryptionPublicKey: Unknown problem: ${JSON.stringify(address)}`))
|
||||
reject(new Error(`MetaMask EncryptionPublicKey: Unknown problem: ${JSON.stringify(address)}`))
|
||||
}
|
||||
})
|
||||
})
|
||||
@ -113,7 +118,7 @@ export default class EncryptionPublicKeyManager extends EventEmitter {
|
||||
const msgData = {
|
||||
id: msgId,
|
||||
msgParams: address,
|
||||
time: time,
|
||||
time,
|
||||
status: 'unapproved',
|
||||
type: MESSAGE_TYPE.ETH_GET_ENCRYPTION_PUBLIC_KEY,
|
||||
}
|
||||
@ -243,7 +248,7 @@ export default class EncryptionPublicKeyManager extends EventEmitter {
|
||||
_setMsgStatus (msgId, status) {
|
||||
const msg = this.getMsg(msgId)
|
||||
if (!msg) {
|
||||
throw new Error('EncryptionPublicKeyManager - Message not found for id: "${msgId}".')
|
||||
throw new Error(`EncryptionPublicKeyManager - Message not found for id: "${msgId}".`)
|
||||
}
|
||||
msg.status = status
|
||||
this._updateMsg(msg)
|
||||
|
@ -1,9 +1,9 @@
|
||||
import namehash from 'eth-ens-namehash'
|
||||
import Eth from 'ethjs-query'
|
||||
import EthContract from 'ethjs-contract'
|
||||
import contentHash from 'content-hash'
|
||||
import registryAbi from './contracts/registry'
|
||||
import resolverAbi from './contracts/resolver'
|
||||
import contentHash from 'content-hash'
|
||||
|
||||
export default async function resolveEnsToIpfsContentId ({ provider, name }) {
|
||||
const eth = new Eth(provider)
|
||||
@ -36,7 +36,7 @@ export default async function resolveEnsToIpfsContentId ({ provider, name }) {
|
||||
decodedContentHash = contentHash.helpers.cidV0ToV1Base32(decodedContentHash)
|
||||
}
|
||||
|
||||
return { type: type, hash: decodedContentHash }
|
||||
return { type, hash: decodedContentHash }
|
||||
}
|
||||
if (isLegacyResolver[0]) {
|
||||
// lookup content id
|
||||
|
@ -1,6 +1,6 @@
|
||||
import urlUtil from 'url'
|
||||
import extension from 'extensionizer'
|
||||
import resolveEnsToIpfsContentId from './resolver.js'
|
||||
import resolveEnsToIpfsContentId from './resolver'
|
||||
|
||||
const supportedTopLevelDomains = ['eth']
|
||||
|
||||
|
@ -19,7 +19,6 @@ export default function extractEthjsErrorMessage (errorMessage) {
|
||||
const payloadAndError = errorMessage.slice(ethJsRpcSlug.length)
|
||||
const originalError = payloadAndError.slice(payloadAndError.indexOf(errorLabelPrefix) + errorLabelPrefix.length)
|
||||
return originalError
|
||||
} else {
|
||||
return errorMessage
|
||||
}
|
||||
return errorMessage
|
||||
}
|
||||
|
@ -30,11 +30,11 @@ function freeze (target, key, value, enumerable = true) {
|
||||
configurable: false, writable: false,
|
||||
}
|
||||
|
||||
if (value !== undefined) {
|
||||
if (value === undefined) {
|
||||
target[key] = deepFreeze(target[key])
|
||||
} else {
|
||||
opts.value = deepFreeze(value)
|
||||
opts.enumerable = enumerable
|
||||
} else {
|
||||
target[key] = deepFreeze(target[key])
|
||||
}
|
||||
|
||||
Object.defineProperty(target, key, opts)
|
||||
|
@ -40,7 +40,7 @@ export default async function getFirstPreferredLangCode () {
|
||||
|
||||
const firstPreferredLangCode = userPreferredLocaleCodes
|
||||
.map((code) => code.toLowerCase().replace('_', '-'))
|
||||
.find((code) => existingLocaleCodes.hasOwnProperty(code))
|
||||
.find((code) => Object.prototype.hasOwnProperty.call(existingLocaleCodes, code))
|
||||
|
||||
return existingLocaleCodes[firstPreferredLangCode] || 'en'
|
||||
}
|
||||
|
@ -6,11 +6,12 @@ import { checkForError } from './util'
|
||||
* A wrapper around the extension's storage local API
|
||||
*/
|
||||
export default class ExtensionStore {
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
constructor () {
|
||||
this.isSupported = !!(extension.storage.local)
|
||||
this.isSupported = Boolean(extension.storage.local)
|
||||
if (!this.isSupported) {
|
||||
log.error('Storage local API not available.')
|
||||
}
|
||||
@ -29,9 +30,8 @@ export default class ExtensionStore {
|
||||
// if the object is empty, treat it as undefined
|
||||
if (isEmpty(result)) {
|
||||
return undefined
|
||||
} else {
|
||||
return result
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
@ -49,7 +49,7 @@ export default class ExtensionStore {
|
||||
* @returns {Object} - the key-value map from local storage
|
||||
*/
|
||||
_get () {
|
||||
const local = extension.storage.local
|
||||
const { local } = extension.storage
|
||||
return new Promise((resolve, reject) => {
|
||||
local.get(null, (/** @type {any} */ result) => {
|
||||
const err = checkForError()
|
||||
@ -69,7 +69,7 @@ export default class ExtensionStore {
|
||||
* @private
|
||||
*/
|
||||
_set (obj) {
|
||||
const local = extension.storage.local
|
||||
const { local } = extension.storage
|
||||
return new Promise((resolve, reject) => {
|
||||
local.set(obj, () => {
|
||||
const err = checkForError()
|
||||
|
@ -64,7 +64,8 @@ export default class MessageManager extends EventEmitter {
|
||||
getUnapprovedMsgs () {
|
||||
return this.messages.filter((msg) => msg.status === 'unapproved')
|
||||
.reduce((result, msg) => {
|
||||
result[msg.id] = msg; return result
|
||||
result[msg.id] = msg
|
||||
return result
|
||||
}, {})
|
||||
}
|
||||
|
||||
@ -114,8 +115,8 @@ export default class MessageManager extends EventEmitter {
|
||||
const msgId = createId()
|
||||
const msgData = {
|
||||
id: msgId,
|
||||
msgParams: msgParams,
|
||||
time: time,
|
||||
msgParams,
|
||||
time,
|
||||
status: 'unapproved',
|
||||
type: MESSAGE_TYPE.ETH_SIGN,
|
||||
}
|
||||
@ -225,7 +226,7 @@ export default class MessageManager extends EventEmitter {
|
||||
_setMsgStatus (msgId, status) {
|
||||
const msg = this.getMsg(msgId)
|
||||
if (!msg) {
|
||||
throw new Error('MessageManager - Message not found for id: "${msgId}".')
|
||||
throw new Error(`MessageManager - Message not found for id: "${msgId}".`)
|
||||
}
|
||||
msg.status = status
|
||||
this._updateMsg(msg)
|
||||
@ -278,8 +279,7 @@ function normalizeMsgData (data) {
|
||||
if (data.slice(0, 2) === '0x') {
|
||||
// data is already hex
|
||||
return data
|
||||
} else {
|
||||
// data is unicode, convert to hex
|
||||
return ethUtil.bufferToHex(Buffer.from(data, 'utf8'))
|
||||
}
|
||||
// data is unicode, convert to hex
|
||||
return ethUtil.bufferToHex(Buffer.from(data, 'utf8'))
|
||||
}
|
||||
|
@ -46,6 +46,7 @@ export default class Migrator extends EventEmitter {
|
||||
throw new Error('Migrator - Migration did not update version number correctly')
|
||||
}
|
||||
// accept the migration as good
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
versionedData = migratedData
|
||||
} catch (err) {
|
||||
// rewrite error message to add context without clobbering stack
|
||||
|
@ -15,9 +15,7 @@ const callbackNoop = function (err) {
|
||||
*
|
||||
*/
|
||||
export default function nodeify (fn, context) {
|
||||
return function () {
|
||||
// parse arguments
|
||||
const args = [].slice.call(arguments)
|
||||
return function (...args) {
|
||||
const lastArg = args[args.length - 1]
|
||||
const lastArgIsCallback = typeof lastArg === 'function'
|
||||
let callback
|
||||
|
@ -2,11 +2,11 @@ import EventEmitter from 'events'
|
||||
import ObservableStore from 'obs-store'
|
||||
import ethUtil from 'ethereumjs-util'
|
||||
import { ethErrors } from 'eth-json-rpc-errors'
|
||||
import log from 'loglevel'
|
||||
import createId from './random-id'
|
||||
import { MESSAGE_TYPE } from './enums'
|
||||
|
||||
const hexRe = /^[0-9A-Fa-f]+$/g
|
||||
import log from 'loglevel'
|
||||
const hexRe = /^[0-9A-Fa-f]+$/ug
|
||||
|
||||
/**
|
||||
* Represents, and contains data about, an 'personal_sign' type signature request. These are created when a
|
||||
@ -28,6 +28,7 @@ import log from 'loglevel'
|
||||
*/
|
||||
|
||||
export default class PersonalMessageManager extends EventEmitter {
|
||||
|
||||
/**
|
||||
* Controller in charge of managing - storing, adding, removing, updating - PersonalMessage.
|
||||
*
|
||||
@ -68,7 +69,8 @@ export default class PersonalMessageManager extends EventEmitter {
|
||||
getUnapprovedMsgs () {
|
||||
return this.messages.filter((msg) => msg.status === 'unapproved')
|
||||
.reduce((result, msg) => {
|
||||
result[msg.id] = msg; return result
|
||||
result[msg.id] = msg
|
||||
return result
|
||||
}, {})
|
||||
}
|
||||
|
||||
@ -85,17 +87,20 @@ export default class PersonalMessageManager extends EventEmitter {
|
||||
addUnapprovedMessageAsync (msgParams, req) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!msgParams.from) {
|
||||
return reject(new Error('MetaMask Message Signature: from field is required.'))
|
||||
reject(new Error('MetaMask Message Signature: from field is required.'))
|
||||
return
|
||||
}
|
||||
const msgId = this.addUnapprovedMessage(msgParams, req)
|
||||
this.once(`${msgId}:finished`, (data) => {
|
||||
switch (data.status) {
|
||||
case 'signed':
|
||||
return resolve(data.rawSig)
|
||||
resolve(data.rawSig)
|
||||
return
|
||||
case 'rejected':
|
||||
return reject(ethErrors.provider.userRejectedRequest('MetaMask Message Signature: User denied message signature.'))
|
||||
reject(ethErrors.provider.userRejectedRequest('MetaMask Message Signature: User denied message signature.'))
|
||||
return
|
||||
default:
|
||||
return reject(new Error(`MetaMask Message Signature: Unknown problem: ${JSON.stringify(msgParams)}`))
|
||||
reject(new Error(`MetaMask Message Signature: Unknown problem: ${JSON.stringify(msgParams)}`))
|
||||
}
|
||||
})
|
||||
})
|
||||
@ -123,8 +128,8 @@ export default class PersonalMessageManager extends EventEmitter {
|
||||
const msgId = createId()
|
||||
const msgData = {
|
||||
id: msgId,
|
||||
msgParams: msgParams,
|
||||
time: time,
|
||||
msgParams,
|
||||
time,
|
||||
status: 'unapproved',
|
||||
type: MESSAGE_TYPE.PERSONAL_SIGN,
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ const MAX = Number.MAX_SAFE_INTEGER
|
||||
|
||||
let idCounter = Math.round(Math.random() * MAX)
|
||||
export default function createRandomId () {
|
||||
idCounter = idCounter % MAX
|
||||
idCounter %= MAX
|
||||
// eslint-disable-next-line no-plusplus
|
||||
return idCounter++
|
||||
}
|
||||
|
@ -30,8 +30,8 @@ const seedPhraseVerifier = {
|
||||
|
||||
const keyring = new Keyring(opts)
|
||||
const restoredAccounts = await keyring.getAccounts()
|
||||
log.debug('Created accounts: ' + JSON.stringify(createdAccounts))
|
||||
log.debug('Restored accounts: ' + JSON.stringify(restoredAccounts))
|
||||
log.debug(`Created accounts: ${JSON.stringify(createdAccounts)}`)
|
||||
log.debug(`Restored accounts: ${JSON.stringify(restoredAccounts)}`)
|
||||
|
||||
if (restoredAccounts.length !== createdAccounts.length) {
|
||||
// this should not happen...
|
||||
@ -40,7 +40,7 @@ const seedPhraseVerifier = {
|
||||
|
||||
for (let i = 0; i < restoredAccounts.length; i++) {
|
||||
if (restoredAccounts[i].toLowerCase() !== createdAccounts[i].toLowerCase()) {
|
||||
throw new Error('Not identical accounts! Original: ' + createdAccounts[i] + ', Restored: ' + restoredAccounts[i])
|
||||
throw new Error(`Not identical accounts! Original: ${createdAccounts[i]}, Restored: ${restoredAccounts[i]}`)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -3,8 +3,7 @@ import { Dedupe, ExtraErrorData } from '@sentry/integrations'
|
||||
|
||||
import extractEthjsErrorMessage from './extractEthjsErrorMessage'
|
||||
|
||||
const METAMASK_DEBUG = process.env.METAMASK_DEBUG
|
||||
const METAMASK_ENVIRONMENT = process.env.METAMASK_ENVIRONMENT
|
||||
const { METAMASK_DEBUG, METAMASK_ENVIRONMENT } = process.env
|
||||
const SENTRY_DSN_DEV = 'https://f59f3dd640d2429d9d0e2445a87ea8e1@sentry.io/273496'
|
||||
|
||||
// This describes the subset of Redux state attached to errors sent to Sentry
|
||||
@ -72,7 +71,7 @@ export default function setupSentry ({ release, getState }) {
|
||||
let sentryTarget
|
||||
|
||||
if (METAMASK_DEBUG) {
|
||||
return
|
||||
return undefined
|
||||
} else if (METAMASK_ENVIRONMENT === 'production') {
|
||||
if (!process.env.SENTRY_DSN) {
|
||||
throw new Error(`Missing SENTRY_DSN environment variable in production environment`)
|
||||
@ -122,13 +121,13 @@ export default function setupSentry ({ release, getState }) {
|
||||
function simplifyErrorMessages (report) {
|
||||
rewriteErrorMessages(report, (errorMessage) => {
|
||||
// simplify ethjs error messages
|
||||
errorMessage = extractEthjsErrorMessage(errorMessage)
|
||||
let simplifiedErrorMessage = extractEthjsErrorMessage(errorMessage)
|
||||
// simplify 'Transaction Failed: known transaction'
|
||||
if (errorMessage.indexOf('Transaction Failed: known transaction') === 0) {
|
||||
if (simplifiedErrorMessage.indexOf('Transaction Failed: known transaction') === 0) {
|
||||
// cut the hash from the error message
|
||||
errorMessage = 'Transaction Failed: known transaction'
|
||||
simplifiedErrorMessage = 'Transaction Failed: known transaction'
|
||||
}
|
||||
return errorMessage
|
||||
return simplifiedErrorMessage
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
// TODO:deprecate:2020
|
||||
// Delete this file
|
||||
|
||||
import 'web3/dist/web3.min.js'
|
||||
import 'web3/dist/web3.min'
|
||||
|
||||
const shouldLogUsage = !([
|
||||
'docs.metamask.io',
|
||||
|
@ -1,12 +1,12 @@
|
||||
import EventEmitter from 'events'
|
||||
import ObservableStore from 'obs-store'
|
||||
import createId from './random-id'
|
||||
import assert from 'assert'
|
||||
import ObservableStore from 'obs-store'
|
||||
import { ethErrors } from 'eth-json-rpc-errors'
|
||||
import sigUtil from 'eth-sig-util'
|
||||
import { isValidAddress } from 'ethereumjs-util'
|
||||
import log from 'loglevel'
|
||||
import jsonschema from 'jsonschema'
|
||||
import createId from './random-id'
|
||||
import { MESSAGE_TYPE } from './enums'
|
||||
|
||||
/**
|
||||
@ -28,6 +28,7 @@ import { MESSAGE_TYPE } from './enums'
|
||||
*/
|
||||
|
||||
export default class TypedMessageManager extends EventEmitter {
|
||||
|
||||
/**
|
||||
* Controller in charge of managing - storing, adding, removing, updating - TypedMessage.
|
||||
*/
|
||||
@ -61,7 +62,8 @@ export default class TypedMessageManager extends EventEmitter {
|
||||
getUnapprovedMsgs () {
|
||||
return this.messages.filter((msg) => msg.status === 'unapproved')
|
||||
.reduce((result, msg) => {
|
||||
result[msg.id] = msg; return result
|
||||
result[msg.id] = msg
|
||||
return result
|
||||
}, {})
|
||||
}
|
||||
|
||||
@ -118,8 +120,8 @@ export default class TypedMessageManager extends EventEmitter {
|
||||
const msgId = createId()
|
||||
const msgData = {
|
||||
id: msgId,
|
||||
msgParams: msgParams,
|
||||
time: time,
|
||||
msgParams,
|
||||
time,
|
||||
status: 'unapproved',
|
||||
type: MESSAGE_TYPE.ETH_SIGN_TYPED_DATA,
|
||||
}
|
||||
@ -154,7 +156,7 @@ export default class TypedMessageManager extends EventEmitter {
|
||||
}, 'Signing data must be valid EIP-712 typed data.')
|
||||
break
|
||||
case 'V3':
|
||||
case 'V4':
|
||||
case 'V4': {
|
||||
assert.equal(typeof params.data, 'string', '"params.data" must be a string.')
|
||||
let data
|
||||
assert.doesNotThrow(() => {
|
||||
@ -163,10 +165,12 @@ export default class TypedMessageManager extends EventEmitter {
|
||||
const validation = jsonschema.validate(data, sigUtil.TYPED_MESSAGE_SCHEMA)
|
||||
assert.ok(data.primaryType in data.types, `Primary type of "${data.primaryType}" has no type definition.`)
|
||||
assert.equal(validation.errors.length, 0, 'Signing data must conform to EIP-712 schema. See https://git.io/fNtcx.')
|
||||
const chainId = data.domain.chainId
|
||||
const { chainId } = data.domain
|
||||
// eslint-disable-next-line radix
|
||||
const activeChainId = parseInt(this.networkController.getNetworkState())
|
||||
chainId && assert.equal(chainId, activeChainId, `Provided chainId "${chainId}" must match the active chainId "${activeChainId}"`)
|
||||
break
|
||||
}
|
||||
default:
|
||||
assert.fail(`Unknown typed data version "${params.version}"`)
|
||||
}
|
||||
@ -291,7 +295,7 @@ export default class TypedMessageManager extends EventEmitter {
|
||||
_setMsgStatus (msgId, status) {
|
||||
const msg = this.getMsg(msgId)
|
||||
if (!msg) {
|
||||
throw new Error('TypedMessageManager - Message not found for id: "${msgId}".')
|
||||
throw new Error(`TypedMessageManager - Message not found for id: "${msgId}".`)
|
||||
}
|
||||
msg.status = status
|
||||
this._updateMsg(msg)
|
||||
|
@ -1,6 +1,6 @@
|
||||
import assert from 'assert'
|
||||
import extension from 'extensionizer'
|
||||
import ethUtil from 'ethereumjs-util'
|
||||
import assert from 'assert'
|
||||
import BN from 'bn.js'
|
||||
import { memoize } from 'lodash'
|
||||
|
||||
@ -27,9 +27,8 @@ const getEnvironmentTypeMemo = memoize((url) => {
|
||||
return ENVIRONMENT_TYPE_FULLSCREEN
|
||||
} else if (parsedUrl.pathname === '/notification.html') {
|
||||
return ENVIRONMENT_TYPE_NOTIFICATION
|
||||
} else {
|
||||
return ENVIRONMENT_TYPE_BACKGROUND
|
||||
}
|
||||
return ENVIRONMENT_TYPE_BACKGROUND
|
||||
})
|
||||
|
||||
/**
|
||||
@ -55,19 +54,19 @@ const getEnvironmentType = (url = window.location.href) => getEnvironmentTypeMem
|
||||
*/
|
||||
const getPlatform = (_) => {
|
||||
const ua = window.navigator.userAgent
|
||||
if (ua.search('Firefox') !== -1) {
|
||||
return PLATFORM_FIREFOX
|
||||
} else {
|
||||
if (ua.search('Firefox') === -1) {
|
||||
if (window && window.chrome && window.chrome.ipcRenderer) {
|
||||
return PLATFORM_BRAVE
|
||||
} else if (ua.search('Edge') !== -1) {
|
||||
return PLATFORM_EDGE
|
||||
} else if (ua.search('OPR') !== -1) {
|
||||
return PLATFORM_OPERA
|
||||
} else {
|
||||
return PLATFORM_CHROME
|
||||
}
|
||||
if (ua.search('Edge') !== -1) {
|
||||
return PLATFORM_EDGE
|
||||
}
|
||||
if (ua.search('OPR') !== -1) {
|
||||
return PLATFORM_OPERA
|
||||
}
|
||||
return PLATFORM_CHROME
|
||||
}
|
||||
return PLATFORM_FIREFOX
|
||||
}
|
||||
|
||||
/**
|
||||
@ -135,12 +134,12 @@ function BnMultiplyByFraction (targetBN, numerator, denominator) {
|
||||
/**
|
||||
* Returns an Error if extension.runtime.lastError is present
|
||||
* this is a workaround for the non-standard error object that's used
|
||||
* @returns {Error}
|
||||
* @returns {Error|undefined}
|
||||
*/
|
||||
function checkForError () {
|
||||
const lastError = extension.runtime.lastError
|
||||
const { lastError } = extension.runtime
|
||||
if (!lastError) {
|
||||
return
|
||||
return undefined
|
||||
}
|
||||
// if it quacks like an Error, its an Error
|
||||
if (lastError.stack && lastError.message) {
|
||||
|
@ -10,22 +10,35 @@ import pump from 'pump'
|
||||
import Dnode from 'dnode'
|
||||
import extension from 'extensionizer'
|
||||
import ObservableStore from 'obs-store'
|
||||
import ComposableObservableStore from './lib/ComposableObservableStore'
|
||||
import asStream from 'obs-store/lib/asStream'
|
||||
import AccountTracker from './lib/account-tracker'
|
||||
import RpcEngine from 'json-rpc-engine'
|
||||
import { debounce } from 'lodash'
|
||||
import createEngineStream from 'json-rpc-middleware-stream/engineStream'
|
||||
import createFilterMiddleware from 'eth-json-rpc-filters'
|
||||
import createSubscriptionManager from 'eth-json-rpc-filters/subscriptionManager'
|
||||
import providerAsMiddleware from 'eth-json-rpc-middleware/providerAsMiddleware'
|
||||
import KeyringController from 'eth-keyring-controller'
|
||||
import { Mutex } from 'await-semaphore'
|
||||
import ethUtil from 'ethereumjs-util'
|
||||
import log from 'loglevel'
|
||||
import TrezorKeyring from 'eth-trezor-keyring'
|
||||
import LedgerBridgeKeyring from '@metamask/eth-ledger-bridge-keyring'
|
||||
import EthQuery from 'eth-query'
|
||||
import nanoid from 'nanoid'
|
||||
import contractMap from 'eth-contract-metadata'
|
||||
import {
|
||||
AddressBookController,
|
||||
CurrencyRateController,
|
||||
PhishingController,
|
||||
} from '@metamask/controllers'
|
||||
import ComposableObservableStore from './lib/ComposableObservableStore'
|
||||
import AccountTracker from './lib/account-tracker'
|
||||
import createLoggerMiddleware from './lib/createLoggerMiddleware'
|
||||
import createMethodMiddleware from './lib/createMethodMiddleware'
|
||||
import createOriginMiddleware from './lib/createOriginMiddleware'
|
||||
import createTabIdMiddleware from './lib/createTabIdMiddleware'
|
||||
import createOnboardingMiddleware from './lib/createOnboardingMiddleware'
|
||||
import providerAsMiddleware from 'eth-json-rpc-middleware/providerAsMiddleware'
|
||||
import { setupMultiplex } from './lib/stream-utils.js'
|
||||
import KeyringController from 'eth-keyring-controller'
|
||||
import { setupMultiplex } from './lib/stream-utils'
|
||||
import EnsController from './controllers/ens'
|
||||
import NetworkController from './controllers/network'
|
||||
import PreferencesController from './controllers/preferences'
|
||||
@ -47,25 +60,8 @@ import { PermissionsController } from './controllers/permissions'
|
||||
import getRestrictedMethods from './controllers/permissions/restrictedMethods'
|
||||
import nodeify from './lib/nodeify'
|
||||
import accountImporter from './account-import-strategies'
|
||||
import getBuyEthUrl from './lib/buy-eth-url'
|
||||
import selectChainId from './lib/select-chain-id'
|
||||
import { Mutex } from 'await-semaphore'
|
||||
import { version } from '../manifest/_base.json'
|
||||
import ethUtil from 'ethereumjs-util'
|
||||
|
||||
import seedPhraseVerifier from './lib/seed-phrase-verifier'
|
||||
import log from 'loglevel'
|
||||
import TrezorKeyring from 'eth-trezor-keyring'
|
||||
import LedgerBridgeKeyring from '@metamask/eth-ledger-bridge-keyring'
|
||||
import EthQuery from 'eth-query'
|
||||
import nanoid from 'nanoid'
|
||||
import contractMap from 'eth-contract-metadata'
|
||||
|
||||
import {
|
||||
AddressBookController,
|
||||
CurrencyRateController,
|
||||
PhishingController,
|
||||
} from '@metamask/controllers'
|
||||
|
||||
import backgroundMetaMetricsEvent from './lib/background-metametrics'
|
||||
|
||||
@ -82,6 +78,7 @@ export default class MetamaskController extends EventEmitter {
|
||||
|
||||
this.sendUpdate = debounce(this.privateSendUpdate.bind(this), 200)
|
||||
this.opts = opts
|
||||
this.platform = opts.platform
|
||||
const initState = opts.initState || {}
|
||||
this.recordFirstTimeInfo(initState)
|
||||
|
||||
@ -89,9 +86,6 @@ export default class MetamaskController extends EventEmitter {
|
||||
// the only thing that uses controller connections are open metamask UI instances
|
||||
this.activeControllerConnections = 0
|
||||
|
||||
// platform-specific api
|
||||
this.platform = opts.platform
|
||||
|
||||
this.getRequestAccountTabIds = opts.getRequestAccountTabIds
|
||||
this.getOpenMetamaskTabsIds = opts.getOpenMetamaskTabsIds
|
||||
|
||||
@ -222,6 +216,7 @@ export default class MetamaskController extends EventEmitter {
|
||||
preferencesStore: this.preferencesController.store,
|
||||
})
|
||||
|
||||
const version = this.platform.getVersion()
|
||||
this.threeBoxController = new ThreeBoxController({
|
||||
preferencesController: this.preferencesController,
|
||||
addressBookController: this.addressBookController,
|
||||
@ -278,7 +273,6 @@ export default class MetamaskController extends EventEmitter {
|
||||
this.encryptionPublicKeyManager = new EncryptionPublicKeyManager()
|
||||
this.typedMessageManager = new TypedMessageManager({ networkController: this.networkController })
|
||||
|
||||
|
||||
this.store.updateStructure({
|
||||
AppStateController: this.appStateController.store,
|
||||
TransactionController: this.txController.store,
|
||||
@ -336,6 +330,7 @@ export default class MetamaskController extends EventEmitter {
|
||||
* Constructor helper: initialize a provider.
|
||||
*/
|
||||
initializeProvider () {
|
||||
const version = this.platform.getVersion()
|
||||
const providerOpts = {
|
||||
static: {
|
||||
eth_syncing: false,
|
||||
@ -409,8 +404,8 @@ export default class MetamaskController extends EventEmitter {
|
||||
* @returns {Object} - status
|
||||
*/
|
||||
getState () {
|
||||
const vault = this.keyringController.store.getState().vault
|
||||
const isInitialized = !!vault
|
||||
const { vault } = this.keyringController.store.getState()
|
||||
const isInitialized = Boolean(vault)
|
||||
|
||||
return {
|
||||
...{ isInitialized },
|
||||
@ -426,14 +421,16 @@ export default class MetamaskController extends EventEmitter {
|
||||
* @returns {Object} - Object containing API functions.
|
||||
*/
|
||||
getApi () {
|
||||
const keyringController = this.keyringController
|
||||
const networkController = this.networkController
|
||||
const onboardingController = this.onboardingController
|
||||
const alertController = this.alertController
|
||||
const permissionsController = this.permissionsController
|
||||
const preferencesController = this.preferencesController
|
||||
const threeBoxController = this.threeBoxController
|
||||
const txController = this.txController
|
||||
const {
|
||||
keyringController,
|
||||
networkController,
|
||||
onboardingController,
|
||||
alertController,
|
||||
permissionsController,
|
||||
preferencesController,
|
||||
threeBoxController,
|
||||
txController,
|
||||
} = this
|
||||
|
||||
return {
|
||||
// etc
|
||||
@ -449,7 +446,6 @@ export default class MetamaskController extends EventEmitter {
|
||||
setCurrentLocale: this.setCurrentLocale.bind(this),
|
||||
markPasswordForgotten: this.markPasswordForgotten.bind(this),
|
||||
unMarkPasswordForgotten: this.unMarkPasswordForgotten.bind(this),
|
||||
buyEth: this.buyEth.bind(this),
|
||||
safelistPhishingDomain: this.safelistPhishingDomain.bind(this),
|
||||
getRequestAccountTabIds: (cb) => cb(null, this.getRequestAccountTabIds()),
|
||||
getOpenMetamaskTabsIds: (cb) => cb(null, this.getOpenMetamaskTabsIds()),
|
||||
@ -596,13 +592,11 @@ export default class MetamaskController extends EventEmitter {
|
||||
vault = await this.keyringController.fullUpdate()
|
||||
} else {
|
||||
vault = await this.keyringController.createNewVaultAndKeychain(password)
|
||||
const accounts = await this.keyringController.getAccounts()
|
||||
this.preferencesController.setAddresses(accounts)
|
||||
const addresses = await this.keyringController.getAccounts()
|
||||
this.preferencesController.setAddresses(addresses)
|
||||
this.selectFirstIdentity()
|
||||
}
|
||||
return vault
|
||||
} catch (err) {
|
||||
throw err
|
||||
} finally {
|
||||
releaseLock()
|
||||
}
|
||||
@ -618,7 +612,7 @@ export default class MetamaskController extends EventEmitter {
|
||||
try {
|
||||
let accounts, lastBalance
|
||||
|
||||
const keyringController = this.keyringController
|
||||
const { keyringController } = this
|
||||
|
||||
// clear known identities
|
||||
this.preferencesController.setAddresses([])
|
||||
@ -658,8 +652,6 @@ export default class MetamaskController extends EventEmitter {
|
||||
this.preferencesController.setAddresses(accounts)
|
||||
this.selectFirstIdentity()
|
||||
return vault
|
||||
} catch (err) {
|
||||
throw err
|
||||
} finally {
|
||||
releaseLock()
|
||||
}
|
||||
@ -714,15 +706,16 @@ export default class MetamaskController extends EventEmitter {
|
||||
Object.keys(accountTokens).forEach((address) => {
|
||||
const checksummedAddress = ethUtil.toChecksumAddress(address)
|
||||
filteredAccountTokens[checksummedAddress] = {}
|
||||
Object.keys(accountTokens[address]).forEach(
|
||||
(networkType) => (filteredAccountTokens[checksummedAddress][networkType] = networkType !== 'mainnet' ?
|
||||
accountTokens[address][networkType] :
|
||||
accountTokens[address][networkType].filter(({ address }) => {
|
||||
const tokenAddress = ethUtil.toChecksumAddress(address)
|
||||
return contractMap[tokenAddress] ? contractMap[tokenAddress].erc20 : true
|
||||
})
|
||||
),
|
||||
)
|
||||
Object.keys(accountTokens[address]).forEach((networkType) => {
|
||||
filteredAccountTokens[checksummedAddress][networkType] = networkType === 'mainnet'
|
||||
? (
|
||||
accountTokens[address][networkType].filter(({ address: tokenAddress }) => {
|
||||
const checksumAddress = ethUtil.toChecksumAddress(tokenAddress)
|
||||
return contractMap[checksumAddress] ? contractMap[checksumAddress].erc20 : true
|
||||
})
|
||||
)
|
||||
: accountTokens[address][networkType]
|
||||
})
|
||||
})
|
||||
|
||||
const preferences = {
|
||||
@ -751,7 +744,7 @@ export default class MetamaskController extends EventEmitter {
|
||||
|
||||
// transactions
|
||||
|
||||
let transactions = this.txController.store.getState().transactions
|
||||
let { transactions } = this.txController.store.getState()
|
||||
// delete tx for other accounts that we're not importing
|
||||
transactions = transactions.filter((tx) => {
|
||||
const checksummedTxFrom = ethUtil.toChecksumAddress(tx.txParams.from)
|
||||
@ -934,7 +927,6 @@ export default class MetamaskController extends EventEmitter {
|
||||
return { ...keyState, identities }
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Account Management
|
||||
//
|
||||
@ -949,7 +941,7 @@ export default class MetamaskController extends EventEmitter {
|
||||
if (!primaryKeyring) {
|
||||
throw new Error('MetamaskController - No HD Key Tree found')
|
||||
}
|
||||
const keyringController = this.keyringController
|
||||
const { keyringController } = this
|
||||
const oldAccounts = await keyringController.getAccounts()
|
||||
const keyState = await keyringController.addNewAccount(primaryKeyring)
|
||||
const newAccounts = await keyringController.getAccounts()
|
||||
@ -1034,7 +1026,6 @@ export default class MetamaskController extends EventEmitter {
|
||||
return address
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Imports an account with the specified import strategy.
|
||||
* These are defined in app/scripts/account-import-strategies
|
||||
@ -1046,7 +1037,7 @@ export default class MetamaskController extends EventEmitter {
|
||||
*/
|
||||
async importAccountWithStrategy (strategy, args) {
|
||||
const privateKey = await accountImporter.importAccount(strategy, args)
|
||||
const keyring = await this.keyringController.addNewKeyring('Simple Key Pair', [ privateKey ])
|
||||
const keyring = await this.keyringController.addNewKeyring('Simple Key Pair', [privateKey])
|
||||
const accounts = await keyring.getAccounts()
|
||||
// update accounts in preferences controller
|
||||
const allAccounts = await this.keyringController.getAccounts()
|
||||
@ -1119,12 +1110,12 @@ export default class MetamaskController extends EventEmitter {
|
||||
* @param {string} msgId - The id of the message to cancel.
|
||||
*/
|
||||
cancelMessage (msgId, cb) {
|
||||
const messageManager = this.messageManager
|
||||
const { messageManager } = this
|
||||
messageManager.rejectMsg(msgId)
|
||||
if (cb && typeof cb === 'function') {
|
||||
cb(null, this.getState())
|
||||
if (!cb || typeof cb !== 'function') {
|
||||
return
|
||||
}
|
||||
cb(null, this.getState())
|
||||
}
|
||||
|
||||
// personal_sign methods:
|
||||
@ -1180,10 +1171,10 @@ export default class MetamaskController extends EventEmitter {
|
||||
cancelPersonalMessage (msgId, cb) {
|
||||
const messageManager = this.personalMessageManager
|
||||
messageManager.rejectMsg(msgId)
|
||||
if (cb && typeof cb === 'function') {
|
||||
cb(null, this.getState())
|
||||
if (!cb || typeof cb !== 'function') {
|
||||
return
|
||||
}
|
||||
cb(null, this.getState())
|
||||
}
|
||||
|
||||
// eth_decrypt methods
|
||||
@ -1265,10 +1256,10 @@ export default class MetamaskController extends EventEmitter {
|
||||
cancelDecryptMessage (msgId, cb) {
|
||||
const messageManager = this.decryptMessageManager
|
||||
messageManager.rejectMsg(msgId)
|
||||
if (cb && typeof cb === 'function') {
|
||||
cb(null, this.getState())
|
||||
if (!cb || typeof cb !== 'function') {
|
||||
return
|
||||
}
|
||||
cb(null, this.getState())
|
||||
}
|
||||
|
||||
// eth_getEncryptionPublicKey methods
|
||||
@ -1323,10 +1314,10 @@ export default class MetamaskController extends EventEmitter {
|
||||
cancelEncryptionPublicKey (msgId, cb) {
|
||||
const messageManager = this.encryptionPublicKeyManager
|
||||
messageManager.rejectMsg(msgId)
|
||||
if (cb && typeof cb === 'function') {
|
||||
cb(null, this.getState())
|
||||
if (!cb || typeof cb !== 'function') {
|
||||
return
|
||||
}
|
||||
cb(null, this.getState())
|
||||
}
|
||||
|
||||
// eth_signTypedData methods
|
||||
@ -1349,12 +1340,12 @@ export default class MetamaskController extends EventEmitter {
|
||||
* Triggers the callback in newUnsignedTypedMessage.
|
||||
*
|
||||
* @param {Object} msgParams - The params passed to eth_signTypedData.
|
||||
* @returns {Object} - Full state update.
|
||||
* @returns {Object|undefined} - Full state update.
|
||||
*/
|
||||
async signTypedMessage (msgParams) {
|
||||
log.info('MetaMaskController - eth_signTypedData')
|
||||
const msgId = msgParams.metamaskId
|
||||
const version = msgParams.version
|
||||
const { version } = msgParams
|
||||
try {
|
||||
const cleanMsgParams = await this.typedMessageManager.approveMessage(msgParams)
|
||||
|
||||
@ -1372,6 +1363,7 @@ export default class MetamaskController extends EventEmitter {
|
||||
} catch (error) {
|
||||
log.info('MetaMaskController - eth_signTypedData failed.', error)
|
||||
this.typedMessageManager.errorMessage(msgId, error)
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
|
||||
@ -1383,10 +1375,10 @@ export default class MetamaskController extends EventEmitter {
|
||||
cancelTypedMessage (msgId, cb) {
|
||||
const messageManager = this.typedMessageManager
|
||||
messageManager.rejectMsg(msgId)
|
||||
if (cb && typeof cb === 'function') {
|
||||
cb(null, this.getState())
|
||||
if (!cb || typeof cb !== 'function') {
|
||||
return
|
||||
}
|
||||
cb(null, this.getState())
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
@ -1401,13 +1393,9 @@ export default class MetamaskController extends EventEmitter {
|
||||
* @returns {Object} - MetaMask state
|
||||
*/
|
||||
async createCancelTransaction (originalTxId, customGasPrice) {
|
||||
try {
|
||||
await this.txController.createCancelTransaction(originalTxId, customGasPrice)
|
||||
const state = await this.getState()
|
||||
return state
|
||||
} catch (error) {
|
||||
throw error
|
||||
}
|
||||
await this.txController.createCancelTransaction(originalTxId, customGasPrice)
|
||||
const state = await this.getState()
|
||||
return state
|
||||
}
|
||||
|
||||
async createSpeedUpTransaction (originalTxId, customGasPrice, customGasLimit) {
|
||||
@ -1470,7 +1458,7 @@ export default class MetamaskController extends EventEmitter {
|
||||
*/
|
||||
setupUntrustedCommunication (connectionStream, sender) {
|
||||
const { usePhishDetect } = this.preferencesController.store.getState()
|
||||
const hostname = (new URL(sender.url)).hostname
|
||||
const { hostname } = new URL(sender.url)
|
||||
// Check if new connection is blocked if phishing detection is on
|
||||
if (usePhishDetect && this.phishingController.test(hostname)) {
|
||||
log.debug('MetaMask - sending phishing warning for', hostname)
|
||||
@ -1526,7 +1514,7 @@ export default class MetamaskController extends EventEmitter {
|
||||
const api = this.getApi()
|
||||
const dnode = Dnode(api)
|
||||
// report new active controller connection
|
||||
this.activeControllerConnections++
|
||||
this.activeControllerConnections += 1
|
||||
this.emit('controllerConnectionChanged', this.activeControllerConnections)
|
||||
// connect dnode api to remote connection
|
||||
pump(
|
||||
@ -1535,7 +1523,7 @@ export default class MetamaskController extends EventEmitter {
|
||||
outStream,
|
||||
(err) => {
|
||||
// report new active controller connection
|
||||
this.activeControllerConnections--
|
||||
this.activeControllerConnections -= 1
|
||||
this.emit('controllerConnectionChanged', this.activeControllerConnections)
|
||||
// report any error
|
||||
if (err) {
|
||||
@ -1609,8 +1597,7 @@ export default class MetamaskController extends EventEmitter {
|
||||
setupProviderEngine ({ origin, location, extensionId, tabId, isInternal = false }) {
|
||||
// setup json rpc engine stack
|
||||
const engine = new RpcEngine()
|
||||
const provider = this.provider
|
||||
const blockTracker = this.blockTracker
|
||||
const { provider, blockTracker } = this
|
||||
|
||||
// create filter polyfill middleware
|
||||
const filterMiddleware = createFilterMiddleware({ provider, blockTracker })
|
||||
@ -1850,6 +1837,7 @@ export default class MetamaskController extends EventEmitter {
|
||||
customVariables,
|
||||
eventOpts: {
|
||||
action,
|
||||
category: 'Background',
|
||||
name,
|
||||
},
|
||||
},
|
||||
@ -1880,28 +1868,11 @@ export default class MetamaskController extends EventEmitter {
|
||||
return
|
||||
} catch (err) {
|
||||
cb(err)
|
||||
// eslint-disable-next-line no-useless-return
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A method for forwarding the user to the easiest way to obtain ether,
|
||||
* or the network "gas" currency, for the current selected network.
|
||||
*
|
||||
* @param {string} address - The address to fund.
|
||||
* @param {string} amount - The amount of ether desired, as a base 10 string.
|
||||
*/
|
||||
buyEth (address, amount) {
|
||||
if (!amount) {
|
||||
amount = '5'
|
||||
}
|
||||
const network = this.networkController.getNetworkState()
|
||||
const url = getBuyEthUrl({ network, address, amount })
|
||||
if (url) {
|
||||
this.platform.openTab({ url })
|
||||
}
|
||||
}
|
||||
|
||||
// network
|
||||
/**
|
||||
* A method for selecting a custom URL for an ethereum RPC provider and updating it
|
||||
@ -1918,7 +1889,6 @@ export default class MetamaskController extends EventEmitter {
|
||||
return rpcUrl
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A method for selecting a custom URL for an ethereum RPC provider.
|
||||
* @param {string} rpcTarget - A URL for a valid Ethereum RPC API.
|
||||
@ -1964,6 +1934,7 @@ export default class MetamaskController extends EventEmitter {
|
||||
return
|
||||
} catch (err) {
|
||||
cb(err)
|
||||
// eslint-disable-next-line no-useless-return
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -1980,6 +1951,7 @@ export default class MetamaskController extends EventEmitter {
|
||||
return
|
||||
} catch (err) {
|
||||
cb(err)
|
||||
// eslint-disable-next-line no-useless-return
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -1996,6 +1968,7 @@ export default class MetamaskController extends EventEmitter {
|
||||
return
|
||||
} catch (err) {
|
||||
cb(err)
|
||||
// eslint-disable-next-line no-useless-return
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -2012,6 +1985,7 @@ export default class MetamaskController extends EventEmitter {
|
||||
return
|
||||
} catch (err) {
|
||||
cb(err)
|
||||
// eslint-disable-next-line no-useless-return
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -2028,6 +2002,7 @@ export default class MetamaskController extends EventEmitter {
|
||||
return
|
||||
} catch (err) {
|
||||
cb(err)
|
||||
// eslint-disable-next-line no-useless-return
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -2039,6 +2014,7 @@ export default class MetamaskController extends EventEmitter {
|
||||
return
|
||||
} catch (err) {
|
||||
cb(err)
|
||||
// eslint-disable-next-line no-useless-return
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -2055,11 +2031,11 @@ export default class MetamaskController extends EventEmitter {
|
||||
return
|
||||
} catch (err) {
|
||||
cb(err)
|
||||
// eslint-disable-next-line no-useless-return
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A method for setting a user's current locale, affecting the language rendered.
|
||||
* @param {string} key - Locale identifier.
|
||||
@ -2072,6 +2048,7 @@ export default class MetamaskController extends EventEmitter {
|
||||
return
|
||||
} catch (err) {
|
||||
cb(err)
|
||||
// eslint-disable-next-line no-useless-return
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -2083,6 +2060,7 @@ export default class MetamaskController extends EventEmitter {
|
||||
*/
|
||||
recordFirstTimeInfo (initState) {
|
||||
if (!('firstTimeInfo' in initState)) {
|
||||
const version = this.platform.getVersion()
|
||||
initState.firstTimeInfo = {
|
||||
version,
|
||||
date: Date.now(),
|
||||
|
@ -1,12 +1,11 @@
|
||||
const version = 2
|
||||
|
||||
import { cloneDeep } from 'lodash'
|
||||
|
||||
const version = 2
|
||||
|
||||
export default {
|
||||
version,
|
||||
|
||||
migrate: function (originalVersionedData) {
|
||||
migrate (originalVersionedData) {
|
||||
const versionedData = cloneDeep(originalVersionedData)
|
||||
versionedData.meta.version = version
|
||||
try {
|
||||
@ -14,7 +13,9 @@ export default {
|
||||
versionedData.data.config.provider.type = 'rpc'
|
||||
versionedData.data.config.provider.rpcTarget = 'https://rpc.metamask.io/'
|
||||
}
|
||||
} catch (e) {}
|
||||
} catch (_) {
|
||||
// empty
|
||||
}
|
||||
return Promise.resolve(versionedData)
|
||||
},
|
||||
}
|
||||
|
@ -1,20 +1,22 @@
|
||||
import { cloneDeep } from 'lodash'
|
||||
|
||||
const version = 3
|
||||
const oldTestRpc = 'https://rawtestrpc.metamask.io/'
|
||||
const newTestRpc = 'https://testrpc.metamask.io/'
|
||||
|
||||
import { cloneDeep } from 'lodash'
|
||||
|
||||
export default {
|
||||
version,
|
||||
|
||||
migrate: function (originalVersionedData) {
|
||||
migrate (originalVersionedData) {
|
||||
const versionedData = cloneDeep(originalVersionedData)
|
||||
versionedData.meta.version = version
|
||||
try {
|
||||
if (versionedData.data.config.provider.rpcTarget === oldTestRpc) {
|
||||
versionedData.data.config.provider.rpcTarget = newTestRpc
|
||||
}
|
||||
} catch (e) {}
|
||||
} catch (_) {
|
||||
// empty
|
||||
}
|
||||
return Promise.resolve(versionedData)
|
||||
},
|
||||
}
|
||||
|
@ -1,11 +1,11 @@
|
||||
const version = 4
|
||||
|
||||
import { cloneDeep } from 'lodash'
|
||||
|
||||
const version = 4
|
||||
|
||||
export default {
|
||||
version,
|
||||
|
||||
migrate: function (versionedData) {
|
||||
migrate (versionedData) {
|
||||
const safeVersionedData = cloneDeep(versionedData)
|
||||
safeVersionedData.meta.version = version
|
||||
try {
|
||||
@ -25,7 +25,9 @@ export default {
|
||||
break
|
||||
// No default
|
||||
}
|
||||
} catch (_) {}
|
||||
} catch (_) {
|
||||
// empty
|
||||
}
|
||||
return Promise.resolve(safeVersionedData)
|
||||
},
|
||||
}
|
||||
|
@ -1,5 +1,3 @@
|
||||
const version = 5
|
||||
|
||||
/*
|
||||
|
||||
This migration moves state from the flat state trie into KeyringController substate
|
||||
@ -8,11 +6,12 @@ This migration moves state from the flat state trie into KeyringController subst
|
||||
|
||||
import { cloneDeep } from 'lodash'
|
||||
|
||||
const version = 5
|
||||
|
||||
export default {
|
||||
version,
|
||||
|
||||
migrate: function (originalVersionedData) {
|
||||
migrate (originalVersionedData) {
|
||||
const versionedData = cloneDeep(originalVersionedData)
|
||||
versionedData.meta.version = version
|
||||
try {
|
||||
@ -20,14 +19,14 @@ export default {
|
||||
const newState = selectSubstateForKeyringController(state)
|
||||
versionedData.data = newState
|
||||
} catch (err) {
|
||||
console.warn('MetaMask Migration #5' + err.stack)
|
||||
console.warn(`MetaMask Migration #5${err.stack}`)
|
||||
}
|
||||
return Promise.resolve(versionedData)
|
||||
},
|
||||
}
|
||||
|
||||
function selectSubstateForKeyringController (state) {
|
||||
const config = state.config
|
||||
const { config } = state
|
||||
const newState = {
|
||||
...state,
|
||||
KeyringController: {
|
||||
|
@ -1,5 +1,3 @@
|
||||
const version = 6
|
||||
|
||||
/*
|
||||
|
||||
This migration moves KeyringController.selectedAddress to PreferencesController.selectedAddress
|
||||
@ -8,10 +6,12 @@ This migration moves KeyringController.selectedAddress to PreferencesController.
|
||||
|
||||
import { cloneDeep } from 'lodash'
|
||||
|
||||
const version = 6
|
||||
|
||||
export default {
|
||||
version,
|
||||
|
||||
migrate: function (originalVersionedData) {
|
||||
migrate (originalVersionedData) {
|
||||
const versionedData = cloneDeep(originalVersionedData)
|
||||
versionedData.meta.version = version
|
||||
try {
|
||||
@ -19,7 +19,7 @@ export default {
|
||||
const newState = migrateState(state)
|
||||
versionedData.data = newState
|
||||
} catch (err) {
|
||||
console.warn(`MetaMask Migration #${version}` + err.stack)
|
||||
console.warn(`MetaMask Migration #${version}${err.stack}`)
|
||||
}
|
||||
return Promise.resolve(versionedData)
|
||||
},
|
||||
|
@ -1,5 +1,3 @@
|
||||
const version = 7
|
||||
|
||||
/*
|
||||
|
||||
This migration breaks out the TransactionManager substate
|
||||
@ -8,10 +6,12 @@ This migration breaks out the TransactionManager substate
|
||||
|
||||
import { cloneDeep } from 'lodash'
|
||||
|
||||
const version = 7
|
||||
|
||||
export default {
|
||||
version,
|
||||
|
||||
migrate: function (originalVersionedData) {
|
||||
migrate (originalVersionedData) {
|
||||
const versionedData = cloneDeep(originalVersionedData)
|
||||
versionedData.meta.version = version
|
||||
try {
|
||||
@ -19,7 +19,7 @@ export default {
|
||||
const newState = transformState(state)
|
||||
versionedData.data = newState
|
||||
} catch (err) {
|
||||
console.warn(`MetaMask Migration #${version}` + err.stack)
|
||||
console.warn(`MetaMask Migration #${version}${err.stack}`)
|
||||
}
|
||||
return Promise.resolve(versionedData)
|
||||
},
|
||||
|
@ -1,5 +1,3 @@
|
||||
const version = 8
|
||||
|
||||
/*
|
||||
|
||||
This migration breaks out the NoticeController substate
|
||||
@ -8,10 +6,12 @@ This migration breaks out the NoticeController substate
|
||||
|
||||
import { cloneDeep } from 'lodash'
|
||||
|
||||
const version = 8
|
||||
|
||||
export default {
|
||||
version,
|
||||
|
||||
migrate: function (originalVersionedData) {
|
||||
migrate (originalVersionedData) {
|
||||
const versionedData = cloneDeep(originalVersionedData)
|
||||
versionedData.meta.version = version
|
||||
try {
|
||||
@ -19,7 +19,7 @@ export default {
|
||||
const newState = transformState(state)
|
||||
versionedData.data = newState
|
||||
} catch (err) {
|
||||
console.warn(`MetaMask Migration #${version}` + err.stack)
|
||||
console.warn(`MetaMask Migration #${version}${err.stack}`)
|
||||
}
|
||||
return Promise.resolve(versionedData)
|
||||
},
|
||||
|
@ -1,5 +1,3 @@
|
||||
const version = 9
|
||||
|
||||
/*
|
||||
|
||||
This migration breaks out the CurrencyController substate
|
||||
@ -8,10 +6,12 @@ This migration breaks out the CurrencyController substate
|
||||
|
||||
import { cloneDeep, merge } from 'lodash'
|
||||
|
||||
const version = 9
|
||||
|
||||
export default {
|
||||
version,
|
||||
|
||||
migrate: function (originalVersionedData) {
|
||||
migrate (originalVersionedData) {
|
||||
const versionedData = cloneDeep(originalVersionedData)
|
||||
versionedData.meta.version = version
|
||||
try {
|
||||
@ -19,7 +19,7 @@ export default {
|
||||
const newState = transformState(state)
|
||||
versionedData.data = newState
|
||||
} catch (err) {
|
||||
console.warn(`MetaMask Migration #${version}` + err.stack)
|
||||
console.warn(`MetaMask Migration #${version}${err.stack}`)
|
||||
}
|
||||
return Promise.resolve(versionedData)
|
||||
},
|
||||
|
@ -1,5 +1,3 @@
|
||||
const version = 10
|
||||
|
||||
/*
|
||||
|
||||
This migration breaks out the ShapeShiftController substate
|
||||
@ -8,10 +6,12 @@ This migration breaks out the ShapeShiftController substate
|
||||
|
||||
import { cloneDeep, merge } from 'lodash'
|
||||
|
||||
const version = 10
|
||||
|
||||
export default {
|
||||
version,
|
||||
|
||||
migrate: function (originalVersionedData) {
|
||||
migrate (originalVersionedData) {
|
||||
const versionedData = cloneDeep(originalVersionedData)
|
||||
versionedData.meta.version = version
|
||||
try {
|
||||
@ -19,7 +19,7 @@ export default {
|
||||
const newState = transformState(state)
|
||||
versionedData.data = newState
|
||||
} catch (err) {
|
||||
console.warn(`MetaMask Migration #${version}` + err.stack)
|
||||
console.warn(`MetaMask Migration #${version}${err.stack}`)
|
||||
}
|
||||
return Promise.resolve(versionedData)
|
||||
},
|
||||
|
@ -1,5 +1,3 @@
|
||||
const version = 11
|
||||
|
||||
/*
|
||||
|
||||
This migration removes the discaimer state from our app, which was integrated into our notices.
|
||||
@ -8,10 +6,12 @@ This migration removes the discaimer state from our app, which was integrated in
|
||||
|
||||
import { cloneDeep } from 'lodash'
|
||||
|
||||
const version = 11
|
||||
|
||||
export default {
|
||||
version,
|
||||
|
||||
migrate: function (originalVersionedData) {
|
||||
migrate (originalVersionedData) {
|
||||
const versionedData = cloneDeep(originalVersionedData)
|
||||
versionedData.meta.version = version
|
||||
try {
|
||||
@ -19,7 +19,7 @@ export default {
|
||||
const newState = transformState(state)
|
||||
versionedData.data = newState
|
||||
} catch (err) {
|
||||
console.warn(`MetaMask Migration #${version}` + err.stack)
|
||||
console.warn(`MetaMask Migration #${version}${err.stack}`)
|
||||
}
|
||||
return Promise.resolve(versionedData)
|
||||
},
|
||||
|
@ -1,5 +1,3 @@
|
||||
const version = 12
|
||||
|
||||
/*
|
||||
|
||||
This migration modifies our notices to delete their body after being read.
|
||||
@ -8,10 +6,12 @@ This migration modifies our notices to delete their body after being read.
|
||||
|
||||
import { cloneDeep } from 'lodash'
|
||||
|
||||
const version = 12
|
||||
|
||||
export default {
|
||||
version,
|
||||
|
||||
migrate: function (originalVersionedData) {
|
||||
migrate (originalVersionedData) {
|
||||
const versionedData = cloneDeep(originalVersionedData)
|
||||
versionedData.meta.version = version
|
||||
try {
|
||||
@ -19,7 +19,7 @@ export default {
|
||||
const newState = transformState(state)
|
||||
versionedData.data = newState
|
||||
} catch (err) {
|
||||
console.warn(`MetaMask Migration #${version}` + err.stack)
|
||||
console.warn(`MetaMask Migration #${version}${err.stack}`)
|
||||
}
|
||||
return Promise.resolve(versionedData)
|
||||
},
|
||||
|
@ -1,5 +1,3 @@
|
||||
const version = 13
|
||||
|
||||
/*
|
||||
|
||||
This migration modifies the network config from ambiguous 'testnet' to explicit 'ropsten'
|
||||
@ -8,10 +6,12 @@ This migration modifies the network config from ambiguous 'testnet' to explicit
|
||||
|
||||
import { cloneDeep } from 'lodash'
|
||||
|
||||
const version = 13
|
||||
|
||||
export default {
|
||||
version,
|
||||
|
||||
migrate: function (originalVersionedData) {
|
||||
migrate (originalVersionedData) {
|
||||
const versionedData = cloneDeep(originalVersionedData)
|
||||
versionedData.meta.version = version
|
||||
try {
|
||||
@ -19,7 +19,7 @@ export default {
|
||||
const newState = transformState(state)
|
||||
versionedData.data = newState
|
||||
} catch (err) {
|
||||
console.warn(`MetaMask Migration #${version}` + err.stack)
|
||||
console.warn(`MetaMask Migration #${version}${err.stack}`)
|
||||
}
|
||||
return Promise.resolve(versionedData)
|
||||
},
|
||||
|
@ -1,5 +1,3 @@
|
||||
const version = 14
|
||||
|
||||
/*
|
||||
|
||||
This migration removes provider from config and moves it too NetworkController.
|
||||
@ -8,10 +6,12 @@ This migration removes provider from config and moves it too NetworkController.
|
||||
|
||||
import { cloneDeep } from 'lodash'
|
||||
|
||||
const version = 14
|
||||
|
||||
export default {
|
||||
version,
|
||||
|
||||
migrate: function (originalVersionedData) {
|
||||
migrate (originalVersionedData) {
|
||||
const versionedData = cloneDeep(originalVersionedData)
|
||||
versionedData.meta.version = version
|
||||
try {
|
||||
@ -19,7 +19,7 @@ export default {
|
||||
const newState = transformState(state)
|
||||
versionedData.data = newState
|
||||
} catch (err) {
|
||||
console.warn(`MetaMask Migration #${version}` + err.stack)
|
||||
console.warn(`MetaMask Migration #${version}${err.stack}`)
|
||||
}
|
||||
return Promise.resolve(versionedData)
|
||||
},
|
||||
|
@ -1,5 +1,3 @@
|
||||
const version = 15
|
||||
|
||||
/*
|
||||
|
||||
This migration sets transactions with the 'Gave up submitting tx.' err message
|
||||
@ -9,10 +7,12 @@ to a 'failed' stated
|
||||
|
||||
import { cloneDeep } from 'lodash'
|
||||
|
||||
const version = 15
|
||||
|
||||
export default {
|
||||
version,
|
||||
|
||||
migrate: function (originalVersionedData) {
|
||||
migrate (originalVersionedData) {
|
||||
const versionedData = cloneDeep(originalVersionedData)
|
||||
versionedData.meta.version = version
|
||||
try {
|
||||
@ -20,7 +20,7 @@ export default {
|
||||
const newState = transformState(state)
|
||||
versionedData.data = newState
|
||||
} catch (err) {
|
||||
console.warn(`MetaMask Migration #${version}` + err.stack)
|
||||
console.warn(`MetaMask Migration #${version}${err.stack}`)
|
||||
}
|
||||
return Promise.resolve(versionedData)
|
||||
},
|
||||
@ -30,7 +30,7 @@ function transformState (state) {
|
||||
const newState = state
|
||||
const { TransactionController } = newState
|
||||
if (TransactionController && TransactionController.transactions) {
|
||||
const transactions = TransactionController.transactions
|
||||
const { transactions } = TransactionController
|
||||
newState.TransactionController.transactions = transactions.map((txMeta) => {
|
||||
if (!txMeta.err) {
|
||||
return txMeta
|
||||
|
@ -1,5 +1,3 @@
|
||||
const version = 16
|
||||
|
||||
/*
|
||||
|
||||
This migration sets transactions with the 'Gave up submitting tx.' err message
|
||||
@ -9,10 +7,12 @@ to a 'failed' stated
|
||||
|
||||
import { cloneDeep } from 'lodash'
|
||||
|
||||
const version = 16
|
||||
|
||||
export default {
|
||||
version,
|
||||
|
||||
migrate: function (originalVersionedData) {
|
||||
migrate (originalVersionedData) {
|
||||
const versionedData = cloneDeep(originalVersionedData)
|
||||
versionedData.meta.version = version
|
||||
try {
|
||||
@ -20,7 +20,7 @@ export default {
|
||||
const newState = transformState(state)
|
||||
versionedData.data = newState
|
||||
} catch (err) {
|
||||
console.warn(`MetaMask Migration #${version}` + err.stack)
|
||||
console.warn(`MetaMask Migration #${version}${err.stack}`)
|
||||
}
|
||||
return Promise.resolve(versionedData)
|
||||
},
|
||||
@ -30,7 +30,7 @@ function transformState (state) {
|
||||
const newState = state
|
||||
const { TransactionController } = newState
|
||||
if (TransactionController && TransactionController.transactions) {
|
||||
const transactions = newState.TransactionController.transactions
|
||||
const { transactions } = newState.TransactionController
|
||||
|
||||
newState.TransactionController.transactions = transactions.map((txMeta) => {
|
||||
if (!txMeta.err) {
|
||||
|
@ -1,5 +1,3 @@
|
||||
const version = 17
|
||||
|
||||
/*
|
||||
|
||||
This migration sets transactions who were retried and marked as failed to submitted
|
||||
@ -8,10 +6,12 @@ This migration sets transactions who were retried and marked as failed to submit
|
||||
|
||||
import { cloneDeep } from 'lodash'
|
||||
|
||||
const version = 17
|
||||
|
||||
export default {
|
||||
version,
|
||||
|
||||
migrate: function (originalVersionedData) {
|
||||
migrate (originalVersionedData) {
|
||||
const versionedData = cloneDeep(originalVersionedData)
|
||||
versionedData.meta.version = version
|
||||
try {
|
||||
@ -19,7 +19,7 @@ export default {
|
||||
const newState = transformState(state)
|
||||
versionedData.data = newState
|
||||
} catch (err) {
|
||||
console.warn(`MetaMask Migration #${version}` + err.stack)
|
||||
console.warn(`MetaMask Migration #${version}${err.stack}`)
|
||||
}
|
||||
return Promise.resolve(versionedData)
|
||||
},
|
||||
@ -29,7 +29,7 @@ function transformState (state) {
|
||||
const newState = state
|
||||
const { TransactionController } = newState
|
||||
if (TransactionController && TransactionController.transactions) {
|
||||
const transactions = newState.TransactionController.transactions
|
||||
const { transactions } = newState.TransactionController
|
||||
newState.TransactionController.transactions = transactions.map((txMeta) => {
|
||||
if (!txMeta.status === 'failed') {
|
||||
return txMeta
|
||||
|
@ -1,5 +1,3 @@
|
||||
const version = 18
|
||||
|
||||
/*
|
||||
|
||||
This migration updates "transaction state history" to diffs style
|
||||
@ -12,11 +10,12 @@ import {
|
||||
migrateFromSnapshotsToDiffs,
|
||||
} from '../controllers/transactions/lib/tx-state-history-helpers'
|
||||
|
||||
const version = 18
|
||||
|
||||
export default {
|
||||
version,
|
||||
|
||||
migrate: function (originalVersionedData) {
|
||||
migrate (originalVersionedData) {
|
||||
const versionedData = cloneDeep(originalVersionedData)
|
||||
versionedData.meta.version = version
|
||||
try {
|
||||
@ -24,7 +23,7 @@ export default {
|
||||
const newState = transformState(state)
|
||||
versionedData.data = newState
|
||||
} catch (err) {
|
||||
console.warn(`MetaMask Migration #${version}` + err.stack)
|
||||
console.warn(`MetaMask Migration #${version}${err.stack}`)
|
||||
}
|
||||
return Promise.resolve(versionedData)
|
||||
},
|
||||
@ -34,7 +33,7 @@ function transformState (state) {
|
||||
const newState = state
|
||||
const { TransactionController } = newState
|
||||
if (TransactionController && TransactionController.transactions) {
|
||||
const transactions = newState.TransactionController.transactions
|
||||
const { transactions } = newState.TransactionController
|
||||
newState.TransactionController.transactions = transactions.map((txMeta) => {
|
||||
// no history: initialize
|
||||
if (!txMeta.history || txMeta.history.length === 0) {
|
||||
|
@ -1,6 +1,4 @@
|
||||
|
||||
const version = 19
|
||||
|
||||
/*
|
||||
|
||||
This migration sets transactions as failed
|
||||
@ -10,10 +8,12 @@ whos nonce is too high
|
||||
|
||||
import { cloneDeep } from 'lodash'
|
||||
|
||||
const version = 19
|
||||
|
||||
export default {
|
||||
version,
|
||||
|
||||
migrate: function (originalVersionedData) {
|
||||
migrate (originalVersionedData) {
|
||||
const versionedData = cloneDeep(originalVersionedData)
|
||||
versionedData.meta.version = version
|
||||
try {
|
||||
@ -21,7 +21,7 @@ export default {
|
||||
const newState = transformState(state)
|
||||
versionedData.data = newState
|
||||
} catch (err) {
|
||||
console.warn(`MetaMask Migration #${version}` + err.stack)
|
||||
console.warn(`MetaMask Migration #${version}${err.stack}`)
|
||||
}
|
||||
return Promise.resolve(versionedData)
|
||||
},
|
||||
@ -32,7 +32,7 @@ function transformState (state) {
|
||||
const { TransactionController } = newState
|
||||
if (TransactionController && TransactionController.transactions) {
|
||||
|
||||
const transactions = newState.TransactionController.transactions
|
||||
const { transactions } = newState.TransactionController
|
||||
|
||||
newState.TransactionController.transactions = transactions.map((txMeta, _, txList) => {
|
||||
if (txMeta.status !== 'submitted') {
|
||||
@ -66,13 +66,13 @@ function transformState (state) {
|
||||
|
||||
function getHighestContinuousFrom (txList, startPoint) {
|
||||
const nonces = txList.map((txMeta) => {
|
||||
const nonce = txMeta.txParams.nonce
|
||||
const { nonce } = txMeta.txParams
|
||||
return parseInt(nonce, 16)
|
||||
})
|
||||
|
||||
let highest = startPoint
|
||||
while (nonces.includes(highest)) {
|
||||
highest++
|
||||
highest += 1
|
||||
}
|
||||
|
||||
return highest
|
||||
@ -80,7 +80,7 @@ function getHighestContinuousFrom (txList, startPoint) {
|
||||
|
||||
function getHighestNonce (txList) {
|
||||
const nonces = txList.map((txMeta) => {
|
||||
const nonce = txMeta.txParams.nonce
|
||||
const { nonce } = txMeta.txParams
|
||||
return parseInt(nonce || '0x0', 16)
|
||||
})
|
||||
const highestNonce = Math.max.apply(null, nonces)
|
||||
|
@ -1,5 +1,3 @@
|
||||
const version = 20
|
||||
|
||||
/*
|
||||
|
||||
This migration ensures previous installations
|
||||
@ -10,10 +8,12 @@ so that we can version notices in the future.
|
||||
|
||||
import { cloneDeep } from 'lodash'
|
||||
|
||||
const version = 20
|
||||
|
||||
export default {
|
||||
version,
|
||||
|
||||
migrate: function (originalVersionedData) {
|
||||
migrate (originalVersionedData) {
|
||||
const versionedData = cloneDeep(originalVersionedData)
|
||||
versionedData.meta.version = version
|
||||
try {
|
||||
@ -21,7 +21,7 @@ export default {
|
||||
const newState = transformState(state)
|
||||
versionedData.data = newState
|
||||
} catch (err) {
|
||||
console.warn(`MetaMask Migration #${version}` + err.stack)
|
||||
console.warn(`MetaMask Migration #${version}${err.stack}`)
|
||||
}
|
||||
return Promise.resolve(versionedData)
|
||||
},
|
||||
|
@ -1,5 +1,3 @@
|
||||
const version = 21
|
||||
|
||||
/*
|
||||
|
||||
This migration removes the BlackListController from disk state
|
||||
@ -8,10 +6,12 @@ This migration removes the BlackListController from disk state
|
||||
|
||||
import { cloneDeep } from 'lodash'
|
||||
|
||||
const version = 21
|
||||
|
||||
export default {
|
||||
version,
|
||||
|
||||
migrate: function (originalVersionedData) {
|
||||
migrate (originalVersionedData) {
|
||||
const versionedData = cloneDeep(originalVersionedData)
|
||||
versionedData.meta.version = version
|
||||
try {
|
||||
@ -19,7 +19,7 @@ export default {
|
||||
const newState = transformState(state)
|
||||
versionedData.data = newState
|
||||
} catch (err) {
|
||||
console.warn(`MetaMask Migration #${version}` + err.stack)
|
||||
console.warn(`MetaMask Migration #${version}${err.stack}`)
|
||||
}
|
||||
return Promise.resolve(versionedData)
|
||||
},
|
||||
|
@ -1,6 +1,4 @@
|
||||
|
||||
const version = 22
|
||||
|
||||
/*
|
||||
|
||||
This migration adds submittedTime to the txMeta if it is not their
|
||||
@ -9,10 +7,12 @@ This migration adds submittedTime to the txMeta if it is not their
|
||||
|
||||
import { cloneDeep } from 'lodash'
|
||||
|
||||
const version = 22
|
||||
|
||||
export default {
|
||||
version,
|
||||
|
||||
migrate: function (originalVersionedData) {
|
||||
migrate (originalVersionedData) {
|
||||
const versionedData = cloneDeep(originalVersionedData)
|
||||
versionedData.meta.version = version
|
||||
try {
|
||||
@ -20,7 +20,7 @@ export default {
|
||||
const newState = transformState(state)
|
||||
versionedData.data = newState
|
||||
} catch (err) {
|
||||
console.warn(`MetaMask Migration #${version}` + err.stack)
|
||||
console.warn(`MetaMask Migration #${version}${err.stack}`)
|
||||
}
|
||||
return Promise.resolve(versionedData)
|
||||
},
|
||||
@ -30,7 +30,7 @@ function transformState (state) {
|
||||
const newState = state
|
||||
const { TransactionController } = newState
|
||||
if (TransactionController && TransactionController.transactions) {
|
||||
const transactions = newState.TransactionController.transactions
|
||||
const { transactions } = newState.TransactionController
|
||||
|
||||
newState.TransactionController.transactions = transactions.map((txMeta) => {
|
||||
if (txMeta.status !== 'submitted' || txMeta.submittedTime) {
|
||||
|
@ -1,6 +1,4 @@
|
||||
|
||||
const version = 23
|
||||
|
||||
/*
|
||||
|
||||
This migration removes transactions that are no longer usefull down to 40 total
|
||||
@ -9,10 +7,12 @@ This migration removes transactions that are no longer usefull down to 40 total
|
||||
|
||||
import { cloneDeep } from 'lodash'
|
||||
|
||||
const version = 23
|
||||
|
||||
export default {
|
||||
version,
|
||||
|
||||
migrate: function (originalVersionedData) {
|
||||
migrate (originalVersionedData) {
|
||||
const versionedData = cloneDeep(originalVersionedData)
|
||||
versionedData.meta.version = version
|
||||
try {
|
||||
@ -20,7 +20,7 @@ export default {
|
||||
const newState = transformState(state)
|
||||
versionedData.data = newState
|
||||
} catch (err) {
|
||||
console.warn(`MetaMask Migration #${version}` + err.stack)
|
||||
console.warn(`MetaMask Migration #${version}${err.stack}`)
|
||||
}
|
||||
return Promise.resolve(versionedData)
|
||||
},
|
||||
@ -31,7 +31,7 @@ function transformState (state) {
|
||||
|
||||
const { TransactionController } = newState
|
||||
if (TransactionController && TransactionController.transactions) {
|
||||
const transactions = newState.TransactionController.transactions
|
||||
const { transactions } = newState.TransactionController
|
||||
|
||||
if (transactions.length <= 40) {
|
||||
return newState
|
||||
|
@ -1,6 +1,4 @@
|
||||
|
||||
const version = 24
|
||||
|
||||
/*
|
||||
|
||||
This migration ensures that the from address in txParams is to lower case for
|
||||
@ -10,10 +8,12 @@ all unapproved transactions
|
||||
|
||||
import { cloneDeep } from 'lodash'
|
||||
|
||||
const version = 24
|
||||
|
||||
export default {
|
||||
version,
|
||||
|
||||
migrate: async function (originalVersionedData) {
|
||||
async migrate (originalVersionedData) {
|
||||
const versionedData = cloneDeep(originalVersionedData)
|
||||
versionedData.meta.version = version
|
||||
const state = versionedData.data
|
||||
@ -28,7 +28,7 @@ function transformState (state) {
|
||||
if (!newState.TransactionController) {
|
||||
return newState
|
||||
}
|
||||
const transactions = newState.TransactionController.transactions
|
||||
const { transactions } = newState.TransactionController
|
||||
newState.TransactionController.transactions = transactions.map((txMeta, _) => {
|
||||
if (
|
||||
txMeta.status === 'unapproved' &&
|
||||
|
@ -1,6 +1,4 @@
|
||||
// next version number
|
||||
const version = 25
|
||||
|
||||
/*
|
||||
|
||||
normalizes txParams on unconfirmed txs
|
||||
@ -10,10 +8,12 @@ import ethUtil from 'ethereumjs-util'
|
||||
|
||||
import { cloneDeep } from 'lodash'
|
||||
|
||||
const version = 25
|
||||
|
||||
export default {
|
||||
version,
|
||||
|
||||
migrate: async function (originalVersionedData) {
|
||||
async migrate (originalVersionedData) {
|
||||
const versionedData = cloneDeep(originalVersionedData)
|
||||
versionedData.meta.version = version
|
||||
const state = versionedData.data
|
||||
@ -28,7 +28,7 @@ function transformState (state) {
|
||||
|
||||
if (newState.TransactionController) {
|
||||
if (newState.TransactionController.transactions) {
|
||||
const transactions = newState.TransactionController.transactions
|
||||
const { transactions } = newState.TransactionController
|
||||
newState.TransactionController.transactions = transactions.map((txMeta) => {
|
||||
if (txMeta.status !== 'unapproved') {
|
||||
return txMeta
|
||||
|
@ -1,5 +1,3 @@
|
||||
const version = 26
|
||||
|
||||
/*
|
||||
|
||||
This migration moves the identities stored in the KeyringController
|
||||
@ -9,6 +7,8 @@ This migration moves the identities stored in the KeyringController
|
||||
|
||||
import { cloneDeep } from 'lodash'
|
||||
|
||||
const version = 26
|
||||
|
||||
export default {
|
||||
version,
|
||||
migrate (originalVersionedData) {
|
||||
@ -18,7 +18,7 @@ export default {
|
||||
const state = versionedData.data
|
||||
versionedData.data = transformState(state)
|
||||
} catch (err) {
|
||||
console.warn(`MetaMask Migration #${version}` + err.stack)
|
||||
console.warn(`MetaMask Migration #${version}${err.stack}`)
|
||||
return Promise.reject(err)
|
||||
}
|
||||
return Promise.resolve(versionedData)
|
||||
|
@ -1,6 +1,4 @@
|
||||
// next version number
|
||||
const version = 27
|
||||
|
||||
/*
|
||||
|
||||
normalizes txParams on unconfirmed txs
|
||||
@ -8,10 +6,12 @@ normalizes txParams on unconfirmed txs
|
||||
*/
|
||||
import { cloneDeep } from 'lodash'
|
||||
|
||||
const version = 27
|
||||
|
||||
export default {
|
||||
version,
|
||||
|
||||
migrate: async function (originalVersionedData) {
|
||||
async migrate (originalVersionedData) {
|
||||
const versionedData = cloneDeep(originalVersionedData)
|
||||
versionedData.meta.version = version
|
||||
const state = versionedData.data
|
||||
@ -26,7 +26,7 @@ function transformState (state) {
|
||||
|
||||
if (newState.TransactionController) {
|
||||
if (newState.TransactionController.transactions) {
|
||||
const transactions = newState.TransactionController.transactions
|
||||
const { transactions } = newState.TransactionController
|
||||
newState.TransactionController.transactions = transactions.filter((txMeta) => txMeta.status !== 'rejected')
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,4 @@
|
||||
// next version number
|
||||
const version = 28
|
||||
|
||||
/*
|
||||
|
||||
normalizes txParams on unconfirmed txs
|
||||
@ -8,10 +6,12 @@ normalizes txParams on unconfirmed txs
|
||||
*/
|
||||
import { cloneDeep } from 'lodash'
|
||||
|
||||
const version = 28
|
||||
|
||||
export default {
|
||||
version,
|
||||
|
||||
migrate: async function (originalVersionedData) {
|
||||
async migrate (originalVersionedData) {
|
||||
const versionedData = cloneDeep(originalVersionedData)
|
||||
versionedData.meta.version = version
|
||||
const state = versionedData.data
|
||||
@ -26,8 +26,7 @@ function transformState (state) {
|
||||
|
||||
if (newState.PreferencesController) {
|
||||
if (newState.PreferencesController.tokens && newState.PreferencesController.identities) {
|
||||
const identities = newState.PreferencesController.identities
|
||||
const tokens = newState.PreferencesController.tokens
|
||||
const { identities, tokens } = newState.PreferencesController
|
||||
newState.PreferencesController.accountTokens = {}
|
||||
Object.keys(identities).forEach((identity) => {
|
||||
newState.PreferencesController.accountTokens[identity] = { 'mainnet': tokens }
|
||||
|
@ -1,7 +1,8 @@
|
||||
// next version number
|
||||
const version = 29
|
||||
import failTxsThat from './fail-tx'
|
||||
|
||||
const version = 29
|
||||
|
||||
// time
|
||||
const seconds = 1000
|
||||
const minutes = 60 * seconds
|
||||
|
@ -1,6 +1,4 @@
|
||||
// next version number
|
||||
const version = 30
|
||||
|
||||
/*
|
||||
|
||||
removes invalid chaids from preferences and networkController for custom rpcs
|
||||
@ -9,10 +7,12 @@ removes invalid chaids from preferences and networkController for custom rpcs
|
||||
|
||||
import { cloneDeep } from 'lodash'
|
||||
|
||||
const version = 30
|
||||
|
||||
export default {
|
||||
version,
|
||||
|
||||
migrate: async function (originalVersionedData) {
|
||||
async migrate (originalVersionedData) {
|
||||
const versionedData = cloneDeep(originalVersionedData)
|
||||
versionedData.meta.version = version
|
||||
const state = versionedData.data
|
||||
@ -25,10 +25,11 @@ export default {
|
||||
function transformState (state) {
|
||||
const newState = state
|
||||
if (state.PreferencesController) {
|
||||
const frequentRpcListDetail = newState.PreferencesController.frequentRpcListDetail
|
||||
const { frequentRpcListDetail } = newState.PreferencesController
|
||||
if (frequentRpcListDetail) {
|
||||
frequentRpcListDetail.forEach((rpc, index) => {
|
||||
if (!!rpc.chainId && Number.isNaN(parseInt(rpc.chainId))) {
|
||||
// eslint-disable-next-line radix
|
||||
if (Boolean(rpc.chainId) && Number.isNaN(parseInt(rpc.chainId))) {
|
||||
delete frequentRpcListDetail[index].chainId
|
||||
}
|
||||
})
|
||||
@ -36,10 +37,12 @@ function transformState (state) {
|
||||
}
|
||||
}
|
||||
if (state.NetworkController) {
|
||||
// eslint-disable-next-line radix
|
||||
if (newState.NetworkController.network && Number.isNaN(parseInt(newState.NetworkController.network))) {
|
||||
delete newState.NetworkController.network
|
||||
}
|
||||
|
||||
// eslint-disable-next-line radix
|
||||
if (newState.NetworkController.provider && newState.NetworkController.provider.chainId && Number.isNaN(parseInt(newState.NetworkController.provider.chainId))) {
|
||||
delete newState.NetworkController.provider.chainId
|
||||
}
|
||||
|
@ -1,7 +1,8 @@
|
||||
// next version number
|
||||
const version = 31
|
||||
import { cloneDeep } from 'lodash'
|
||||
|
||||
const version = 31
|
||||
|
||||
/*
|
||||
* The purpose of this migration is to properly set the completedOnboarding flag based on the state
|
||||
* of the KeyringController.
|
||||
@ -9,7 +10,7 @@ import { cloneDeep } from 'lodash'
|
||||
export default {
|
||||
version,
|
||||
|
||||
migrate: async function (originalVersionedData) {
|
||||
async migrate (originalVersionedData) {
|
||||
const versionedData = cloneDeep(originalVersionedData)
|
||||
versionedData.meta.version = version
|
||||
const state = versionedData.data
|
||||
|
@ -1,12 +1,13 @@
|
||||
const version = 32
|
||||
import { cloneDeep } from 'lodash'
|
||||
|
||||
const version = 32
|
||||
|
||||
/**
|
||||
* The purpose of this migration is to set the {@code completedUiMigration} flag based on the user's UI preferences
|
||||
*/
|
||||
export default {
|
||||
version,
|
||||
migrate: async function (originalVersionedData) {
|
||||
async migrate (originalVersionedData) {
|
||||
const versionedData = cloneDeep(originalVersionedData)
|
||||
versionedData.meta.version = version
|
||||
const state = versionedData.data
|
||||
|
@ -1,6 +1,4 @@
|
||||
// next version number
|
||||
const version = 33
|
||||
|
||||
/*
|
||||
|
||||
Cleans up notices and assocated notice controller code
|
||||
@ -9,10 +7,12 @@ Cleans up notices and assocated notice controller code
|
||||
|
||||
import { cloneDeep } from 'lodash'
|
||||
|
||||
const version = 33
|
||||
|
||||
export default {
|
||||
version,
|
||||
|
||||
migrate: async function (originalVersionedData) {
|
||||
async migrate (originalVersionedData) {
|
||||
const versionedData = cloneDeep(originalVersionedData)
|
||||
versionedData.meta.version = version
|
||||
const state = versionedData.data
|
||||
|
@ -1,13 +1,14 @@
|
||||
const version = 34
|
||||
import { cloneDeep } from 'lodash'
|
||||
|
||||
const version = 34
|
||||
|
||||
/**
|
||||
* The purpose of this migration is to enable the {@code privacyMode} feature flag and set the user as being migrated
|
||||
* if it was {@code false}.
|
||||
*/
|
||||
export default {
|
||||
version,
|
||||
migrate: async function (originalVersionedData) {
|
||||
async migrate (originalVersionedData) {
|
||||
const versionedData = cloneDeep(originalVersionedData)
|
||||
versionedData.meta.version = version
|
||||
const state = versionedData.data
|
||||
|
@ -1,6 +1,4 @@
|
||||
// next version number
|
||||
const version = 35
|
||||
|
||||
/*
|
||||
|
||||
Removes the deprecated 'seedWords' state
|
||||
@ -9,10 +7,12 @@ Removes the deprecated 'seedWords' state
|
||||
|
||||
import { cloneDeep } from 'lodash'
|
||||
|
||||
const version = 35
|
||||
|
||||
export default {
|
||||
version,
|
||||
|
||||
migrate: async function (originalVersionedData) {
|
||||
async migrate (originalVersionedData) {
|
||||
const versionedData = cloneDeep(originalVersionedData)
|
||||
versionedData.meta.version = version
|
||||
versionedData.data = transformState(versionedData.data)
|
||||
|
@ -1,12 +1,13 @@
|
||||
const version = 36
|
||||
import { cloneDeep } from 'lodash'
|
||||
|
||||
const version = 36
|
||||
|
||||
/**
|
||||
* The purpose of this migration is to remove the {@code privacyMode} feature flag.
|
||||
*/
|
||||
export default {
|
||||
version,
|
||||
migrate: async function (originalVersionedData) {
|
||||
async migrate (originalVersionedData) {
|
||||
const versionedData = cloneDeep(originalVersionedData)
|
||||
versionedData.meta.version = version
|
||||
const state = versionedData.data
|
||||
|
@ -1,7 +1,8 @@
|
||||
const version = 37
|
||||
import { cloneDeep } from 'lodash'
|
||||
import { util } from '@metamask/controllers'
|
||||
|
||||
const version = 37
|
||||
|
||||
/**
|
||||
* The purpose of this migration is to update the address book state
|
||||
* to the new schema with chainId as a key.
|
||||
@ -9,7 +10,7 @@ import { util } from '@metamask/controllers'
|
||||
*/
|
||||
export default {
|
||||
version,
|
||||
migrate: async function (originalVersionedData) {
|
||||
async migrate (originalVersionedData) {
|
||||
const versionedData = cloneDeep(originalVersionedData)
|
||||
versionedData.meta.version = version
|
||||
const state = versionedData.data
|
||||
|
@ -1,12 +1,13 @@
|
||||
const version = 38
|
||||
import { cloneDeep } from 'lodash'
|
||||
|
||||
const version = 38
|
||||
|
||||
/**
|
||||
* The purpose of this migration is to assign all users to a test group for the fullScreenVsPopup a/b test
|
||||
*/
|
||||
export default {
|
||||
version,
|
||||
migrate: async function (originalVersionedData) {
|
||||
async migrate (originalVersionedData) {
|
||||
const versionedData = cloneDeep(originalVersionedData)
|
||||
versionedData.meta.version = version
|
||||
const state = versionedData.data
|
||||
@ -19,17 +20,18 @@ function transformState (state) {
|
||||
const { ABTestController: ABTestControllerState = {} } = state
|
||||
const { abTests = {} } = ABTestControllerState
|
||||
|
||||
if (!abTests.fullScreenVsPopup) {
|
||||
state = {
|
||||
...state,
|
||||
ABTestController: {
|
||||
...ABTestControllerState,
|
||||
abTests: {
|
||||
...abTests,
|
||||
fullScreenVsPopup: 'control',
|
||||
},
|
||||
},
|
||||
}
|
||||
if (abTests.fullScreenVsPopup) {
|
||||
return state
|
||||
}
|
||||
|
||||
return {
|
||||
...state,
|
||||
ABTestController: {
|
||||
...ABTestControllerState,
|
||||
abTests: {
|
||||
...abTests,
|
||||
fullScreenVsPopup: 'control',
|
||||
},
|
||||
},
|
||||
}
|
||||
return state
|
||||
}
|
||||
|
@ -1,7 +1,8 @@
|
||||
const version = 39
|
||||
import { cloneDeep } from 'lodash'
|
||||
import ethUtil from 'ethereumjs-util'
|
||||
|
||||
const version = 39
|
||||
|
||||
const DAI_V1_CONTRACT_ADDRESS = '0x89d24A6b4CcB1B6fAA2625fE562bDD9a23260359'
|
||||
const DAI_V1_TOKEN_SYMBOL = 'DAI'
|
||||
const SAI_TOKEN_SYMBOL = 'SAI'
|
||||
@ -21,7 +22,7 @@ function isOldDai (token = {}) {
|
||||
*/
|
||||
export default {
|
||||
version,
|
||||
migrate: async function (originalVersionedData) {
|
||||
async migrate (originalVersionedData) {
|
||||
const versionedData = cloneDeep(originalVersionedData)
|
||||
versionedData.meta.version = version
|
||||
const state = versionedData.data
|
||||
|
@ -1,6 +1,7 @@
|
||||
const version = 40
|
||||
import { cloneDeep } from 'lodash'
|
||||
|
||||
const version = 40
|
||||
|
||||
/**
|
||||
* Site connections are now managed by the PermissionsController, and the
|
||||
* ProviderApprovalController is removed. This migration deletes all
|
||||
@ -8,7 +9,7 @@ import { cloneDeep } from 'lodash'
|
||||
*/
|
||||
export default {
|
||||
version,
|
||||
migrate: async function (originalVersionedData) {
|
||||
async migrate (originalVersionedData) {
|
||||
const versionedData = cloneDeep(originalVersionedData)
|
||||
versionedData.meta.version = version
|
||||
const state = versionedData.data
|
||||
|
@ -1,12 +1,13 @@
|
||||
const version = 41
|
||||
import { cloneDeep } from 'lodash'
|
||||
|
||||
const version = 41
|
||||
|
||||
/**
|
||||
* PreferencesController.autoLogoutTimeLimit -> autoLockTimeLimit
|
||||
*/
|
||||
export default {
|
||||
version,
|
||||
migrate: async function (originalVersionedData) {
|
||||
async migrate (originalVersionedData) {
|
||||
const versionedData = cloneDeep(originalVersionedData)
|
||||
versionedData.meta.version = version
|
||||
const state = versionedData.data
|
||||
|
@ -1,13 +1,14 @@
|
||||
const version = 42
|
||||
import { cloneDeep } from 'lodash'
|
||||
|
||||
const version = 42
|
||||
|
||||
/**
|
||||
* Initialize `connectedStatusPopoverHasBeenShown` to `false` if it hasn't yet been set,
|
||||
* so that existing users are introduced to the new connected status indicator
|
||||
*/
|
||||
export default {
|
||||
version,
|
||||
migrate: async function (originalVersionedData) {
|
||||
async migrate (originalVersionedData) {
|
||||
const versionedData = cloneDeep(originalVersionedData)
|
||||
versionedData.meta.version = version
|
||||
const state = versionedData.data
|
||||
|
@ -1,12 +1,13 @@
|
||||
const version = 43
|
||||
import { cloneDeep } from 'lodash'
|
||||
|
||||
const version = 43
|
||||
|
||||
/**
|
||||
* Remove unused 'currentAccountTab' state
|
||||
*/
|
||||
export default {
|
||||
version,
|
||||
migrate: async function (originalVersionedData) {
|
||||
async migrate (originalVersionedData) {
|
||||
const versionedData = cloneDeep(originalVersionedData)
|
||||
versionedData.meta.version = version
|
||||
const state = versionedData.data
|
||||
|
@ -1,12 +1,13 @@
|
||||
const version = 44
|
||||
import { cloneDeep } from 'lodash'
|
||||
|
||||
const version = 44
|
||||
|
||||
/**
|
||||
* Remove unused 'mkrMigrationReminderTimestamp' state from the `AppStateController`
|
||||
*/
|
||||
export default {
|
||||
version,
|
||||
migrate: async function (originalVersionedData) {
|
||||
async migrate (originalVersionedData) {
|
||||
const versionedData = cloneDeep(originalVersionedData)
|
||||
versionedData.meta.version = version
|
||||
const state = versionedData.data
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user