From e226b10a89d87af07c7c35ff1251a8264f3bb1b8 Mon Sep 17 00:00:00 2001 From: Alexander Tseung Date: Tue, 28 Nov 2017 20:24:35 -0800 Subject: Add react-router to allow use of the browser back button --- app/scripts/lib/is-popup-or-notification.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'app/scripts') diff --git a/app/scripts/lib/is-popup-or-notification.js b/app/scripts/lib/is-popup-or-notification.js index e2999411f..ad3e825c0 100644 --- a/app/scripts/lib/is-popup-or-notification.js +++ b/app/scripts/lib/is-popup-or-notification.js @@ -3,7 +3,8 @@ module.exports = function isPopupOrNotification () { // if (url.match(/popup.html$/) || url.match(/home.html$/)) { // Below regexes needed for feature toggles (e.g. see line ~340 in ui/app/app.js) // Revert below regexes to above commented out regexes before merge to master - if (url.match(/popup.html(?:\?.+)*$/) || url.match(/home.html(?:\?.+)*$/)) { + if (url.match(/popup.html(?:\?.+)*$/) || + url.match(/home.html(?:\?.+)*$/) || url.match(/home.html(?:#.*)*$/)) { return 'popup' } else { return 'notification' -- cgit From e8a480aac44546e6bd5d7457545bc951a8787814 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Mon, 2 Apr 2018 13:17:54 -0700 Subject: transactions validationt - valdate from field on txParams --- app/scripts/lib/tx-gas-utils.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'app/scripts') diff --git a/app/scripts/lib/tx-gas-utils.js b/app/scripts/lib/tx-gas-utils.js index 0fa9dd8d4..4be7738b0 100644 --- a/app/scripts/lib/tx-gas-utils.js +++ b/app/scripts/lib/tx-gas-utils.js @@ -100,6 +100,7 @@ module.exports = class TxGasUtil { } async validateTxParams (txParams) { + this.validateFrom(txParams) this.validateRecipient(txParams) if ('value' in txParams) { const value = txParams.value.toString() @@ -112,6 +113,12 @@ module.exports = class TxGasUtil { } } } + + validateFrom (txParams) { + if ( !(typeof txParams.from === 'string') ) throw new Error(`Invalid from address ${txParams.from} not a string`) + if (!isValidAddress(txParams.from)) throw new Error('Invalid from address') + } + validateRecipient (txParams) { if (txParams.to === '0x' || txParams.to === null ) { if (txParams.data) { @@ -124,4 +131,4 @@ module.exports = class TxGasUtil { } return txParams } -} +} \ No newline at end of file -- cgit From ab126b8c7894a0cfb8e728eeed48689200ed7a6c Mon Sep 17 00:00:00 2001 From: frankiebee Date: Mon, 2 Apr 2018 15:43:32 -0700 Subject: transactions gasLimit - use the block gasLimit if getCode fails --- app/scripts/controllers/transactions.js | 5 +++-- app/scripts/lib/tx-gas-utils.js | 4 +++- 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'app/scripts') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index a18a2d2e2..31e53554d 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -187,12 +187,12 @@ module.exports = class TransactionController extends EventEmitter { // validate await this.txGasUtil.validateTxParams(txParams) // construct txMeta - const txMeta = this.txStateManager.generateTxMeta({txParams}) + let txMeta = this.txStateManager.generateTxMeta({txParams}) this.addTx(txMeta) this.emit('newUnapprovedTx', txMeta) // add default tx params try { - await this.addTxDefaults(txMeta) + txMeta = await this.addTxDefaults(txMeta) } catch (error) { console.log(error) this.txStateManager.setTxStatusFailed(txMeta.id, error) @@ -215,6 +215,7 @@ module.exports = class TransactionController extends EventEmitter { } txParams.gasPrice = ethUtil.addHexPrefix(gasPrice.toString(16)) txParams.value = txParams.value || '0x0' + if (txParams.to === null) delete txParams.to // set gasLimit return await this.txGasUtil.analyzeGasUsage(txMeta) } diff --git a/app/scripts/lib/tx-gas-utils.js b/app/scripts/lib/tx-gas-utils.js index 4be7738b0..829b4c421 100644 --- a/app/scripts/lib/tx-gas-utils.js +++ b/app/scripts/lib/tx-gas-utils.js @@ -52,7 +52,9 @@ module.exports = class TxGasUtil { // if recipient has no code, gas is 21k max: const recipient = txParams.to const hasRecipient = Boolean(recipient) - const code = await this.query.getCode(recipient) + let code + if (recipient) code = await this.query.getCode(recipient) + if (hasRecipient && (!code || code === '0x')) { txParams.gas = SIMPLE_GAS_COST txMeta.simpleSend = true // Prevents buffer addition -- cgit From 00657e14a8b102051157e18bbea24630ff050488 Mon Sep 17 00:00:00 2001 From: kumavis Date: Tue, 3 Apr 2018 09:51:33 -0700 Subject: build - correctly set METAMASK_ENV via envify --- app/scripts/background.js | 4 ++-- app/scripts/config.js | 2 +- app/scripts/first-time-state.js | 2 +- app/scripts/inpage.js | 2 +- app/scripts/lib/setupRaven.js | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) (limited to 'app/scripts') diff --git a/app/scripts/background.js b/app/scripts/background.js index 7782fc41e..3ad0a7863 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -22,7 +22,7 @@ const EdgeEncryptor = require('./edge-encryptor') const getFirstPreferredLangCode = require('./lib/get-first-preferred-lang-code') const STORAGE_KEY = 'metamask-config' -const METAMASK_DEBUG = 'GULP_METAMASK_DEBUG' +const METAMASK_DEBUG = process.env.METAMASK_DEBUG window.log = log log.setDefaultLevel(METAMASK_DEBUG ? 'debug' : 'warn') @@ -94,7 +94,7 @@ function setupController (initState, initLangCode) { // // MetaMask Controller // - + const controller = new MetamaskController({ // User confirmation callbacks: showUnconfirmedMessage: triggerUi, diff --git a/app/scripts/config.js b/app/scripts/config.js index 74c5b576e..a8470ed82 100644 --- a/app/scripts/config.js +++ b/app/scripts/config.js @@ -13,7 +13,7 @@ const DEFAULT_RPC = 'rinkeby' const OLD_UI_NETWORK_TYPE = 'network' const BETA_UI_NETWORK_TYPE = 'networkBeta' -global.METAMASK_DEBUG = 'GULP_METAMASK_DEBUG' +global.METAMASK_DEBUG = process.env.METAMASK_DEBUG module.exports = { network: { diff --git a/app/scripts/first-time-state.js b/app/scripts/first-time-state.js index 5e8577100..3063df627 100644 --- a/app/scripts/first-time-state.js +++ b/app/scripts/first-time-state.js @@ -1,6 +1,6 @@ // test and development environment variables const env = process.env.METAMASK_ENV -const METAMASK_DEBUG = 'GULP_METAMASK_DEBUG' +const METAMASK_DEBUG = process.env.METAMASK_DEBUG // // The default state of MetaMask diff --git a/app/scripts/inpage.js b/app/scripts/inpage.js index 9261e7d64..ec99bfc35 100644 --- a/app/scripts/inpage.js +++ b/app/scripts/inpage.js @@ -9,7 +9,7 @@ const setupDappAutoReload = require('./lib/auto-reload.js') const MetamaskInpageProvider = require('./lib/inpage-provider.js') restoreContextAfterImports() -const METAMASK_DEBUG = 'GULP_METAMASK_DEBUG' +const METAMASK_DEBUG = process.env.METAMASK_DEBUG window.log = log log.setDefaultLevel(METAMASK_DEBUG ? 'debug' : 'warn') diff --git a/app/scripts/lib/setupRaven.js b/app/scripts/lib/setupRaven.js index b93591e65..9ec9a256f 100644 --- a/app/scripts/lib/setupRaven.js +++ b/app/scripts/lib/setupRaven.js @@ -1,5 +1,5 @@ const Raven = require('raven-js') -const METAMASK_DEBUG = 'GULP_METAMASK_DEBUG' +const METAMASK_DEBUG = process.env.METAMASK_DEBUG const extractEthjsErrorMessage = require('./extractEthjsErrorMessage') const PROD = 'https://3567c198f8a8412082d32655da2961d0@sentry.io/273505' const DEV = 'https://f59f3dd640d2429d9d0e2445a87ea8e1@sentry.io/273496' -- cgit From ecbab14cae659cdcec9e59dc0a3f450069a6a05f Mon Sep 17 00:00:00 2001 From: kumavis Date: Tue, 3 Apr 2018 10:33:10 -0700 Subject: app - warn on fetch errors instead of spamming sentry --- app/scripts/controllers/blacklist.js | 5 ++--- app/scripts/controllers/currency.js | 22 ++++++++++------------ app/scripts/controllers/infura.js | 18 ++++++++---------- app/scripts/controllers/shapeshift.js | 15 ++++++++------- 4 files changed, 28 insertions(+), 32 deletions(-) (limited to 'app/scripts') diff --git a/app/scripts/controllers/blacklist.js b/app/scripts/controllers/blacklist.js index 33c31dab9..df41c90c0 100644 --- a/app/scripts/controllers/blacklist.js +++ b/app/scripts/controllers/blacklist.js @@ -41,9 +41,9 @@ class BlacklistController { scheduleUpdates () { if (this._phishingUpdateIntervalRef) return - this.updatePhishingList() + this.updatePhishingList().catch(log.warn) this._phishingUpdateIntervalRef = setInterval(() => { - this.updatePhishingList() + this.updatePhishingList().catch(log.warn) }, POLLING_INTERVAL) } @@ -57,4 +57,3 @@ class BlacklistController { } module.exports = BlacklistController - diff --git a/app/scripts/controllers/currency.js b/app/scripts/controllers/currency.js index 930fc52e8..aca57dc71 100644 --- a/app/scripts/controllers/currency.js +++ b/app/scripts/controllers/currency.js @@ -43,20 +43,18 @@ class CurrencyController { this.store.updateState({ conversionDate }) } - updateConversionRate () { - const currentCurrency = this.getCurrentCurrency() - return fetch(`https://api.infura.io/v1/ticker/eth${currentCurrency.toLowerCase()}`) - .then(response => response.json()) - .then((parsedResponse) => { + await updateConversionRate () { + try { + const currentCurrency = this.getCurrentCurrency() + const response = await fetch(`https://api.infura.io/v1/ticker/eth${currentCurrency.toLowerCase()}`) + const parsedResponse = await response.json() this.setConversionRate(Number(parsedResponse.bid)) this.setConversionDate(Number(parsedResponse.timestamp)) - }).catch((err) => { - if (err) { - console.warn(`MetaMask - Failed to query currency conversion:`, currentCurrency, err) - this.setConversionRate(0) - this.setConversionDate('N/A') - } - }) + } catch (err) { + console.warn(`MetaMask - Failed to query currency conversion:`, currentCurrency, err) + this.setConversionRate(0) + this.setConversionDate('N/A') + } } scheduleConversionInterval () { diff --git a/app/scripts/controllers/infura.js b/app/scripts/controllers/infura.js index 10adb1004..c6b4c9de2 100644 --- a/app/scripts/controllers/infura.js +++ b/app/scripts/controllers/infura.js @@ -19,15 +19,13 @@ class InfuraController { // Responsible for retrieving the status of Infura's nodes. Can return either // ok, degraded, or down. - checkInfuraNetworkStatus () { - return fetch('https://api.infura.io/v1/status/metamask') - .then(response => response.json()) - .then((parsedResponse) => { - this.store.updateState({ - infuraNetworkStatus: parsedResponse, - }) - return parsedResponse - }) + async checkInfuraNetworkStatus () { + const response = await fetch('https://api.infura.io/v1/status/metamask') + const parsedResponse = await response.json() + this.store.updateState({ + infuraNetworkStatus: parsedResponse, + }) + return parsedResponse } scheduleInfuraNetworkCheck () { @@ -35,7 +33,7 @@ class InfuraController { clearInterval(this.conversionInterval) } this.conversionInterval = setInterval(() => { - this.checkInfuraNetworkStatus() + this.checkInfuraNetworkStatus().catch(log.warn) }, POLLING_INTERVAL) } } diff --git a/app/scripts/controllers/shapeshift.js b/app/scripts/controllers/shapeshift.js index 3d955c01f..3bbfaa1c5 100644 --- a/app/scripts/controllers/shapeshift.js +++ b/app/scripts/controllers/shapeshift.js @@ -45,18 +45,19 @@ class ShapeshiftController { }) } - updateTx (tx) { - const url = `https://shapeshift.io/txStat/${tx.depositAddress}` - return fetch(url) - .then((response) => { - return response.json() - }).then((json) => { + async updateTx (tx) { + try { + const url = `https://shapeshift.io/txStat/${tx.depositAddress}` + const response = await fetch(url) + const json = await response.json() tx.response = json if (tx.response.status === 'complete') { tx.time = new Date().getTime() } return tx - }) + } catch (err) { + log.warn(err) + } } saveTx (tx) { -- cgit From 79d63332eeb798346f5cd4af6fc4ff91372ab014 Mon Sep 17 00:00:00 2001 From: kumavis Date: Tue, 3 Apr 2018 10:35:41 -0700 Subject: app - currency - fix typo --- app/scripts/controllers/currency.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/scripts') diff --git a/app/scripts/controllers/currency.js b/app/scripts/controllers/currency.js index aca57dc71..266d8ff1d 100644 --- a/app/scripts/controllers/currency.js +++ b/app/scripts/controllers/currency.js @@ -43,7 +43,7 @@ class CurrencyController { this.store.updateState({ conversionDate }) } - await updateConversionRate () { + async updateConversionRate () { try { const currentCurrency = this.getCurrentCurrency() const response = await fetch(`https://api.infura.io/v1/ticker/eth${currentCurrency.toLowerCase()}`) -- cgit From 038ad914541c3a4e6579da5b1ac79ba41b33cfb3 Mon Sep 17 00:00:00 2001 From: kumavis Date: Tue, 3 Apr 2018 10:39:23 -0700 Subject: app - currency - fix typo + prefer log over console --- app/scripts/controllers/currency.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'app/scripts') diff --git a/app/scripts/controllers/currency.js b/app/scripts/controllers/currency.js index 266d8ff1d..36b8808aa 100644 --- a/app/scripts/controllers/currency.js +++ b/app/scripts/controllers/currency.js @@ -44,14 +44,15 @@ class CurrencyController { } async updateConversionRate () { + let currentCurrency try { - const currentCurrency = this.getCurrentCurrency() + currentCurrency = this.getCurrentCurrency() const response = await fetch(`https://api.infura.io/v1/ticker/eth${currentCurrency.toLowerCase()}`) const parsedResponse = await response.json() this.setConversionRate(Number(parsedResponse.bid)) this.setConversionDate(Number(parsedResponse.timestamp)) } catch (err) { - console.warn(`MetaMask - Failed to query currency conversion:`, currentCurrency, err) + log.warn(`MetaMask - Failed to query currency conversion:`, currentCurrency, err) this.setConversionRate(0) this.setConversionDate('N/A') } -- cgit From 3b1e4c74f5c8d503184a75584dca570187a13b8c Mon Sep 17 00:00:00 2001 From: frankiebee Date: Tue, 3 Apr 2018 12:14:30 -0700 Subject: transactions - dont throw if chain id is not a string --- app/scripts/lib/tx-state-manager.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app/scripts') diff --git a/app/scripts/lib/tx-state-manager.js b/app/scripts/lib/tx-state-manager.js index 23c915a61..3577d45d0 100644 --- a/app/scripts/lib/tx-state-manager.js +++ b/app/scripts/lib/tx-state-manager.js @@ -140,8 +140,8 @@ module.exports = class TransactionStateManager extends EventEmitter { validateTxParams(txParams) { Object.keys(txParams).forEach((key) => { const value = txParams[key] - if (typeof value !== 'string') throw new Error(`${key}: ${value} in txParams is not a string`) - if (!ethUtil.isHexPrefixed(value)) throw new Error('is not hex prefixed, everything on txParams must be hex prefixed') + if (typeof value !== 'string' && key !== 'chainId') throw new Error(`${key}: ${value} in txParams is not a string`) + if (!ethUtil.isHexPrefixed(value) && key !== 'chainId') throw new Error('is not hex prefixed, everything on txParams must be hex prefixed') }) } -- cgit From 83df8b58ba470b6446c158789a308e801bf5becb Mon Sep 17 00:00:00 2001 From: kumavis Date: Tue, 3 Apr 2018 13:55:20 -0700 Subject: tx-state-manager - validateTxParams - validate chainId is Number --- app/scripts/lib/tx-state-manager.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'app/scripts') diff --git a/app/scripts/lib/tx-state-manager.js b/app/scripts/lib/tx-state-manager.js index 3577d45d0..9e597ef37 100644 --- a/app/scripts/lib/tx-state-manager.js +++ b/app/scripts/lib/tx-state-manager.js @@ -140,8 +140,16 @@ module.exports = class TransactionStateManager extends EventEmitter { validateTxParams(txParams) { Object.keys(txParams).forEach((key) => { const value = txParams[key] - if (typeof value !== 'string' && key !== 'chainId') throw new Error(`${key}: ${value} in txParams is not a string`) - if (!ethUtil.isHexPrefixed(value) && key !== 'chainId') throw new Error('is not hex prefixed, everything on txParams must be hex prefixed') + // validate types + switch (key) { + case 'chainId': + if (typeof value !== 'number') throw new Error(`${key} in txParams is not a Number. got: (${value})`) + break + default: + if (typeof value !== 'string') throw new Error(`${key} in txParams is not a string. got: (${value})`) + if (!ethUtil.isHexPrefixed(value)) throw new Error(`${key} in txParams is not hex prefixed. got: (${value})`) + break + } }) } -- cgit From 5aff114001d21696e7a7670db56b53cf3f36afa5 Mon Sep 17 00:00:00 2001 From: Dan Date: Tue, 3 Apr 2018 20:34:28 -0230 Subject: Ensure get-first-preferred-lang-code.js matches locale codes from local directory names and chrome extension api. --- app/scripts/lib/get-first-preferred-lang-code.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/scripts') diff --git a/app/scripts/lib/get-first-preferred-lang-code.js b/app/scripts/lib/get-first-preferred-lang-code.js index 28612f763..25221ff98 100644 --- a/app/scripts/lib/get-first-preferred-lang-code.js +++ b/app/scripts/lib/get-first-preferred-lang-code.js @@ -2,7 +2,7 @@ const extension = require('extensionizer') const promisify = require('pify') const allLocales = require('../../_locales/index.json') -const existingLocaleCodes = allLocales.map(locale => locale.code) +const existingLocaleCodes = allLocales.map(locale => locale.code.replace('_', '-')) async function getFirstPreferredLangCode () { const userPreferredLocaleCodes = await promisify( -- cgit From 3c4b72bf2c5eab9c98531fcf7b0929a415b63f87 Mon Sep 17 00:00:00 2001 From: Dan Date: Tue, 3 Apr 2018 20:52:17 -0230 Subject: Map existingLocaleCodes and userPreferredLocaleCodes to lower case in get-first-preferred-lang-code.js --- app/scripts/lib/get-first-preferred-lang-code.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'app/scripts') diff --git a/app/scripts/lib/get-first-preferred-lang-code.js b/app/scripts/lib/get-first-preferred-lang-code.js index 25221ff98..e3635434e 100644 --- a/app/scripts/lib/get-first-preferred-lang-code.js +++ b/app/scripts/lib/get-first-preferred-lang-code.js @@ -2,14 +2,16 @@ const extension = require('extensionizer') const promisify = require('pify') const allLocales = require('../../_locales/index.json') -const existingLocaleCodes = allLocales.map(locale => locale.code.replace('_', '-')) +const existingLocaleCodes = allLocales.map(locale => locale.code.toLowerCase().replace('_', '-')) async function getFirstPreferredLangCode () { const userPreferredLocaleCodes = await promisify( extension.i18n.getAcceptLanguages, { errorFirst: false } )() - const firstPreferredLangCode = userPreferredLocaleCodes.find(code => existingLocaleCodes.includes(code)) + const firstPreferredLangCode = userPreferredLocaleCodes + .map(code => code.toLowerCase()) + .find(code => existingLocaleCodes.includes(code)) return firstPreferredLangCode || 'en' } -- cgit From 86693af15653c5966ee7d5842bcc905e2867e925 Mon Sep 17 00:00:00 2001 From: Dan Finlay <542863+danfinlay@users.noreply.github.com> Date: Tue, 3 Apr 2018 20:33:19 -0700 Subject: Add webby awards to web3 block list. --- app/scripts/contentscript.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'app/scripts') diff --git a/app/scripts/contentscript.js b/app/scripts/contentscript.js index 2098fae27..fe1766273 100644 --- a/app/scripts/contentscript.js +++ b/app/scripts/contentscript.js @@ -131,7 +131,11 @@ function documentElementCheck () { } function blacklistedDomainCheck () { - var blacklistedDomains = ['uscourts.gov', 'dropbox.com'] + var blacklistedDomains = [ + 'uscourts.gov', + 'dropbox.com', + 'webbyawards.com', + ] var currentUrl = window.location.href var currentRegex for (let i = 0; i < blacklistedDomains.length; i++) { -- cgit From 502011019a028258305abcb415cdba1b2530b5ad Mon Sep 17 00:00:00 2001 From: kumavis Date: Wed, 4 Apr 2018 08:59:03 -0700 Subject: tx - txParams - allow chainId to be a hex string --- app/scripts/lib/tx-state-manager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/scripts') diff --git a/app/scripts/lib/tx-state-manager.js b/app/scripts/lib/tx-state-manager.js index 9e597ef37..2ab24d6a0 100644 --- a/app/scripts/lib/tx-state-manager.js +++ b/app/scripts/lib/tx-state-manager.js @@ -143,7 +143,7 @@ module.exports = class TransactionStateManager extends EventEmitter { // validate types switch (key) { case 'chainId': - if (typeof value !== 'number') throw new Error(`${key} in txParams is not a Number. got: (${value})`) + if (typeof value !== 'number' && typeof value !== 'string') throw new Error(`${key} in txParams is not a Number or hex string. got: (${value})`) break default: if (typeof value !== 'string') throw new Error(`${key} in txParams is not a string. got: (${value})`) -- cgit From 457a47bf62272deb257e3935a62e0ed265a49d78 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Wed, 4 Apr 2018 12:25:51 -0700 Subject: transactions - normalize txParams --- app/scripts/controllers/transactions.js | 54 +++++++++++++++++++++++++++++++-- app/scripts/lib/tx-gas-utils.js | 35 +-------------------- 2 files changed, 53 insertions(+), 36 deletions(-) (limited to 'app/scripts') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 31e53554d..9568fcbb9 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -185,7 +185,8 @@ module.exports = class TransactionController extends EventEmitter { async addUnapprovedTransaction (txParams) { // validate - await this.txGasUtil.validateTxParams(txParams) + await this._validateTxParams(txParams) + this._normalizeTxParams(txParams) // construct txMeta let txMeta = this.txStateManager.generateTxMeta({txParams}) this.addTx(txMeta) @@ -215,7 +216,6 @@ module.exports = class TransactionController extends EventEmitter { } txParams.gasPrice = ethUtil.addHexPrefix(gasPrice.toString(16)) txParams.value = txParams.value || '0x0' - if (txParams.to === null) delete txParams.to // set gasLimit return await this.txGasUtil.analyzeGasUsage(txMeta) } @@ -314,6 +314,56 @@ module.exports = class TransactionController extends EventEmitter { // PRIVATE METHODS // + _normalizeTxParams (txParams) { + delete txParams.chainId + + if ( !txParams.to ) delete txParams.to + else txParams.to = ethUtil.addHexPrefix(txParams.to) + + txParams.from = ethUtil.addHexPrefix(txParams.from).toLowerCase() + + if (!txParams.data) delete txParams.data + else txParams.data = ethUtil.addHexPrefix(txParams.data) + + if (txParams.value) txParams.value = ethUtil.addHexPrefix(txParams.value) + + if (txParams.gas) txParams.gas = ethUtil.addHexPrefix(txParams.gas) + if (txParams.gasPrice) txParams.gas = ethUtil.addHexPrefix(txParams.gas) + } + + async _validateTxParams (txParams) { + this._validateFrom(txParams) + this._validateRecipient(txParams) + if ('value' in txParams) { + const value = txParams.value.toString() + if (value.includes('-')) { + throw new Error(`Invalid transaction value of ${txParams.value} not a positive number.`) + } + + if (value.includes('.')) { + throw new Error(`Invalid transaction value of ${txParams.value} number must be in wei`) + } + } + } + + _validateFrom (txParams) { + if ( !(typeof txParams.from === 'string') ) throw new Error(`Invalid from address ${txParams.from} not a string`) + if (!ethUtil.isValidAddress(txParams.from)) throw new Error('Invalid from address') + } + + _validateRecipient (txParams) { + if (txParams.to === '0x' || txParams.to === null ) { + if (txParams.data) { + delete txParams.to + } else { + throw new Error('Invalid recipient address') + } + } else if ( txParams.to !== undefined && !ethUtil.isValidAddress(txParams.to) ) { + throw new Error('Invalid recipient address') + } + return txParams + } + _markNonceDuplicatesDropped (txId) { this.txStateManager.setTxStatusConfirmed(txId) // get the confirmed transactions nonce and from address diff --git a/app/scripts/lib/tx-gas-utils.js b/app/scripts/lib/tx-gas-utils.js index 829b4c421..c579e462a 100644 --- a/app/scripts/lib/tx-gas-utils.js +++ b/app/scripts/lib/tx-gas-utils.js @@ -4,7 +4,7 @@ const { BnMultiplyByFraction, bnToHex, } = require('./util') -const { addHexPrefix, isValidAddress } = require('ethereumjs-util') +const { addHexPrefix } = require('ethereumjs-util') const SIMPLE_GAS_COST = '0x5208' // Hex for 21000, cost of a simple send. /* @@ -100,37 +100,4 @@ module.exports = class TxGasUtil { // otherwise use blockGasLimit return bnToHex(upperGasLimitBn) } - - async validateTxParams (txParams) { - this.validateFrom(txParams) - this.validateRecipient(txParams) - if ('value' in txParams) { - const value = txParams.value.toString() - if (value.includes('-')) { - throw new Error(`Invalid transaction value of ${txParams.value} not a positive number.`) - } - - if (value.includes('.')) { - throw new Error(`Invalid transaction value of ${txParams.value} number must be in wei`) - } - } - } - - validateFrom (txParams) { - if ( !(typeof txParams.from === 'string') ) throw new Error(`Invalid from address ${txParams.from} not a string`) - if (!isValidAddress(txParams.from)) throw new Error('Invalid from address') - } - - validateRecipient (txParams) { - if (txParams.to === '0x' || txParams.to === null ) { - if (txParams.data) { - delete txParams.to - } else { - throw new Error('Invalid recipient address') - } - } else if ( txParams.to !== undefined && !isValidAddress(txParams.to) ) { - throw new Error('Invalid recipient address') - } - return txParams - } } \ No newline at end of file -- cgit From 8243824c6af97e9b4d44f47b783d789fcf734705 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Wed, 4 Apr 2018 14:22:46 -0700 Subject: hot-fix - migrate unaproved txParams so that the from is lowercase --- app/scripts/migrations/024.js | 45 +++++++++++++++++++++++++++++++++++++++++ app/scripts/migrations/index.js | 1 + 2 files changed, 46 insertions(+) create mode 100644 app/scripts/migrations/024.js (limited to 'app/scripts') diff --git a/app/scripts/migrations/024.js b/app/scripts/migrations/024.js new file mode 100644 index 000000000..7a0391805 --- /dev/null +++ b/app/scripts/migrations/024.js @@ -0,0 +1,45 @@ + +const version = 24 + +/* + +This migration ensures that the from address in txParams is to lower case for +all unapproved transactions + +*/ + +const clone = require('clone') + +module.exports = { + version, + + migrate: function (originalVersionedData) { + const versionedData = clone(originalVersionedData) + versionedData.meta.version = version + try { + const state = versionedData.data + const newState = transformState(state) + versionedData.data = newState + } catch (err) { + console.warn(`MetaMask Migration #${version}` + err.stack) + } + return Promise.resolve(versionedData) + }, +} + +function transformState (state) { + const newState = state + const transactions = newState.TransactionController.transactions + + newState.TransactionController.transactions = transactions.map((txMeta, _, txList) => { + if ( + txMeta.status === 'unapproved' && + txMeta.txParams && + txMeta.txParams.from + ) { + txMeta.txParams.from = txMeta.txParams.from.toLowerCase() + } + return txMeta + }) + return newState +} diff --git a/app/scripts/migrations/index.js b/app/scripts/migrations/index.js index 811e06b6b..7e4542740 100644 --- a/app/scripts/migrations/index.js +++ b/app/scripts/migrations/index.js @@ -34,4 +34,5 @@ module.exports = [ require('./021'), require('./022'), require('./023'), + require('./024'), ] -- cgit From 245c01bc0fed585c4ac8ed05edf7ebe1a65de80b Mon Sep 17 00:00:00 2001 From: frankiebee Date: Wed, 4 Apr 2018 14:56:30 -0700 Subject: transactions - make #_validateTxParams not async and "linting" wink wink nudge nudge --- app/scripts/controllers/transactions.js | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) (limited to 'app/scripts') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 9568fcbb9..a73a8b36d 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -185,7 +185,7 @@ module.exports = class TransactionController extends EventEmitter { async addUnapprovedTransaction (txParams) { // validate - await this._validateTxParams(txParams) + this._validateTxParams(txParams) this._normalizeTxParams(txParams) // construct txMeta let txMeta = this.txStateManager.generateTxMeta({txParams}) @@ -317,13 +317,18 @@ module.exports = class TransactionController extends EventEmitter { _normalizeTxParams (txParams) { delete txParams.chainId - if ( !txParams.to ) delete txParams.to - else txParams.to = ethUtil.addHexPrefix(txParams.to) - + if ( !txParams.to ) { + delete txParams.to + } else { + txParams.to = ethUtil.addHexPrefix(txParams.to) + } txParams.from = ethUtil.addHexPrefix(txParams.from).toLowerCase() - if (!txParams.data) delete txParams.data - else txParams.data = ethUtil.addHexPrefix(txParams.data) + if (!txParams.data) { + delete txParams.data + } else { + txParams.data = ethUtil.addHexPrefix(txParams.data) + } if (txParams.value) txParams.value = ethUtil.addHexPrefix(txParams.value) @@ -331,7 +336,7 @@ module.exports = class TransactionController extends EventEmitter { if (txParams.gasPrice) txParams.gas = ethUtil.addHexPrefix(txParams.gas) } - async _validateTxParams (txParams) { + _validateTxParams (txParams) { this._validateFrom(txParams) this._validateRecipient(txParams) if ('value' in txParams) { -- cgit From 343f0e9e80af804f256a5fa1a55b136c8241c368 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Wed, 4 Apr 2018 20:18:44 -0700 Subject: transactions - remove unnecessary keys on txParams --- app/scripts/controllers/transactions.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'app/scripts') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index a73a8b36d..0b78d62f1 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -315,6 +315,18 @@ module.exports = class TransactionController extends EventEmitter { // _normalizeTxParams (txParams) { + const acceptableKeys = [ + 'from', + 'to', + 'nonce', + 'value', + 'data', + 'gas', + 'gasPrice', + ] + Object.keys(txParams).forEach((key) => { + if (!acceptableKeys.includes(key)) delete txParams[key] + }) delete txParams.chainId if ( !txParams.to ) { -- cgit From 418926ffdfabe8aaefbba5abbf44ebbfd838bbfc Mon Sep 17 00:00:00 2001 From: Alexander Tseung Date: Thu, 5 Apr 2018 01:04:12 -0700 Subject: Fix populating txParams with undefined data --- app/scripts/lib/tx-state-manager.js | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'app/scripts') diff --git a/app/scripts/lib/tx-state-manager.js b/app/scripts/lib/tx-state-manager.js index 2ab24d6a0..d8ea17400 100644 --- a/app/scripts/lib/tx-state-manager.js +++ b/app/scripts/lib/tx-state-manager.js @@ -108,6 +108,10 @@ module.exports = class TransactionStateManager extends EventEmitter { updateTx (txMeta, note) { // validate txParams if (txMeta.txParams) { + if (typeof txMeta.txParams.data === 'undefined') { + delete txMeta.txParams.data + } + this.validateTxParams(txMeta.txParams) } -- cgit From 4efc718074a819c15beceece5e0f08b49c8b60bb Mon Sep 17 00:00:00 2001 From: frankiebee Date: Thu, 5 Apr 2018 11:28:25 -0700 Subject: make migration-24 compat with first-time-state --- app/scripts/migrations/024.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/scripts') diff --git a/app/scripts/migrations/024.js b/app/scripts/migrations/024.js index 7a0391805..043b47ccc 100644 --- a/app/scripts/migrations/024.js +++ b/app/scripts/migrations/024.js @@ -29,8 +29,8 @@ module.exports = { function transformState (state) { const newState = state + if (!newState.TransactionController) return newState const transactions = newState.TransactionController.transactions - newState.TransactionController.transactions = transactions.map((txMeta, _, txList) => { if ( txMeta.status === 'unapproved' && -- cgit From c02da0f27ca4a4239ebae4cfd3348a656e258b86 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Thu, 5 Apr 2018 12:12:02 -0700 Subject: transactions - _normalizeTxParams will now return a new object for txParams --- app/scripts/controllers/transactions.js | 49 ++++++++++++--------------------- 1 file changed, 18 insertions(+), 31 deletions(-) (limited to 'app/scripts') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 0b78d62f1..336b0d8f7 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -185,10 +185,10 @@ module.exports = class TransactionController extends EventEmitter { async addUnapprovedTransaction (txParams) { // validate - this._validateTxParams(txParams) - this._normalizeTxParams(txParams) + const normalizedTxParams = this._normalizeTxParams(txParams) + this._validateTxParams(normalizedTxParams) // construct txMeta - let txMeta = this.txStateManager.generateTxMeta({txParams}) + let txMeta = this.txStateManager.generateTxMeta({ txParams: normalizedTxParams }) this.addTx(txMeta) this.emit('newUnapprovedTx', txMeta) // add default tx params @@ -315,37 +315,24 @@ module.exports = class TransactionController extends EventEmitter { // _normalizeTxParams (txParams) { - const acceptableKeys = [ - 'from', - 'to', - 'nonce', - 'value', - 'data', - 'gas', - 'gasPrice', - ] - Object.keys(txParams).forEach((key) => { - if (!acceptableKeys.includes(key)) delete txParams[key] - }) - delete txParams.chainId - - if ( !txParams.to ) { - delete txParams.to - } else { - txParams.to = ethUtil.addHexPrefix(txParams.to) + // functions that handle normalizing of that key in txParams + const whiteList = { + from: from => ethUtil.addHexPrefix(from).toLowerCase(), + to: to => ethUtil.addHexPrefix(txParams.to).toLowerCase(), + nonce: nonce => ethUtil.addHexPrefix(nonce), + value: value => ethUtil.addHexPrefix(value), + data: data => ethUtil.addHexPrefix(data), + gas: gas => ethUtil.addHexPrefix(gas), + gasPrice: gasPrice => ethUtil.addHexPrefix(gasPrice), } - txParams.from = ethUtil.addHexPrefix(txParams.from).toLowerCase() - if (!txParams.data) { - delete txParams.data - } else { - txParams.data = ethUtil.addHexPrefix(txParams.data) - } - - if (txParams.value) txParams.value = ethUtil.addHexPrefix(txParams.value) + // apply only keys in the whiteList + const normalizedTxParams = {} + Object.keys(whiteList).forEach((key) => { + if (txParams[key]) normalizedTxParams[key] = whiteList[key](txParams[key]) + }) - if (txParams.gas) txParams.gas = ethUtil.addHexPrefix(txParams.gas) - if (txParams.gasPrice) txParams.gas = ethUtil.addHexPrefix(txParams.gas) + return normalizedTxParams } _validateTxParams (txParams) { -- cgit From 2b880dd4e060f8f7f95afe9ff2a3e2e6d540c922 Mon Sep 17 00:00:00 2001 From: kumavis Date: Thu, 5 Apr 2018 13:15:08 -0700 Subject: migrations - report migrations errors to sentry with vault structure --- app/scripts/background.js | 20 +++++++++++++++++++- app/scripts/lib/getObjStructure.js | 33 +++++++++++++++++++++++++++++++++ app/scripts/lib/migrator/index.js | 24 ++++++++++++++++++++---- app/scripts/migrations/024.js | 14 +++++--------- 4 files changed, 77 insertions(+), 14 deletions(-) create mode 100644 app/scripts/lib/getObjStructure.js (limited to 'app/scripts') diff --git a/app/scripts/background.js b/app/scripts/background.js index 3ad0a7863..ec586f642 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -20,6 +20,7 @@ const reportFailedTxToSentry = require('./lib/reportFailedTxToSentry') const setupMetamaskMeshMetrics = require('./lib/setupMetamaskMeshMetrics') const EdgeEncryptor = require('./edge-encryptor') const getFirstPreferredLangCode = require('./lib/get-first-preferred-lang-code') +const getObjStructure = require('./lib/getObjStructure') const STORAGE_KEY = 'metamask-config' const METAMASK_DEBUG = process.env.METAMASK_DEBUG @@ -77,6 +78,16 @@ async function loadStateFromPersistence () { diskStore.getState() || migrator.generateInitialState(firstTimeState) + // report migration errors to sentry + migrator.on('error', (err) => { + // get vault structure without secrets + const vaultStructure = getObjStructure(versionedData) + raven.captureException(err, { + // "extra" key is required by Sentry + extra: { vaultStructure }, + }) + }) + // migrate data versionedData = await migrator.migrateData(versionedData) if (!versionedData) { @@ -84,7 +95,14 @@ async function loadStateFromPersistence () { } // write to disk - if (localStore.isSupported) localStore.set(versionedData) + if (localStore.isSupported) { + localStore.set(versionedData) + } else { + // throw in setTimeout so as to not block boot + setTimeout(() => { + throw new Error('MetaMask - Localstore not supported') + }) + } // return just the data return versionedData.data diff --git a/app/scripts/lib/getObjStructure.js b/app/scripts/lib/getObjStructure.js new file mode 100644 index 000000000..3db389507 --- /dev/null +++ b/app/scripts/lib/getObjStructure.js @@ -0,0 +1,33 @@ +const clone = require('clone') + +module.exports = getObjStructure + +// This will create an object that represents the structure of the given object +// it replaces all values with the result of their type + +// { +// "data": { +// "CurrencyController": { +// "conversionDate": "number", +// "conversionRate": "number", +// "currentCurrency": "string" +// } +// } + +function getObjStructure(obj) { + const structure = clone(obj) + return deepMap(structure, (value) => { + return value === null ? 'null' : typeof value + }) +} + +function deepMap(target = {}, visit) { + Object.entries(target).forEach(([key, value]) => { + if (typeof value === 'object' && value !== null) { + target[key] = deepMap(value, visit) + } else { + target[key] = visit(value) + } + }) + return target +} diff --git a/app/scripts/lib/migrator/index.js b/app/scripts/lib/migrator/index.js index 4fd2cae92..203b2ddc9 100644 --- a/app/scripts/lib/migrator/index.js +++ b/app/scripts/lib/migrator/index.js @@ -1,6 +1,9 @@ -class Migrator { +const EventEmitter = require('events') + +class Migrator extends EventEmitter { constructor (opts = {}) { + super() const migrations = opts.migrations || [] // sort migrations by version this.migrations = migrations.sort((a, b) => a.version - b.version) @@ -12,13 +15,26 @@ class Migrator { // run all pending migrations on meta in place async migrateData (versionedData = this.generateInitialState()) { + // get all migrations that have not yet been run const pendingMigrations = this.migrations.filter(migrationIsPending) + // perform each migration for (const index in pendingMigrations) { const migration = pendingMigrations[index] - versionedData = await migration.migrate(versionedData) - if (!versionedData.data) throw new Error('Migrator - migration returned empty data') - if (versionedData.version !== undefined && versionedData.meta.version !== migration.version) throw new Error('Migrator - Migration did not update version number correctly') + try { + // attempt migration and validate + const migratedData = await migration.migrate(versionedData) + if (!migratedData.data) throw new Error('Migrator - migration returned empty data') + if (migratedData.version !== undefined && migratedData.meta.version !== migration.version) throw new Error('Migrator - Migration did not update version number correctly') + // accept the migration as good + versionedData = migratedData + } catch (err) { + // emit error instead of throw so as to not break the run (gracefully fail) + const error = new Error(`MetaMask Migration Error #${version}:\n${err.stack}`) + this.emit('error', error) + // stop migrating and use state as is + return versionedData + } } return versionedData diff --git a/app/scripts/migrations/024.js b/app/scripts/migrations/024.js index 7a0391805..c917a167c 100644 --- a/app/scripts/migrations/024.js +++ b/app/scripts/migrations/024.js @@ -13,17 +13,13 @@ const clone = require('clone') module.exports = { version, - migrate: function (originalVersionedData) { + migrate: async function (originalVersionedData) { const versionedData = clone(originalVersionedData) versionedData.meta.version = version - try { - const state = versionedData.data - const newState = transformState(state) - versionedData.data = newState - } catch (err) { - console.warn(`MetaMask Migration #${version}` + err.stack) - } - return Promise.resolve(versionedData) + const state = versionedData.data + const newState = transformState(state) + versionedData.data = newState + return versionedData }, } -- cgit From 7fdf663ea7ae4b3c6bb5cdefb1f33729f5cf4422 Mon Sep 17 00:00:00 2001 From: kumavis Date: Thu, 5 Apr 2018 13:21:00 -0700 Subject: migrator - fix typo --- app/scripts/lib/migrator/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/scripts') diff --git a/app/scripts/lib/migrator/index.js b/app/scripts/lib/migrator/index.js index 203b2ddc9..ea9af3c80 100644 --- a/app/scripts/lib/migrator/index.js +++ b/app/scripts/lib/migrator/index.js @@ -30,7 +30,7 @@ class Migrator extends EventEmitter { versionedData = migratedData } catch (err) { // emit error instead of throw so as to not break the run (gracefully fail) - const error = new Error(`MetaMask Migration Error #${version}:\n${err.stack}`) + const error = new Error(`MetaMask Migration Error #${migration.version}:\n${err.stack}`) this.emit('error', error) // stop migrating and use state as is return versionedData -- cgit From ffc71ff7d2c27d419bff4ca127ed5219bf9261c3 Mon Sep 17 00:00:00 2001 From: kumavis Date: Thu, 5 Apr 2018 13:38:34 -0700 Subject: migrator - dont overwrite error stack and warn to console --- app/scripts/lib/migrator/index.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'app/scripts') diff --git a/app/scripts/lib/migrator/index.js b/app/scripts/lib/migrator/index.js index ea9af3c80..85c2717ea 100644 --- a/app/scripts/lib/migrator/index.js +++ b/app/scripts/lib/migrator/index.js @@ -29,9 +29,12 @@ class Migrator extends EventEmitter { // accept the migration as good versionedData = migratedData } catch (err) { + // rewrite error message to add context without clobbering stack + const originalErrorMessage = err.message + err.message = `MetaMask Migration Error #${migration.version}: ${originalErrorMessage}` + console.warn(err.stack) // emit error instead of throw so as to not break the run (gracefully fail) - const error = new Error(`MetaMask Migration Error #${migration.version}:\n${err.stack}`) - this.emit('error', error) + this.emit('error', err) // stop migrating and use state as is return versionedData } -- cgit From b9243cd8b9aab3f7eae07fb29f0f184e9a263ee3 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Thu, 5 Apr 2018 16:22:24 -0700 Subject: meta - create a migration template --- app/scripts/migrations/template.js | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 app/scripts/migrations/template.js (limited to 'app/scripts') diff --git a/app/scripts/migrations/template.js b/app/scripts/migrations/template.js new file mode 100644 index 000000000..0915c6bdf --- /dev/null +++ b/app/scripts/migrations/template.js @@ -0,0 +1,29 @@ +// next version number +const version = 0 + +/* + +description of migration and what it does + +*/ + +const clone = require('clone') + +module.exports = { + version, + + migrate: async function (originalVersionedData) { + const versionedData = clone(originalVersionedData) + versionedData.meta.version = version + const state = versionedData.data + const newState = transformState(state) + versionedData.data = newState + return versionedData + }, +} + +function transformState (state) { + const newState = state + // transform state here + return newState +} -- cgit From 7d243aacf9db9dc8e3e2e3acfc54298ffc06fe12 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Thu, 5 Apr 2018 18:05:03 -0700 Subject: create migration 25 --- app/scripts/migrations/025.js | 61 +++++++++++++++++++++++++++++++++++++++++ app/scripts/migrations/index.js | 1 + 2 files changed, 62 insertions(+) create mode 100644 app/scripts/migrations/025.js (limited to 'app/scripts') diff --git a/app/scripts/migrations/025.js b/app/scripts/migrations/025.js new file mode 100644 index 000000000..fc3b20a44 --- /dev/null +++ b/app/scripts/migrations/025.js @@ -0,0 +1,61 @@ +// next version number +const version = 25 + +/* + +normalizes txParams on unconfirmed txs + +*/ +const ethUtil = require('ethereumjs-util') +const clone = require('clone') + +module.exports = { + version, + + migrate: async function (originalVersionedData) { + const versionedData = clone(originalVersionedData) + versionedData.meta.version = version + const state = versionedData.data + const newState = transformState(state) + versionedData.data = newState + return versionedData + }, +} + +function transformState (state) { + const newState = state + + if (newState.TransactionController) { + if (newState.TransactionController.transactions) { + const transactions = newState.TransactionController.transactions + newState.TransactionController.transactions = transactions.map((txMeta) => { + if (txMeta.status !== 'unapproved') return txMeta + txMeta.txParams = normalizeTxParams(txMeta.txParams) + return txMeta + }) + } + } + + return newState +} + +function normalizeTxParams (txParams) { + // functions that handle normalizing of that key in txParams + const whiteList = { + from: from => ethUtil.addHexPrefix(from).toLowerCase(), + to: to => ethUtil.addHexPrefix(txParams.to).toLowerCase(), + nonce: nonce => ethUtil.addHexPrefix(nonce), + value: value => ethUtil.addHexPrefix(value), + data: data => ethUtil.addHexPrefix(data), + gas: gas => ethUtil.addHexPrefix(gas), + gasPrice: gasPrice => ethUtil.addHexPrefix(gasPrice), + } + + // apply only keys in the whiteList + const normalizedTxParams = {} + Object.keys(whiteList).forEach((key) => { + if (txParams[key]) normalizedTxParams[key] = whiteList[key](txParams[key]) + }) + + return normalizedTxParams +} diff --git a/app/scripts/migrations/index.js b/app/scripts/migrations/index.js index 7e4542740..6c4a51b32 100644 --- a/app/scripts/migrations/index.js +++ b/app/scripts/migrations/index.js @@ -35,4 +35,5 @@ module.exports = [ require('./022'), require('./023'), require('./024'), + require('./025'), ] -- cgit From d4e30040a2186a1320a44f86849506729b2dafad Mon Sep 17 00:00:00 2001 From: frankiebee Date: Thu, 5 Apr 2018 19:28:53 -0700 Subject: migrations - back fixes --- app/scripts/migrations/013.js | 7 +++++-- app/scripts/migrations/015.js | 15 +++++++++------ app/scripts/migrations/016.js | 22 +++++++++++++--------- app/scripts/migrations/017.js | 21 ++++++++++++--------- app/scripts/migrations/018.js | 39 ++++++++++++++++++++------------------ app/scripts/migrations/019.js | 44 +++++++++++++++++++++++-------------------- app/scripts/migrations/022.js | 17 ++++++++++------- app/scripts/migrations/023.js | 38 ++++++++++++++++++++----------------- 8 files changed, 115 insertions(+), 88 deletions(-) (limited to 'app/scripts') diff --git a/app/scripts/migrations/013.js b/app/scripts/migrations/013.js index 8f11e510e..15a9b28d4 100644 --- a/app/scripts/migrations/013.js +++ b/app/scripts/migrations/013.js @@ -27,8 +27,11 @@ module.exports = { function transformState (state) { const newState = state - if (newState.config.provider.type === 'testnet') { - newState.config.provider.type = 'ropsten' + const { config } = newState + if ( config && config.provider ) { + if (config.provider.type === 'testnet') { + newState.config.provider.type = 'ropsten' + } } return newState } diff --git a/app/scripts/migrations/015.js b/app/scripts/migrations/015.js index 4b839580b..5e2f9e63b 100644 --- a/app/scripts/migrations/015.js +++ b/app/scripts/migrations/015.js @@ -28,11 +28,14 @@ module.exports = { function transformState (state) { const newState = state - const transactions = newState.TransactionController.transactions - newState.TransactionController.transactions = transactions.map((txMeta) => { - if (!txMeta.err) return txMeta - else if (txMeta.err.message === 'Gave up submitting tx.') txMeta.status = 'failed' - return txMeta - }) + const { TransactionController } = newState + if (TransactionController && TransactionController.transactions) { + const transactions = TransactionController.transactions + newState.TransactionController.transactions = transactions.map((txMeta) => { + if (!txMeta.err) return txMeta + else if (txMeta.err.message === 'Gave up submitting tx.') txMeta.status = 'failed' + return txMeta + }) + } return newState } diff --git a/app/scripts/migrations/016.js b/app/scripts/migrations/016.js index 4fc534f1c..048c7a40e 100644 --- a/app/scripts/migrations/016.js +++ b/app/scripts/migrations/016.js @@ -28,14 +28,18 @@ module.exports = { function transformState (state) { const newState = state - const transactions = newState.TransactionController.transactions - newState.TransactionController.transactions = transactions.map((txMeta) => { - if (!txMeta.err) return txMeta - if (txMeta.err === 'transaction with the same hash was already imported.') { - txMeta.status = 'submitted' - delete txMeta.err - } - return txMeta - }) + const { TransactionController } = newState + if (TransactionController && TransactionController.transactions) { + const transactions = newState.TransactionController.transactions + + newState.TransactionController.transactions = transactions.map((txMeta) => { + if (!txMeta.err) return txMeta + if (txMeta.err === 'transaction with the same hash was already imported.') { + txMeta.status = 'submitted' + delete txMeta.err + } + return txMeta + }) + } return newState } diff --git a/app/scripts/migrations/017.js b/app/scripts/migrations/017.js index 24959cd3a..5f6d906d6 100644 --- a/app/scripts/migrations/017.js +++ b/app/scripts/migrations/017.js @@ -27,14 +27,17 @@ module.exports = { function transformState (state) { const newState = state - const transactions = newState.TransactionController.transactions - newState.TransactionController.transactions = transactions.map((txMeta) => { - if (!txMeta.status === 'failed') return txMeta - if (txMeta.retryCount > 0 && txMeta.retryCount < 2) { - txMeta.status = 'submitted' - delete txMeta.err - } - return txMeta - }) + const { TransactionController } = newState + if (TransactionController && TransactionController.transactions) { + const transactions = newState.TransactionController.transactions + newState.TransactionController.transactions = transactions.map((txMeta) => { + if (!txMeta.status === 'failed') return txMeta + if (txMeta.retryCount > 0 && txMeta.retryCount < 2) { + txMeta.status = 'submitted' + delete txMeta.err + } + return txMeta + }) + } return newState } diff --git a/app/scripts/migrations/018.js b/app/scripts/migrations/018.js index d27fe3f46..bea1fe3da 100644 --- a/app/scripts/migrations/018.js +++ b/app/scripts/migrations/018.js @@ -29,24 +29,27 @@ module.exports = { function transformState (state) { const newState = state - const transactions = newState.TransactionController.transactions - newState.TransactionController.transactions = transactions.map((txMeta) => { - // no history: initialize - if (!txMeta.history || txMeta.history.length === 0) { - const snapshot = txStateHistoryHelper.snapshotFromTxMeta(txMeta) - txMeta.history = [snapshot] + const { TransactionController } = newState + if (TransactionController && TransactionController.transactions) { + const transactions = newState.TransactionController.transactions + newState.TransactionController.transactions = transactions.map((txMeta) => { + // no history: initialize + if (!txMeta.history || txMeta.history.length === 0) { + const snapshot = txStateHistoryHelper.snapshotFromTxMeta(txMeta) + txMeta.history = [snapshot] + return txMeta + } + // has history: migrate + const newHistory = ( + txStateHistoryHelper.migrateFromSnapshotsToDiffs(txMeta.history) + // remove empty diffs + .filter((entry) => { + return !Array.isArray(entry) || entry.length > 0 + }) + ) + txMeta.history = newHistory return txMeta - } - // has history: migrate - const newHistory = ( - txStateHistoryHelper.migrateFromSnapshotsToDiffs(txMeta.history) - // remove empty diffs - .filter((entry) => { - return !Array.isArray(entry) || entry.length > 0 - }) - ) - txMeta.history = newHistory - return txMeta - }) + }) + } return newState } diff --git a/app/scripts/migrations/019.js b/app/scripts/migrations/019.js index 072c96370..ce5da6859 100644 --- a/app/scripts/migrations/019.js +++ b/app/scripts/migrations/019.js @@ -29,32 +29,36 @@ module.exports = { function transformState (state) { const newState = state - const transactions = newState.TransactionController.transactions + const { TransactionController } = newState + if (TransactionController && TransactionController.transactions) { - newState.TransactionController.transactions = transactions.map((txMeta, _, txList) => { - if (txMeta.status !== 'submitted') return txMeta + const transactions = newState.TransactionController.transactions - const confirmedTxs = txList.filter((tx) => tx.status === 'confirmed') - .filter((tx) => tx.txParams.from === txMeta.txParams.from) - .filter((tx) => tx.metamaskNetworkId.from === txMeta.metamaskNetworkId.from) - const highestConfirmedNonce = getHighestNonce(confirmedTxs) + newState.TransactionController.transactions = transactions.map((txMeta, _, txList) => { + if (txMeta.status !== 'submitted') return txMeta - const pendingTxs = txList.filter((tx) => tx.status === 'submitted') - .filter((tx) => tx.txParams.from === txMeta.txParams.from) - .filter((tx) => tx.metamaskNetworkId.from === txMeta.metamaskNetworkId.from) - const highestContinuousNonce = getHighestContinuousFrom(pendingTxs, highestConfirmedNonce) + const confirmedTxs = txList.filter((tx) => tx.status === 'confirmed') + .filter((tx) => tx.txParams.from === txMeta.txParams.from) + .filter((tx) => tx.metamaskNetworkId.from === txMeta.metamaskNetworkId.from) + const highestConfirmedNonce = getHighestNonce(confirmedTxs) - const maxNonce = Math.max(highestContinuousNonce, highestConfirmedNonce) + const pendingTxs = txList.filter((tx) => tx.status === 'submitted') + .filter((tx) => tx.txParams.from === txMeta.txParams.from) + .filter((tx) => tx.metamaskNetworkId.from === txMeta.metamaskNetworkId.from) + const highestContinuousNonce = getHighestContinuousFrom(pendingTxs, highestConfirmedNonce) - if (parseInt(txMeta.txParams.nonce, 16) > maxNonce + 1) { - txMeta.status = 'failed' - txMeta.err = { - message: 'nonce too high', - note: 'migration 019 custom error', + const maxNonce = Math.max(highestContinuousNonce, highestConfirmedNonce) + + if (parseInt(txMeta.txParams.nonce, 16) > maxNonce + 1) { + txMeta.status = 'failed' + txMeta.err = { + message: 'nonce too high', + note: 'migration 019 custom error', + } } - } - return txMeta - }) + return txMeta + }) + } return newState } diff --git a/app/scripts/migrations/022.js b/app/scripts/migrations/022.js index c3c0d53ef..1fbe241e6 100644 --- a/app/scripts/migrations/022.js +++ b/app/scripts/migrations/022.js @@ -28,12 +28,15 @@ module.exports = { function transformState (state) { const newState = state - const transactions = newState.TransactionController.transactions - - newState.TransactionController.transactions = transactions.map((txMeta) => { - if (txMeta.status !== 'submitted' || txMeta.submittedTime) return txMeta - txMeta.submittedTime = (new Date()).getTime() - return txMeta - }) + const { TransactionController } = newState + if (TransactionController && TransactionController.transactions) { + const transactions = newState.TransactionController.transactions + + newState.TransactionController.transactions = transactions.map((txMeta) => { + if (txMeta.status !== 'submitted' || txMeta.submittedTime) return txMeta + txMeta.submittedTime = (new Date()).getTime() + return txMeta + }) + } return newState } diff --git a/app/scripts/migrations/023.js b/app/scripts/migrations/023.js index bce0a5bea..151496b06 100644 --- a/app/scripts/migrations/023.js +++ b/app/scripts/migrations/023.js @@ -28,23 +28,27 @@ module.exports = { function transformState (state) { const newState = state - const transactions = newState.TransactionController.transactions - - if (transactions.length <= 40) return newState - - let reverseTxList = transactions.reverse() - let stripping = true - while (reverseTxList.length > 40 && stripping) { - let txIndex = reverseTxList.findIndex((txMeta) => { - return (txMeta.status === 'failed' || - txMeta.status === 'rejected' || - txMeta.status === 'confirmed' || - txMeta.status === 'dropped') - }) - if (txIndex < 0) stripping = false - else reverseTxList.splice(txIndex, 1) - } - newState.TransactionController.transactions = reverseTxList.reverse() + const { TransactionController } = newState + if (TransactionController && TransactionController.transactions) { + const transactions = newState.TransactionController.transactions + + if (transactions.length <= 40) return newState + + let reverseTxList = transactions.reverse() + let stripping = true + while (reverseTxList.length > 40 && stripping) { + let txIndex = reverseTxList.findIndex((txMeta) => { + return (txMeta.status === 'failed' || + txMeta.status === 'rejected' || + txMeta.status === 'confirmed' || + txMeta.status === 'dropped') + }) + if (txIndex < 0) stripping = false + else reverseTxList.splice(txIndex, 1) + } + + newState.TransactionController.transactions = reverseTxList.reverse() + } return newState } -- cgit From 26fe6383778f6f94698c2d0d2adec4ae2f1d3406 Mon Sep 17 00:00:00 2001 From: kumavis Date: Fri, 6 Apr 2018 10:18:00 -0700 Subject: tx-state-manager - dont remove old tx history if candidate is not found --- app/scripts/lib/tx-state-manager.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'app/scripts') diff --git a/app/scripts/lib/tx-state-manager.js b/app/scripts/lib/tx-state-manager.js index d8ea17400..c6d10ee62 100644 --- a/app/scripts/lib/tx-state-manager.js +++ b/app/scripts/lib/tx-state-manager.js @@ -92,8 +92,10 @@ module.exports = class TransactionStateManager extends EventEmitter { // or rejected tx's. // not tx's that are pending or unapproved if (txCount > txHistoryLimit - 1) { - const index = transactions.findIndex((metaTx) => metaTx.status === 'confirmed' || metaTx.status === 'rejected') - transactions.splice(index, 1) + let index = transactions.findIndex((metaTx) => metaTx.status === 'confirmed' || metaTx.status === 'rejected') + if (index !== -1) { + transactions.splice(index, 1) + } } transactions.push(txMeta) this._saveTxList(transactions) -- cgit From 0685381fdcd3ab8cebc76bf73e9678deaf5d15f8 Mon Sep 17 00:00:00 2001 From: kumavis Date: Fri, 6 Apr 2018 12:05:24 -0700 Subject: metamask - attempt recovery from empty vault --- app/scripts/background.js | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'app/scripts') diff --git a/app/scripts/background.js b/app/scripts/background.js index ec586f642..a4d95289b 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -78,6 +78,28 @@ async function loadStateFromPersistence () { diskStore.getState() || migrator.generateInitialState(firstTimeState) + // check if somehow state is empty + // this should never happen but new error reporting suggests that it has + // for a small number of users + // https://github.com/metamask/metamask-extension/issues/3919 + if (versionedData && !versionedData.data) { + // try to recover from diskStore incase only localStore is bad + const diskStoreState = diskStore.getState() + if (diskStoreState && diskStoreState.data) { + // we were able to recover (though it might be old) + versionedData = diskStoreState + const vaultStructure = getObjStructure(versionedData) + raven.captureMessage('MetaMask - Empty vault found - recovered from diskStore', { + // "extra" key is required by Sentry + extra: { vaultStructure }, + }) + } else { + // unable to recover, clear state + versionedData = migrator.generateInitialState(firstTimeState) + raven.captureMessage('MetaMask - Empty vault found - unable to recover') + } + } + // report migration errors to sentry migrator.on('error', (err) => { // get vault structure without secrets -- cgit From 6f4dbd6d4a27888ccff88d336ae4340cb69c90e7 Mon Sep 17 00:00:00 2001 From: kumavis Date: Fri, 6 Apr 2018 12:08:51 -0700 Subject: metamask - never persist if state is missing data --- app/scripts/background.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'app/scripts') diff --git a/app/scripts/background.js b/app/scripts/background.js index a4d95289b..837fd7133 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -162,9 +162,9 @@ function setupController (initState, initLangCode) { asStream(controller.store), debounce(1000), storeTransform(versionifyData), - storeTransform(syncDataWithExtension), + storeTransform(persistData), (error) => { - log.error('pump hit error', error) + log.error('MetaMask - Persistence pipeline failed', error) } ) @@ -173,7 +173,10 @@ function setupController (initState, initLangCode) { return versionedData } - function syncDataWithExtension(state) { + function persistData(state) { + if (!state.data) { + throw new Error('MetaMask - updated state is missing data', state) + } if (localStore.isSupported) { localStore.set(state) .catch((err) => { -- cgit From f9a6feb26369048d63cc3794f4f94db4c89ed287 Mon Sep 17 00:00:00 2001 From: kumavis Date: Fri, 6 Apr 2018 12:10:39 -0700 Subject: metamask - never persist if state is missing --- app/scripts/background.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'app/scripts') diff --git a/app/scripts/background.js b/app/scripts/background.js index 837fd7133..5878cd2e8 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -174,8 +174,11 @@ function setupController (initState, initLangCode) { } function persistData(state) { + if (!state) { + throw new Error('MetaMask - updated state is missing', state) + } if (!state.data) { - throw new Error('MetaMask - updated state is missing data', state) + throw new Error('MetaMask - updated state does not have data', state) } if (localStore.isSupported) { localStore.set(state) -- cgit