diff options
fix merge conflicts
-rw-r--r-- | CHANGELOG.md | 3 | ||||
-rw-r--r-- | app/scripts/controllers/transactions/index.js | 9 | ||||
-rw-r--r-- | app/scripts/controllers/transactions/nonce-tracker.js | 54 | ||||
-rw-r--r-- | app/scripts/controllers/transactions/pending-tx-tracker.js | 4 | ||||
-rw-r--r-- | app/scripts/inpage.js | 21 | ||||
-rw-r--r-- | app/scripts/lib/auto-reload.js | 61 | ||||
-rw-r--r-- | app/scripts/metamask-controller.js | 20 | ||||
-rw-r--r-- | package-lock.json | 92 | ||||
-rw-r--r-- | package.json | 1 | ||||
-rw-r--r-- | test/e2e/func.js | 2 | ||||
-rw-r--r-- | ui/app/components/pending-tx/confirm-send-ether.js | 2 | ||||
-rw-r--r-- | ui/app/components/pending-tx/confirm-send-token.js | 2 |
12 files changed, 146 insertions, 125 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 9fef15109..3f9413c8a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,8 @@ ## Current Master -- Fix bug where account reset did not work with custom RPC providers. +- Fix bug where account reset did not work with custom RPC providers +- Stop reloading browser page on Ethereum network change ## 4.7.4 Tue Jun 05 2018 diff --git a/app/scripts/controllers/transactions/index.js b/app/scripts/controllers/transactions/index.js index b53947e27..8e2288aed 100644 --- a/app/scripts/controllers/transactions/index.js +++ b/app/scripts/controllers/transactions/index.js @@ -165,7 +165,7 @@ class TransactionController extends EventEmitter { // add default tx params txMeta = await this.addTxGasDefaults(txMeta) } catch (error) { - console.log(error) + log.warn(error) this.txStateManager.setTxStatusFailed(txMeta.id, error) throw error } @@ -264,7 +264,12 @@ class TransactionController extends EventEmitter { // must set transaction to submitted/failed before releasing lock nonceLock.releaseLock() } catch (err) { - this.txStateManager.setTxStatusFailed(txId, err) + // 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) + } // must set transaction to submitted/failed before releasing lock if (nonceLock) nonceLock.releaseLock() // continue with error chain diff --git a/app/scripts/controllers/transactions/nonce-tracker.js b/app/scripts/controllers/transactions/nonce-tracker.js index f8cdc5523..35ca08d6c 100644 --- a/app/scripts/controllers/transactions/nonce-tracker.js +++ b/app/scripts/controllers/transactions/nonce-tracker.js @@ -49,29 +49,35 @@ class NonceTracker { await this._globalMutexFree() // await lock free, then take lock const releaseLock = await this._takeMutex(address) - // evaluate multiple nextNonce strategies - const nonceDetails = {} - const networkNonceResult = await this._getNetworkNextNonce(address) - const highestLocallyConfirmed = this._getHighestLocallyConfirmed(address) - const nextNetworkNonce = networkNonceResult.nonce - const highestSuggested = Math.max(nextNetworkNonce, highestLocallyConfirmed) - - const pendingTxs = this.getPendingTransactions(address) - const localNonceResult = this._getHighestContinuousFrom(pendingTxs, highestSuggested) || 0 - - nonceDetails.params = { - highestLocallyConfirmed, - highestSuggested, - nextNetworkNonce, + try { + // evaluate multiple nextNonce strategies + const nonceDetails = {} + const networkNonceResult = await this._getNetworkNextNonce(address) + const highestLocallyConfirmed = this._getHighestLocallyConfirmed(address) + const nextNetworkNonce = networkNonceResult.nonce + const highestSuggested = Math.max(nextNetworkNonce, highestLocallyConfirmed) + + const pendingTxs = this.getPendingTransactions(address) + const localNonceResult = this._getHighestContinuousFrom(pendingTxs, highestSuggested) || 0 + + nonceDetails.params = { + highestLocallyConfirmed, + highestSuggested, + nextNetworkNonce, + } + nonceDetails.local = localNonceResult + nonceDetails.network = networkNonceResult + + const nextNonce = Math.max(networkNonceResult.nonce, localNonceResult.nonce) + assert(Number.isInteger(nextNonce), `nonce-tracker - nextNonce is not an integer - got: (${typeof nextNonce}) "${nextNonce}"`) + + // return nonce and release cb + return { nextNonce, nonceDetails, releaseLock } + } catch (err) { + // release lock if we encounter an error + releaseLock() + throw err } - nonceDetails.local = localNonceResult - nonceDetails.network = networkNonceResult - - const nextNonce = Math.max(networkNonceResult.nonce, localNonceResult.nonce) - assert(Number.isInteger(nextNonce), `nonce-tracker - nextNonce is not an integer - got: (${typeof nextNonce}) "${nextNonce}"`) - - // return nonce and release cb - return { nextNonce, nonceDetails, releaseLock } } async _getCurrentBlock () { @@ -85,8 +91,8 @@ class NonceTracker { async _globalMutexFree () { const globalMutex = this._lookupMutex('global') - const release = await globalMutex.acquire() - release() + const releaseLock = await globalMutex.acquire() + releaseLock() } async _takeMutex (lockId) { diff --git a/app/scripts/controllers/transactions/pending-tx-tracker.js b/app/scripts/controllers/transactions/pending-tx-tracker.js index 6e2fcb40b..4e41cdaf8 100644 --- a/app/scripts/controllers/transactions/pending-tx-tracker.js +++ b/app/scripts/controllers/transactions/pending-tx-tracker.js @@ -196,14 +196,14 @@ class PendingTransactionTracker extends EventEmitter { async _checkPendingTxs () { const signedTxList = this.getPendingTransactions() // in order to keep the nonceTracker accurate we block it while updating pending transactions - const nonceGlobalLock = await this.nonceTracker.getGlobalLock() + const { releaseLock } = await this.nonceTracker.getGlobalLock() try { await Promise.all(signedTxList.map((txMeta) => this._checkPendingTx(txMeta))) } catch (err) { log.error('PendingTransactionWatcher - Error updating pending transactions') log.error(err) } - nonceGlobalLock.releaseLock() + releaseLock() } /** diff --git a/app/scripts/inpage.js b/app/scripts/inpage.js index 6d16eebd4..070f5d247 100644 --- a/app/scripts/inpage.js +++ b/app/scripts/inpage.js @@ -3,7 +3,6 @@ cleanContextForImports() require('web3/dist/web3.min.js') const log = require('loglevel') const LocalMessageDuplexStream = require('post-message-stream') -const setupDappAutoReload = require('./lib/auto-reload.js') const MetamaskInpageProvider = require('./lib/inpage-provider.js') restoreContextAfterImports() @@ -38,8 +37,24 @@ web3.setProvider = function () { log.debug('MetaMask - overrode web3.setProvider') } log.debug('MetaMask - injected web3') -// export global web3, with usage-detection -setupDappAutoReload(web3, inpageProvider.publicConfigStore) + +// export global web3, with usage-detection and deprecation warning +let hasBeenWarned = false +global.web3 = new Proxy(web3, { + get: (_web3, key) => { + // show warning once on web3 access + if (!hasBeenWarned && key !== 'currentProvider') { + console.warn('MetaMask: web3 will be deprecated in the near future in favor of the ethereumProvider \nhttps://github.com/MetaMask/faq/blob/master/detecting_metamask.md#web3-deprecation') + hasBeenWarned = true + } + // return value normally + return _web3[key] + }, + set: (_web3, key, value) => { + // set value normally + _web3[key] = value + }, +}) // set web3 defaultAccount inpageProvider.publicConfigStore.subscribe(function (state) { diff --git a/app/scripts/lib/auto-reload.js b/app/scripts/lib/auto-reload.js deleted file mode 100644 index cce31c3d2..000000000 --- a/app/scripts/lib/auto-reload.js +++ /dev/null @@ -1,61 +0,0 @@ -module.exports = setupDappAutoReload - -function setupDappAutoReload (web3, observable) { - // export web3 as a global, checking for usage - let hasBeenWarned = false - let reloadInProgress = false - let lastTimeUsed - let lastSeenNetwork - - global.web3 = new Proxy(web3, { - get: (_web3, key) => { - // show warning once on web3 access - if (!hasBeenWarned && key !== 'currentProvider') { - console.warn('MetaMask: web3 will be deprecated in the near future in favor of the ethereumProvider \nhttps://github.com/MetaMask/faq/blob/master/detecting_metamask.md#web3-deprecation') - hasBeenWarned = true - } - // get the time of use - lastTimeUsed = Date.now() - // return value normally - return _web3[key] - }, - set: (_web3, key, value) => { - // set value normally - _web3[key] = value - }, - }) - - observable.subscribe(function (state) { - // if reload in progress, no need to check reload logic - if (reloadInProgress) return - - const currentNetwork = state.networkVersion - - // set the initial network - if (!lastSeenNetwork) { - lastSeenNetwork = currentNetwork - return - } - - // skip reload logic if web3 not used - if (!lastTimeUsed) return - - // if network did not change, exit - if (currentNetwork === lastSeenNetwork) return - - // initiate page reload - reloadInProgress = true - const timeSinceUse = Date.now() - lastTimeUsed - // if web3 was recently used then delay the reloading of the page - if (timeSinceUse > 500) { - triggerReset() - } else { - setTimeout(triggerReset, 500) - } - }) -} - -// reload the page -function triggerReset () { - global.location.reload() -} diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index abe7ff8a2..6c380fd71 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -443,28 +443,24 @@ module.exports = class MetamaskController extends EventEmitter { * @returns {Object} vault */ async createNewVaultAndKeychain (password) { - const release = await this.createVaultMutex.acquire() - let vault - + const releaseLock = await this.createVaultMutex.acquire() try { + let vault const accounts = await this.keyringController.getAccounts() - if (accounts.length > 0) { vault = await this.keyringController.fullUpdate() - } else { vault = await this.keyringController.createNewVaultAndKeychain(password) const accounts = await this.keyringController.getAccounts() this.preferencesController.setAddresses(accounts) this.selectFirstIdentity() } - release() + releaseLock() + return vault } catch (err) { - release() + releaseLock() throw err } - - return vault } /** @@ -473,7 +469,7 @@ module.exports = class MetamaskController extends EventEmitter { * @param {} seed */ async createNewVaultAndRestore (password, seed) { - const release = await this.createVaultMutex.acquire() + const releaseLock = await this.createVaultMutex.acquire() try { // clear known identities this.preferencesController.setAddresses([]) @@ -483,10 +479,10 @@ module.exports = class MetamaskController extends EventEmitter { const accounts = await this.keyringController.getAccounts() this.preferencesController.setAddresses(accounts) this.selectFirstIdentity() - release() + releaseLock() return vault } catch (err) { - release() + releaseLock() throw err } } diff --git a/package-lock.json b/package-lock.json index 0fdbc02d6..4d2bee8bb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8267,7 +8267,7 @@ "dependencies": { "ethereumjs-abi": { "version": "git+https://github.com/ethereumjs/ethereumjs-abi.git#4ea2fdfed09e8f99117d9362d17c6b01b64a2bcf", - "from": "git+https://github.com/ethereumjs/ethereumjs-abi.git", + "from": "git+https://github.com/ethereumjs/ethereumjs-abi.git#4ea2fdfed09e8f99117d9362d17c6b01b64a2bcf", "requires": { "bn.js": "^4.10.0", "ethereumjs-util": "^5.0.0" @@ -8489,8 +8489,8 @@ } }, "eth-trezor-keyring": { - "version": "github:brunobar79/eth-trezor-keyring#c138d26c36a01f15be5e12a81e4fcbf56b044fa4", - "from": "github:brunobar79/eth-trezor-keyring#c138d26c36a01f15be5e12a81e4fcbf56b044fa4", + "version": "github:brunobar79/eth-trezor-keyring#34fec28417c9203dc6ad7d7c53fa46a7f422aa4e", + "from": "github:brunobar79/eth-trezor-keyring#34fec28417c9203dc6ad7d7c53fa46a7f422aa4e", "requires": { "eth-sig-util": "^1.4.2", "ethereumjs-tx": "^1.3.4", @@ -8531,6 +8531,16 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/events/-/events-2.1.0.tgz", "integrity": "sha512-3Zmiobend8P9DjmKAty0Era4jV8oJ0yGYe2nJJAxgymF9+N8F2m0hhZiMoWtcfepExzNKZumFU3ksdQbInGWCg==" + }, + "hdkey": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/hdkey/-/hdkey-0.8.0.tgz", + "integrity": "sha512-oYsdlK22eobT68N5faWI3776f6tOLyqxLLYwxMx+TP0rkWzuCs0oiOm2VbLWcxdpHFP4LtiRR8udaIX8VkEaZQ==", + "requires": { + "coinstring": "^2.0.0", + "safe-buffer": "^5.1.1", + "secp256k1": "^3.0.1" + } } } }, @@ -8554,6 +8564,20 @@ "web3-provider-engine": "^13.3.2" }, "dependencies": { + "ethereumjs-util": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz", + "integrity": "sha512-CJAKdI0wgMbQFLlLRtZKGcy/L6pzVRgelIZqRqNbuVFM3K9VEnyfbcvz0ncWMRNCe4kaHWjwRYQcYMucmwsnWA==", + "requires": { + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "ethjs-util": "^0.1.3", + "keccak": "^1.0.2", + "rlp": "^2.0.0", + "safe-buffer": "^5.1.1", + "secp256k1": "^3.0.1" + } + }, "ethereumjs-vm": { "version": "2.3.5", "resolved": "https://registry.npmjs.org/ethereumjs-vm/-/ethereumjs-vm-2.3.5.tgz", @@ -8698,6 +8722,22 @@ "ethereumjs-tx": "^1.2.2", "ethereumjs-util": "^5.0.0", "merkle-patricia-tree": "^2.1.2" + }, + "dependencies": { + "ethereumjs-util": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz", + "integrity": "sha512-CJAKdI0wgMbQFLlLRtZKGcy/L6pzVRgelIZqRqNbuVFM3K9VEnyfbcvz0ncWMRNCe4kaHWjwRYQcYMucmwsnWA==", + "requires": { + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "ethjs-util": "^0.1.3", + "keccak": "^1.0.2", + "rlp": "^2.0.0", + "safe-buffer": "^5.1.1", + "secp256k1": "^3.0.1" + } + } } }, "ethereumjs-tx": { @@ -8713,6 +8753,20 @@ "version": "0.0.18", "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.0.18.tgz", "integrity": "sha1-L9w1dvIykDNYl26znaeDIT/5Uj8=" + }, + "ethereumjs-util": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz", + "integrity": "sha512-CJAKdI0wgMbQFLlLRtZKGcy/L6pzVRgelIZqRqNbuVFM3K9VEnyfbcvz0ncWMRNCe4kaHWjwRYQcYMucmwsnWA==", + "requires": { + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "ethjs-util": "^0.1.3", + "keccak": "^1.0.2", + "rlp": "^2.0.0", + "safe-buffer": "^5.1.1", + "secp256k1": "^3.0.1" + } } } }, @@ -8784,15 +8838,6 @@ "rlp": "^2.0.0", "secp256k1": "^3.0.1" } - }, - "hdkey": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/hdkey/-/hdkey-0.7.1.tgz", - "integrity": "sha1-yu5L6BqneSHpCbjSKN0PKayu5jI=", - "requires": { - "coinstring": "^2.0.0", - "secp256k1": "^3.0.1" - } } } }, @@ -13623,12 +13668,11 @@ } }, "hdkey": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/hdkey/-/hdkey-0.8.0.tgz", - "integrity": "sha512-oYsdlK22eobT68N5faWI3776f6tOLyqxLLYwxMx+TP0rkWzuCs0oiOm2VbLWcxdpHFP4LtiRR8udaIX8VkEaZQ==", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/hdkey/-/hdkey-0.7.1.tgz", + "integrity": "sha1-yu5L6BqneSHpCbjSKN0PKayu5jI=", "requires": { "coinstring": "^2.0.0", - "safe-buffer": "^5.1.1", "secp256k1": "^3.0.1" } }, @@ -18288,6 +18332,20 @@ "version": "1.5.2", "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" + }, + "ethereumjs-util": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz", + "integrity": "sha512-CJAKdI0wgMbQFLlLRtZKGcy/L6pzVRgelIZqRqNbuVFM3K9VEnyfbcvz0ncWMRNCe4kaHWjwRYQcYMucmwsnWA==", + "requires": { + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "ethjs-util": "^0.1.3", + "keccak": "^1.0.2", + "rlp": "^2.0.0", + "safe-buffer": "^5.1.1", + "secp256k1": "^3.0.1" + } } } }, @@ -31338,7 +31396,7 @@ "dependencies": { "bignumber.js": { "version": "git+https://github.com/frozeman/bignumber.js-nolookahead.git#57692b3ecfc98bbdd6b3a516cb2353652ea49934", - "from": "git+https://github.com/frozeman/bignumber.js-nolookahead.git" + "from": "git+https://github.com/frozeman/bignumber.js-nolookahead.git#57692b3ecfc98bbdd6b3a516cb2353652ea49934" } } }, diff --git a/package.json b/package.json index 198f45cf1..ce28d484a 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ "dist": "gulp dist", "doc": "jsdoc -c development/tools/.jsdoc.json", "test": "npm run test:unit && npm run test:integration && npm run lint", + "watch:test:unit": "nodemon --exec \"npm run test:unit\" ./test ./app ./ui", "test:unit": "cross-env METAMASK_ENV=test mocha --exit --require test/setup.js --recursive \"test/unit/**/*.js\" \"ui/app/**/*.test.js\" && dot-only-hunter", "test:single": "cross-env METAMASK_ENV=test mocha --require test/helper.js", "test:integration": "npm run test:integration:build && npm run test:flat && npm run test:mascara", diff --git a/test/e2e/func.js b/test/e2e/func.js index 9f06e7f37..7b1730959 100644 --- a/test/e2e/func.js +++ b/test/e2e/func.js @@ -21,7 +21,7 @@ function delay (time) { } function buildChromeWebDriver (extPath) { - const tmpProfile = path.join(os.tmpdir(), fs.mkdtempSync('mm-chrome-profile')); + const tmpProfile = fs.mkdtempSync(path.join(os.tmpdir(), 'mm-chrome-profile')) return new webdriver.Builder() .withCapabilities({ chromeOptions: { diff --git a/ui/app/components/pending-tx/confirm-send-ether.js b/ui/app/components/pending-tx/confirm-send-ether.js index 97d0318ea..bbf5683f0 100644 --- a/ui/app/components/pending-tx/confirm-send-ether.js +++ b/ui/app/components/pending-tx/confirm-send-ether.js @@ -647,7 +647,7 @@ ConfirmSendEther.prototype.gatherTxMeta = function () { const state = this.state const txData = clone(state.txData) || clone(props.txData) - const { gasPrice: sendGasPrice, gas: sendGasLimit } = props.send + const { gasPrice: sendGasPrice, gasLimit: sendGasLimit } = props.send const { lastGasPrice, txParams: { diff --git a/ui/app/components/pending-tx/confirm-send-token.js b/ui/app/components/pending-tx/confirm-send-token.js index 1802d3143..ee066b8f4 100644 --- a/ui/app/components/pending-tx/confirm-send-token.js +++ b/ui/app/components/pending-tx/confirm-send-token.js @@ -651,7 +651,7 @@ ConfirmSendToken.prototype.gatherTxMeta = function () { const state = this.state const txData = clone(state.txData) || clone(props.txData) - const { gasPrice: sendGasPrice, gas: sendGasLimit } = props.send + const { gasPrice: sendGasPrice, gasLimit: sendGasLimit } = props.send const { lastGasPrice, txParams: { |