From 222e62d7f10ffe22dd606aea9c15e1547986c4ab Mon Sep 17 00:00:00 2001 From: Howard Braham Date: Mon, 17 Sep 2018 20:04:10 -0700 Subject: Bug Fix: #1789 and #4525 eth.getCode() with no contract --- CHANGELOG.md | 1 + app/_locales/en/messages.json | 3 +++ .../controllers/transactions/tx-gas-utils.js | 23 +++++++++++++++------- old-ui/app/components/pending-tx.js | 2 +- .../confirm-transaction-base.component.js | 2 +- ui/app/components/send/send.utils.js | 2 +- ui/app/constants/error-keys.js | 1 + ui/app/helpers/transactions.util.js | 2 +- 8 files changed, 25 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aef455127..6adb6f64b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ - Update transaction statuses when switching networks. - [#5470](https://github.com/MetaMask/metamask-extension/pull/5470) 100% coverage in French locale, fixed the procedure to verify proposed locale. +- [#5283](https://github.com/MetaMask/metamask-extension/pull/5283): Fix bug when eth.getCode() called with no contract ## 4.12.0 Thursday September 27 2018 diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index 66f378ab8..94716a7ad 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -1154,6 +1154,9 @@ "transactionError": { "message": "Transaction Error. Exception thrown in contract code." }, + "transactionErrorNoContract": { + "message": "Trying to call a contract function at an address that is not a contract address." + }, "transactionMemo": { "message": "Transaction memo (optional)" }, diff --git a/app/scripts/controllers/transactions/tx-gas-utils.js b/app/scripts/controllers/transactions/tx-gas-utils.js index 3dd45507f..5ec728085 100644 --- a/app/scripts/controllers/transactions/tx-gas-utils.js +++ b/app/scripts/controllers/transactions/tx-gas-utils.js @@ -7,6 +7,8 @@ const { const { addHexPrefix } = require('ethereumjs-util') const SIMPLE_GAS_COST = '0x5208' // Hex for 21000, cost of a simple send. +import { TRANSACTION_NO_CONTRACT_ERROR_KEY } from '../../../../ui/app/constants/error-keys' + /** tx-gas-utils are gas utility methods for Transaction manager its passed ethquery @@ -32,6 +34,7 @@ class TxGasUtil { } catch (err) { txMeta.simulationFails = { reason: err.message, + errorKey: err.errorKey, } return txMeta } @@ -56,16 +59,22 @@ class TxGasUtil { return txParams.gas } - // if recipient has no code, gas is 21k max: const recipient = txParams.to const hasRecipient = Boolean(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 - return SIMPLE_GAS_COST + if (hasRecipient) { + let code = await this.query.getCode(recipient) + + // If there's data in the params, but there's no code, it's not a valid contract + // For no code, Infura will return '0x', and Ganache will return '0x0' + if (txParams.data && (!code || code === '0x' || code === '0x0')) { + throw {errorKey: TRANSACTION_NO_CONTRACT_ERROR_KEY} + } + else if (!code) { + txParams.gas = SIMPLE_GAS_COST // For a standard ETH send, gas is 21k max + txMeta.simpleSend = true // Prevents buffer addition + return SIMPLE_GAS_COST + } } // if not, fall back to block gasLimit diff --git a/old-ui/app/components/pending-tx.js b/old-ui/app/components/pending-tx.js index c8132539c..7d8c94699 100644 --- a/old-ui/app/components/pending-tx.js +++ b/old-ui/app/components/pending-tx.js @@ -489,7 +489,7 @@ PendingTx.prototype.verifyGasParams = function () { } PendingTx.prototype._notZeroOrEmptyString = function (obj) { - return obj !== '' && obj !== '0x0' + return obj !== '' && obj !== '0x0' && obj !== '0x' // The '0x' case might not ever happen, but it seems safest to protect against it } PendingTx.prototype.bnMultiplyByFraction = function (targetBN, numerator, denominator) { diff --git a/ui/app/components/pages/confirm-transaction-base/confirm-transaction-base.component.js b/ui/app/components/pages/confirm-transaction-base/confirm-transaction-base.component.js index 707dad62d..9e6341722 100644 --- a/ui/app/components/pages/confirm-transaction-base/confirm-transaction-base.component.js +++ b/ui/app/components/pages/confirm-transaction-base/confirm-transaction-base.component.js @@ -131,7 +131,7 @@ export default class ConfirmTransactionBase extends Component { if (simulationFails) { return { valid: true, - errorKey: TRANSACTION_ERROR_KEY, + errorKey: simulationFails.errorKey ? simulationFails.errorKey : TRANSACTION_ERROR_KEY, } } diff --git a/ui/app/components/send/send.utils.js b/ui/app/components/send/send.utils.js index a18a9e4b3..05ba6b88f 100644 --- a/ui/app/components/send/send.utils.js +++ b/ui/app/components/send/send.utils.js @@ -215,7 +215,7 @@ async function estimateGas ({ // if recipient has no code, gas is 21k max: if (!selectedToken && !data) { const code = Boolean(to) && await global.eth.getCode(to) - if (!code || code === '0x') { + if (!code || code === '0x' || code === '0x0') { // Infura will return '0x', and Ganache will return '0x0' return SIMPLE_GAS_COST } } else if (selectedToken && !to) { diff --git a/ui/app/constants/error-keys.js b/ui/app/constants/error-keys.js index f70ed3b19..704064c96 100644 --- a/ui/app/constants/error-keys.js +++ b/ui/app/constants/error-keys.js @@ -1,3 +1,4 @@ export const INSUFFICIENT_FUNDS_ERROR_KEY = 'insufficientFunds' export const GAS_LIMIT_TOO_LOW_ERROR_KEY = 'gasLimitTooLow' export const TRANSACTION_ERROR_KEY = 'transactionError' +export const TRANSACTION_NO_CONTRACT_ERROR_KEY = 'transactionErrorNoContract' diff --git a/ui/app/helpers/transactions.util.js b/ui/app/helpers/transactions.util.js index f7d249e63..0eb7972d6 100644 --- a/ui/app/helpers/transactions.util.js +++ b/ui/app/helpers/transactions.util.js @@ -114,7 +114,7 @@ export function getLatestSubmittedTxWithNonce (transactions = [], nonce = '0x0') export async function isSmartContractAddress (address) { const code = await global.eth.getCode(address) - return code && code !== '0x' + return code && code !== '0x' && code !== '0x0'; // Infura will return '0x', and Ganache will return '0x0' } export function sumHexes (...args) { -- cgit From 4cc0b1ef01573e1541d18bdcd89650e1db32ae9a Mon Sep 17 00:00:00 2001 From: Howard Braham Date: Fri, 28 Sep 2018 11:01:34 -0700 Subject: ganache-core merged my PR, so I changed some comments to clarify that ganache-core v2.2.1 and below will return the non-standard '0x0' --- app/scripts/controllers/transactions/tx-gas-utils.js | 11 ++++++----- old-ui/app/components/pending-tx.js | 2 +- ui/app/components/send/send.utils.js | 2 +- ui/app/helpers/transactions.util.js | 2 +- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/app/scripts/controllers/transactions/tx-gas-utils.js b/app/scripts/controllers/transactions/tx-gas-utils.js index 5ec728085..ac57dfe1d 100644 --- a/app/scripts/controllers/transactions/tx-gas-utils.js +++ b/app/scripts/controllers/transactions/tx-gas-utils.js @@ -63,14 +63,15 @@ class TxGasUtil { const hasRecipient = Boolean(recipient) if (hasRecipient) { - let code = await this.query.getCode(recipient) + const code = await this.query.getCode(recipient) // If there's data in the params, but there's no code, it's not a valid contract - // For no code, Infura will return '0x', and Ganache will return '0x0' + // For no code, Infura will return '0x', and ganache-core v2.2.1 will return '0x0' if (txParams.data && (!code || code === '0x' || code === '0x0')) { - throw {errorKey: TRANSACTION_NO_CONTRACT_ERROR_KEY} - } - else if (!code) { + const err = new Error() + err.errorKey = TRANSACTION_NO_CONTRACT_ERROR_KEY + throw err + } else if (!code) { txParams.gas = SIMPLE_GAS_COST // For a standard ETH send, gas is 21k max txMeta.simpleSend = true // Prevents buffer addition return SIMPLE_GAS_COST diff --git a/old-ui/app/components/pending-tx.js b/old-ui/app/components/pending-tx.js index 7d8c94699..d8d2334a4 100644 --- a/old-ui/app/components/pending-tx.js +++ b/old-ui/app/components/pending-tx.js @@ -489,7 +489,7 @@ PendingTx.prototype.verifyGasParams = function () { } PendingTx.prototype._notZeroOrEmptyString = function (obj) { - return obj !== '' && obj !== '0x0' && obj !== '0x' // The '0x' case might not ever happen, but it seems safest to protect against it + return obj !== '' && obj !== '0x0' && obj !== '0x' // '0x' means null } PendingTx.prototype.bnMultiplyByFraction = function (targetBN, numerator, denominator) { diff --git a/ui/app/components/send/send.utils.js b/ui/app/components/send/send.utils.js index 05ba6b88f..af7b3823f 100644 --- a/ui/app/components/send/send.utils.js +++ b/ui/app/components/send/send.utils.js @@ -215,7 +215,7 @@ async function estimateGas ({ // if recipient has no code, gas is 21k max: if (!selectedToken && !data) { const code = Boolean(to) && await global.eth.getCode(to) - if (!code || code === '0x' || code === '0x0') { // Infura will return '0x', and Ganache will return '0x0' + if (!code || code === '0x' || code === '0x0') { // Infura will return '0x', and ganache-core v2.2.1 will return '0x0' return SIMPLE_GAS_COST } } else if (selectedToken && !to) { diff --git a/ui/app/helpers/transactions.util.js b/ui/app/helpers/transactions.util.js index 0eb7972d6..b2c617384 100644 --- a/ui/app/helpers/transactions.util.js +++ b/ui/app/helpers/transactions.util.js @@ -114,7 +114,7 @@ export function getLatestSubmittedTxWithNonce (transactions = [], nonce = '0x0') export async function isSmartContractAddress (address) { const code = await global.eth.getCode(address) - return code && code !== '0x' && code !== '0x0'; // Infura will return '0x', and Ganache will return '0x0' + return code && code !== '0x' && code !== '0x0' // Infura will return '0x', and ganache-core v2.2.1 will return '0x0' } export function sumHexes (...args) { -- cgit From 600f755dbf8d4cfdc152e3d521b537ee9a046a35 Mon Sep 17 00:00:00 2001 From: kumavis Date: Tue, 9 Oct 2018 23:17:05 -0400 Subject: tx-gas-utils - improve format + comments --- .../controllers/transactions/tx-gas-utils.js | 30 +++++++++++++--------- 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/app/scripts/controllers/transactions/tx-gas-utils.js b/app/scripts/controllers/transactions/tx-gas-utils.js index ac57dfe1d..436900715 100644 --- a/app/scripts/controllers/transactions/tx-gas-utils.js +++ b/app/scripts/controllers/transactions/tx-gas-utils.js @@ -62,28 +62,34 @@ class TxGasUtil { const recipient = txParams.to const hasRecipient = Boolean(recipient) + // see if we can set the gas based on the recipient if (hasRecipient) { const code = await this.query.getCode(recipient) - - // If there's data in the params, but there's no code, it's not a valid contract - // For no code, Infura will return '0x', and ganache-core v2.2.1 will return '0x0' - if (txParams.data && (!code || code === '0x' || code === '0x0')) { - const err = new Error() - err.errorKey = TRANSACTION_NO_CONTRACT_ERROR_KEY - throw err - } else if (!code) { - txParams.gas = SIMPLE_GAS_COST // For a standard ETH send, gas is 21k max - txMeta.simpleSend = true // Prevents buffer addition + // For an address with no code, geth will return '0x', and ganache-core v2.2.1 will return '0x0' + const codeIsEmpty = !code || code === '0x' || code === '0x0' + + if (codeIsEmpty) { + // if there's data in the params, but there's no contract code, it's not a valid transaction + if (txParams.data) { + const err = new Error() + err.errorKey = TRANSACTION_NO_CONTRACT_ERROR_KEY + throw err + } + + // This is a standard ether simple send, gas requirement is exactly 21k + txParams.gas = SIMPLE_GAS_COST + // prevents buffer addition + txMeta.simpleSend = true return SIMPLE_GAS_COST } } - // if not, fall back to block gasLimit + // fallback to block gasLimit const blockGasLimitBN = hexToBn(blockGasLimitHex) const saferGasLimitBN = BnMultiplyByFraction(blockGasLimitBN, 19, 20) txParams.gas = bnToHex(saferGasLimitBN) - // run tx + // estimate tx gas requirements return await this.query.estimateGas(txParams) } -- cgit From 26b30a031dacb23cc0a8ec742ece972acdd48594 Mon Sep 17 00:00:00 2001 From: kumavis Date: Fri, 19 Oct 2018 04:36:36 -0400 Subject: sentry - move isBrave decoration to insides of try-catch --- app/scripts/lib/setupRaven.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/scripts/lib/setupRaven.js b/app/scripts/lib/setupRaven.js index e6e511640..e1dc4bb8b 100644 --- a/app/scripts/lib/setupRaven.js +++ b/app/scripts/lib/setupRaven.js @@ -24,10 +24,11 @@ function setupRaven (opts) { const client = Raven.config(ravenTarget, { release, transport: function (opts) { - opts.data.extra.isBrave = isBrave const report = opts.data try { + // mark browser as brave or not + report.extra.isBrave = isBrave // handle error-like non-error exceptions rewriteErrorLikeExceptions(report) // simplify certain complex error messages (e.g. Ethjs) -- cgit From fb1b8d42ac09982b0844ebfd5d4e0169383c983f Mon Sep 17 00:00:00 2001 From: kumavis Date: Fri, 19 Oct 2018 04:40:23 -0400 Subject: sentry - update raven-js --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 09b66d261..7be0ccbce 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10390,7 +10390,7 @@ "dependencies": { "babelify": { "version": "7.3.0", - "resolved": "http://registry.npmjs.org/babelify/-/babelify-7.3.0.tgz", + "resolved": "https://registry.npmjs.org/babelify/-/babelify-7.3.0.tgz", "integrity": "sha1-qlau3nBn/XvVSWZu4W3ChQh+iOU=", "requires": { "babel-core": "^6.0.14", @@ -27091,9 +27091,9 @@ } }, "raven-js": { - "version": "3.24.2", - "resolved": "https://registry.npmjs.org/raven-js/-/raven-js-3.24.2.tgz", - "integrity": "sha512-Dy/FHDxuo5pXywVf8Nrs5utB2juMATpkxWGqHjVbpFD3m8CaWYLvkB5SEXjWFUZ5GvUsrBVVQ+Dfcp0x6Z7SOg==" + "version": "3.27.0", + "resolved": "https://registry.npmjs.org/raven-js/-/raven-js-3.27.0.tgz", + "integrity": "sha512-vChdOL+yzecfnGA+B5EhEZkJ3kY3KlMzxEhShKh6Vdtooyl0yZfYNFQfYzgMf2v4pyQa+OTZ5esTxxgOOZDHqw==" }, "raw-body": { "version": "2.3.2", diff --git a/package.json b/package.json index c994acc2f..6c2773623 100644 --- a/package.json +++ b/package.json @@ -186,7 +186,7 @@ "pumpify": "^1.3.4", "qrcode-npm": "0.0.3", "ramda": "^0.24.1", - "raven-js": "^3.24.2", + "raven-js": "^3.27.0", "react": "^15.6.2", "react-addons-css-transition-group": "^15.6.0", "react-dom": "^15.6.2", -- cgit From 65aa0a1d14b0b18d77b537b216d03ce5d9fca725 Mon Sep 17 00:00:00 2001 From: kumavis Date: Fri, 19 Oct 2018 04:51:03 -0400 Subject: blacklist - throw errors on request/parse failure --- app/scripts/controllers/blacklist.js | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/app/scripts/controllers/blacklist.js b/app/scripts/controllers/blacklist.js index 89c7cc888..5a5ec1c31 100644 --- a/app/scripts/controllers/blacklist.js +++ b/app/scripts/controllers/blacklist.js @@ -83,8 +83,23 @@ class BlacklistController { * */ async updatePhishingList () { - const response = await fetch('https://api.infura.io/v2/blacklist') - const phishing = await response.json() + // make request + let response + try { + response = await fetch('https://api.infura.io/v2/blacklist') + } catch (err) { + throw new Error(`BlacklistController - failed to fetch blacklist:\n${err.stack}`) + } + // parse response + let rawResponse + let phishing + try { + const rawResponse = await response.text() + phishing = JSON.parse(rawResponse) + } catch (err) { + throw new Error(`BlacklistController - failed to parse blacklist:\n${rawResponse}`) + } + // update current blacklist this.store.updateState({ phishing }) this._setupPhishingDetector(phishing) return phishing @@ -97,9 +112,9 @@ class BlacklistController { */ scheduleUpdates () { if (this._phishingUpdateIntervalRef) return - this.updatePhishingList().catch(log.warn) + this.updatePhishingList() this._phishingUpdateIntervalRef = setInterval(() => { - this.updatePhishingList().catch(log.warn) + this.updatePhishingList() }, POLLING_INTERVAL) } -- cgit From 2394881511928e414ca99cac2a46f30a7703ae91 Mon Sep 17 00:00:00 2001 From: kumavis Date: Fri, 19 Oct 2018 04:58:19 -0400 Subject: currency - throw errors on failure --- app/scripts/controllers/currency.js | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/app/scripts/controllers/currency.js b/app/scripts/controllers/currency.js index d5bc5fe2b..619c515fa 100644 --- a/app/scripts/controllers/currency.js +++ b/app/scripts/controllers/currency.js @@ -107,14 +107,28 @@ class CurrencyController { let currentCurrency try { currentCurrency = this.getCurrentCurrency() - const response = await fetch(`https://api.infura.io/v1/ticker/eth${currentCurrency.toLowerCase()}`) - const parsedResponse = await response.json() + let response + try { + response = await fetch(`https://api.infura.io/v1/ticker/eth${currentCurrency.toLowerCase()}`) + } catch (err) { + throw new Error(`CurrencyController - Failed to request currency from Infura:\n${err.stack}`) + } + let rawResponse + let parsedResponse + try { + rawResponse = await response.text() + parsedResponse = JSON.parse(rawResponse) + } catch () { + throw new Error(`CurrencyController - Failed to parse response "${rawResponse}"`) + } this.setConversionRate(Number(parsedResponse.bid)) this.setConversionDate(Number(parsedResponse.timestamp)) } catch (err) { - log.warn(`MetaMask - Failed to query currency conversion:`, currentCurrency, err) + // reset current conversion rate this.setConversionRate(0) this.setConversionDate('N/A') + // throw error + throw new Error(`CurrencyController - Failed to query rate for currency "${currentCurrency}":\n${err.stack}`) } } -- cgit From 0b12c4efb197dafce24eed8ae25fb93c0571bce0 Mon Sep 17 00:00:00 2001 From: kumavis Date: Fri, 19 Oct 2018 05:18:47 -0400 Subject: deps - bump eth-json-rpc-middleware for bugfix --- package-lock.json | 48 ++++++++++++++++++++++++++++++++++++++---------- package.json | 2 +- 2 files changed, 39 insertions(+), 11 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7be0ccbce..b754db4b8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9899,29 +9899,26 @@ } }, "eth-json-rpc-middleware": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/eth-json-rpc-middleware/-/eth-json-rpc-middleware-3.1.3.tgz", - "integrity": "sha512-glp/mCefhsqrgVOTTuYlHYiTL+9mMPfaZsuQv4vnRg3kqNigblS1nqARaMeVW9WOM8ssh9TqIFpuUr7JDgNmKQ==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/eth-json-rpc-middleware/-/eth-json-rpc-middleware-3.1.5.tgz", + "integrity": "sha512-68POkWUj0zYvxincExjRWXE49cxKDUSrSZn4oDVER5O5mWm0q/xcsLxlcurNFdHPov9APVqCXqzK6n2jUCDfRQ==", "dev": true, "requires": { - "async": "^2.5.0", "btoa": "^1.2.1", "clone": "^2.1.1", "eth-query": "^2.1.2", "eth-sig-util": "^1.4.2", - "eth-tx-summary": "^3.1.2", + "eth-tx-summary": "^3.2.3", "ethereumjs-block": "^1.6.0", "ethereumjs-tx": "^1.3.3", "ethereumjs-util": "^5.1.2", - "ethereumjs-vm": "^2.1.0", + "ethereumjs-vm": "^2.4.0", "fetch-ponyfill": "^4.0.0", - "json-rpc-engine": "^3.6.3", + "json-rpc-engine": "^3.8.0", "json-rpc-error": "^2.0.0", "json-stable-stringify": "^1.0.1", "pify": "^3.0.0", - "promise-to-callback": "^1.0.0", - "safe-event-emitter": "^1.0.1", - "tape": "^4.6.3" + "safe-event-emitter": "^1.0.1" }, "dependencies": { "eth-sig-util": { @@ -9957,6 +9954,31 @@ "safe-buffer": "^5.1.1", "secp256k1": "^3.0.1" } + }, + "ethereumjs-vm": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/ethereumjs-vm/-/ethereumjs-vm-2.4.0.tgz", + "integrity": "sha512-MJ4lCWa5c6LhahhhvoDKW+YGjK00ZQn0RHHLh4L+WaH1k6Qv7/q3uTluew6sJGNCZdlO0yYMDXYW9qyxLHKlgQ==", + "dev": true, + "requires": { + "async": "^2.1.2", + "async-eventemitter": "^0.2.2", + "ethereumjs-account": "^2.0.3", + "ethereumjs-block": "~1.7.0", + "ethereumjs-common": "~0.4.0", + "ethereumjs-util": "^5.2.0", + "fake-merkle-patricia-tree": "^1.0.1", + "functional-red-black-tree": "^1.0.1", + "merkle-patricia-tree": "^2.1.2", + "rustbn.js": "~0.2.0", + "safe-buffer": "^5.1.1" + } + }, + "rustbn.js": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/rustbn.js/-/rustbn.js-0.2.0.tgz", + "integrity": "sha512-4VlvkRUuCJvr2J6Y0ImW7NvTCriMi7ErOAqWk1y69vAdoNIzCF3yPmgeNzx+RQTLEDFq5sHfscn1MwHxP9hNfA==", + "dev": true } } }, @@ -10907,6 +10929,12 @@ } } }, + "ethereumjs-common": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/ethereumjs-common/-/ethereumjs-common-0.4.1.tgz", + "integrity": "sha512-ywYGsOeGCsMNWso5Y4GhjWI24FJv9FK7+VyVKiQgXg8ZRDPXJ7F/kJ1CnjtkjTvDF4e0yqU+FWswlqR3bmZQ9Q==", + "dev": true + }, "ethereumjs-tx": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/ethereumjs-tx/-/ethereumjs-tx-1.3.3.tgz", diff --git a/package.json b/package.json index 6c2773623..3b35c6cff 100644 --- a/package.json +++ b/package.json @@ -261,7 +261,7 @@ "eslint-plugin-json": "^1.2.0", "eslint-plugin-mocha": "^5.0.0", "eslint-plugin-react": "^7.4.0", - "eth-json-rpc-middleware": "^3.1.3", + "eth-json-rpc-middleware": "^3.1.5", "eth-keyring-controller": "^3.3.1", "fetch-mock": "^6.5.2", "file-loader": "^1.1.11", -- cgit From 3e3d4b9ddef032fe81419a516e65eb62ed664cb9 Mon Sep 17 00:00:00 2001 From: kumavis Date: Fri, 19 Oct 2018 05:30:21 -0400 Subject: sentry - failed txs - namespace txMeta for better readability --- app/scripts/lib/reportFailedTxToSentry.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/scripts/lib/reportFailedTxToSentry.js b/app/scripts/lib/reportFailedTxToSentry.js index df5661e59..fc6fbac24 100644 --- a/app/scripts/lib/reportFailedTxToSentry.js +++ b/app/scripts/lib/reportFailedTxToSentry.js @@ -11,6 +11,6 @@ function reportFailedTxToSentry ({ raven, txMeta }) { const errorMessage = 'Transaction Failed: ' + extractEthjsErrorMessage(txMeta.err.message) raven.captureMessage(errorMessage, { // "extra" key is required by Sentry - extra: txMeta, + extra: { txMeta }, }) } -- cgit From b85ae55cd59b4f8fe52ec75e1b7c6efe52a02e3f Mon Sep 17 00:00:00 2001 From: kumavis Date: Fri, 19 Oct 2018 06:42:53 -0400 Subject: fetch debugger - only append source stack if no stack is present --- app/scripts/lib/setupFetchDebugging.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/app/scripts/lib/setupFetchDebugging.js b/app/scripts/lib/setupFetchDebugging.js index dd87b65a6..c1ef22d21 100644 --- a/app/scripts/lib/setupFetchDebugging.js +++ b/app/scripts/lib/setupFetchDebugging.js @@ -2,7 +2,7 @@ module.exports = setupFetchDebugging // // This is a utility to help resolve cases where `window.fetch` throws a -// `TypeError: Failed to Fetch` without any stack or context for the request +// `TypeError: Failed to Fetch` without any stack or context for the request // https://github.com/getsentry/sentry-javascript/pull/1293 // @@ -17,9 +17,11 @@ function setupFetchDebugging() { try { return await originalFetch.call(window, ...args) } catch (err) { - console.warn('FetchDebugger - fetch encountered an Error', err) - console.warn('FetchDebugger - overriding stack to point of original call') - err.stack = initialStack + if (!err.stack) { + console.warn('FetchDebugger - fetch encountered an Error without a stack', err) + console.warn('FetchDebugger - overriding stack to point of original call') + err.stack = initialStack + } throw err } } -- cgit From a57d267dcbfa1a75a5ce3295e51825561e42c58d Mon Sep 17 00:00:00 2001 From: kumavis Date: Fri, 19 Oct 2018 07:08:04 -0400 Subject: lint fix --- app/scripts/controllers/blacklist.js | 1 - app/scripts/controllers/currency.js | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/app/scripts/controllers/blacklist.js b/app/scripts/controllers/blacklist.js index 5a5ec1c31..6ee89259c 100644 --- a/app/scripts/controllers/blacklist.js +++ b/app/scripts/controllers/blacklist.js @@ -1,7 +1,6 @@ const ObservableStore = require('obs-store') const extend = require('xtend') const PhishingDetector = require('eth-phishing-detect/src/detector') -const log = require('loglevel') // compute phishing lists const PHISHING_DETECTION_CONFIG = require('eth-phishing-detect/src/config.json') diff --git a/app/scripts/controllers/currency.js b/app/scripts/controllers/currency.js index 619c515fa..6cb39d39a 100644 --- a/app/scripts/controllers/currency.js +++ b/app/scripts/controllers/currency.js @@ -1,6 +1,5 @@ const ObservableStore = require('obs-store') const extend = require('xtend') -const log = require('loglevel') // every ten minutes const POLLING_INTERVAL = 600000 @@ -118,7 +117,7 @@ class CurrencyController { try { rawResponse = await response.text() parsedResponse = JSON.parse(rawResponse) - } catch () { + } catch (err) { throw new Error(`CurrencyController - Failed to parse response "${rawResponse}"`) } this.setConversionRate(Number(parsedResponse.bid)) -- cgit From 31175dcb24d836650469775a50289bfc131bcd18 Mon Sep 17 00:00:00 2001 From: kumavis Date: Fri, 19 Oct 2018 07:18:16 -0400 Subject: blacklist + currency - report error via log instead of throw --- app/scripts/controllers/blacklist.js | 7 +++++-- app/scripts/controllers/currency.js | 10 +++++++--- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/app/scripts/controllers/blacklist.js b/app/scripts/controllers/blacklist.js index 6ee89259c..e55b09d03 100644 --- a/app/scripts/controllers/blacklist.js +++ b/app/scripts/controllers/blacklist.js @@ -1,6 +1,7 @@ const ObservableStore = require('obs-store') const extend = require('xtend') const PhishingDetector = require('eth-phishing-detect/src/detector') +const log = require('loglevel') // compute phishing lists const PHISHING_DETECTION_CONFIG = require('eth-phishing-detect/src/config.json') @@ -87,7 +88,8 @@ class BlacklistController { try { response = await fetch('https://api.infura.io/v2/blacklist') } catch (err) { - throw new Error(`BlacklistController - failed to fetch blacklist:\n${err.stack}`) + log.error(new Error(`BlacklistController - failed to fetch blacklist:\n${err.stack}`)) + return } // parse response let rawResponse @@ -96,7 +98,8 @@ class BlacklistController { const rawResponse = await response.text() phishing = JSON.parse(rawResponse) } catch (err) { - throw new Error(`BlacklistController - failed to parse blacklist:\n${rawResponse}`) + log.error(new Error(`BlacklistController - failed to parse blacklist:\n${rawResponse}`)) + return } // update current blacklist this.store.updateState({ phishing }) diff --git a/app/scripts/controllers/currency.js b/app/scripts/controllers/currency.js index 6cb39d39a..6b82265f6 100644 --- a/app/scripts/controllers/currency.js +++ b/app/scripts/controllers/currency.js @@ -1,5 +1,6 @@ const ObservableStore = require('obs-store') const extend = require('xtend') +const log = require('loglevel') // every ten minutes const POLLING_INTERVAL = 600000 @@ -110,7 +111,8 @@ class CurrencyController { try { response = await fetch(`https://api.infura.io/v1/ticker/eth${currentCurrency.toLowerCase()}`) } catch (err) { - throw new Error(`CurrencyController - Failed to request currency from Infura:\n${err.stack}`) + log.error(new Error(`CurrencyController - Failed to request currency from Infura:\n${err.stack}`)) + return } let rawResponse let parsedResponse @@ -118,7 +120,8 @@ class CurrencyController { rawResponse = await response.text() parsedResponse = JSON.parse(rawResponse) } catch (err) { - throw new Error(`CurrencyController - Failed to parse response "${rawResponse}"`) + log.error(new Error(`CurrencyController - Failed to parse response "${rawResponse}"`)) + return } this.setConversionRate(Number(parsedResponse.bid)) this.setConversionDate(Number(parsedResponse.timestamp)) @@ -127,7 +130,8 @@ class CurrencyController { this.setConversionRate(0) this.setConversionDate('N/A') // throw error - throw new Error(`CurrencyController - Failed to query rate for currency "${currentCurrency}":\n${err.stack}`) + log.error(new Error(`CurrencyController - Failed to query rate for currency "${currentCurrency}":\n${err.stack}`)) + return } } -- cgit From 2f6530a4948743fe156dc3519f04bd44f7c6e2ae Mon Sep 17 00:00:00 2001 From: hackyminer Date: Sat, 20 Oct 2018 00:45:59 +0900 Subject: support both eth_chainId and net_version get the real chainId using eth_chainId and use net_version as a fallback --- app/scripts/controllers/network/network.js | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/app/scripts/controllers/network/network.js b/app/scripts/controllers/network/network.js index c1667d9a6..b386161da 100644 --- a/app/scripts/controllers/network/network.js +++ b/app/scripts/controllers/network/network.js @@ -86,10 +86,17 @@ module.exports = class NetworkController extends EventEmitter { return log.warn('NetworkController - lookupNetwork aborted due to missing provider') } const ethQuery = new EthQuery(this._provider) - ethQuery.sendAsync({ method: 'net_version' }, (err, network) => { - if (err) return this.setNetworkState('loading') - log.info('web3.getNetwork returned ' + network) - this.setNetworkState(network) + ethQuery.sendAsync({ method: 'eth_chainId' }, (err, chainId) => { + if (err) { + ethQuery.sendAsync({ method: 'net_version' }, (err, network) => { + if (err) return this.setNetworkState('loading') + log.info('web3.getNetwork returned net_version = ' + network) + this.setNetworkState(network) + }) + return + } + log.info('web3.getNetwork returned chainId = ' + parseInt(chainId)) + this.setNetworkState(parseInt(chainId)) }) } -- cgit From e3fda83ab209af7836ba93bfaba215c271d73e8a Mon Sep 17 00:00:00 2001 From: kumavis Date: Sat, 20 Oct 2018 02:22:50 -0400 Subject: sentry - replace raven-js with sentry/browser --- app/scripts/background.js | 12 ++-- app/scripts/lib/reportFailedTxToSentry.js | 4 +- app/scripts/lib/setupRaven.js | 101 ------------------------------ app/scripts/lib/setupSentry.js | 91 +++++++++++++++++++++++++++ app/scripts/ui.js | 4 +- package-lock.json | 57 +++++++++++++++-- package.json | 2 +- 7 files changed, 154 insertions(+), 117 deletions(-) delete mode 100644 app/scripts/lib/setupRaven.js create mode 100644 app/scripts/lib/setupSentry.js diff --git a/app/scripts/background.js b/app/scripts/background.js index 509a0001d..2455608aa 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -23,7 +23,7 @@ const createStreamSink = require('./lib/createStreamSink') const NotificationManager = require('./lib/notification-manager.js') const MetamaskController = require('./metamask-controller') const rawFirstTimeState = require('./first-time-state') -const setupRaven = require('./lib/setupRaven') +const setupSentry = require('./lib/setupSentry') const reportFailedTxToSentry = require('./lib/reportFailedTxToSentry') const setupMetamaskMeshMetrics = require('./lib/setupMetamaskMeshMetrics') const EdgeEncryptor = require('./edge-encryptor') @@ -50,7 +50,7 @@ global.METAMASK_NOTIFIER = notificationManager // setup sentry error reporting const release = platform.getVersion() -const raven = setupRaven({ release }) +const sentry = setupSentry({ release }) // browser check if it is Edge - https://stackoverflow.com/questions/9847580/how-to-detect-safari-chrome-ie-firefox-and-opera-browser // Internet Explorer 6-11 @@ -197,14 +197,14 @@ async function loadStateFromPersistence () { // 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', { + sentry.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') + sentry.captureMessage('MetaMask - Empty vault found - unable to recover') } } @@ -212,7 +212,7 @@ async function loadStateFromPersistence () { migrator.on('error', (err) => { // get vault structure without secrets const vaultStructure = getObjStructure(versionedData) - raven.captureException(err, { + sentry.captureException(err, { // "extra" key is required by Sentry extra: { vaultStructure }, }) @@ -279,7 +279,7 @@ function setupController (initState, initLangCode) { if (status !== 'failed') return const txMeta = controller.txController.txStateManager.getTx(txId) try { - reportFailedTxToSentry({ raven, txMeta }) + reportFailedTxToSentry({ sentry, txMeta }) } catch (e) { console.error(e) } diff --git a/app/scripts/lib/reportFailedTxToSentry.js b/app/scripts/lib/reportFailedTxToSentry.js index fc6fbac24..de4d57145 100644 --- a/app/scripts/lib/reportFailedTxToSentry.js +++ b/app/scripts/lib/reportFailedTxToSentry.js @@ -7,9 +7,9 @@ module.exports = reportFailedTxToSentry // for sending to sentry // -function reportFailedTxToSentry ({ raven, txMeta }) { +function reportFailedTxToSentry ({ sentry, txMeta }) { const errorMessage = 'Transaction Failed: ' + extractEthjsErrorMessage(txMeta.err.message) - raven.captureMessage(errorMessage, { + sentry.captureMessage(errorMessage, { // "extra" key is required by Sentry extra: { txMeta }, }) diff --git a/app/scripts/lib/setupRaven.js b/app/scripts/lib/setupRaven.js deleted file mode 100644 index e1dc4bb8b..000000000 --- a/app/scripts/lib/setupRaven.js +++ /dev/null @@ -1,101 +0,0 @@ -const Raven = require('raven-js') -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' - -module.exports = setupRaven - -// Setup raven / sentry remote error reporting -function setupRaven (opts) { - const { release } = opts - let ravenTarget - // detect brave - const isBrave = Boolean(window.chrome.ipcRenderer) - - if (METAMASK_DEBUG) { - console.log('Setting up Sentry Remote Error Reporting: DEV') - ravenTarget = DEV - } else { - console.log('Setting up Sentry Remote Error Reporting: PROD') - ravenTarget = PROD - } - - const client = Raven.config(ravenTarget, { - release, - transport: function (opts) { - const report = opts.data - - try { - // mark browser as brave or not - report.extra.isBrave = isBrave - // handle error-like non-error exceptions - rewriteErrorLikeExceptions(report) - // simplify certain complex error messages (e.g. Ethjs) - simplifyErrorMessages(report) - // modify report urls - rewriteReportUrls(report) - } catch (err) { - console.warn(err) - } - // make request normally - client._makeRequest(opts) - }, - }) - client.install() - - return Raven -} - -function rewriteErrorLikeExceptions (report) { - // handle errors that lost their error-ness in serialization (e.g. dnode) - rewriteErrorMessages(report, (errorMessage) => { - if (!errorMessage.includes('Non-Error exception captured with keys:')) return errorMessage - if (!(report.extra && report.extra.__serialized__ && report.extra.__serialized__.message)) return errorMessage - return `Non-Error Exception: ${report.extra.__serialized__.message}` - }) -} - -function simplifyErrorMessages (report) { - rewriteErrorMessages(report, (errorMessage) => { - // simplify ethjs error messages - errorMessage = extractEthjsErrorMessage(errorMessage) - // simplify 'Transaction Failed: known transaction' - if (errorMessage.indexOf('Transaction Failed: known transaction') === 0) { - // cut the hash from the error message - errorMessage = 'Transaction Failed: known transaction' - } - return errorMessage - }) -} - -function rewriteErrorMessages (report, rewriteFn) { - // rewrite top level message - if (typeof report.message === 'string') report.message = rewriteFn(report.message) - // rewrite each exception message - if (report.exception && report.exception.values) { - report.exception.values.forEach(item => { - if (typeof item.value === 'string') item.value = rewriteFn(item.value) - }) - } -} - -function rewriteReportUrls (report) { - // update request url - report.request.url = toMetamaskUrl(report.request.url) - // update exception stack trace - if (report.exception && report.exception.values) { - report.exception.values.forEach(item => { - item.stacktrace.frames.forEach(frame => { - frame.filename = toMetamaskUrl(frame.filename) - }) - }) - } -} - -function toMetamaskUrl (origUrl) { - const filePath = origUrl.split(location.origin)[1] - if (!filePath) return origUrl - const metamaskUrl = `metamask${filePath}` - return metamaskUrl -} diff --git a/app/scripts/lib/setupSentry.js b/app/scripts/lib/setupSentry.js new file mode 100644 index 000000000..aa8d72194 --- /dev/null +++ b/app/scripts/lib/setupSentry.js @@ -0,0 +1,91 @@ +const Sentry = require('@sentry/browser') +const METAMASK_DEBUG = process.env.METAMASK_DEBUG +const extractEthjsErrorMessage = require('./extractEthjsErrorMessage') +const SENTRY_DSN_PROD = 'https://3567c198f8a8412082d32655da2961d0@sentry.io/273505' +const SENTRY_DSN_DEV = 'https://f59f3dd640d2429d9d0e2445a87ea8e1@sentry.io/273496' + +module.exports = setupSentry + +// Setup sentry remote error reporting +function setupSentry (opts) { + const { release } = opts + let sentryTarget + // detect brave + const isBrave = Boolean(window.chrome.ipcRenderer) + + if (METAMASK_DEBUG) { + console.log('Setting up Sentry Remote Error Reporting: SENTRY_DSN_DEV') + sentryTarget = SENTRY_DSN_DEV + } else { + console.log('Setting up Sentry Remote Error Reporting: SENTRY_DSN_PROD') + sentryTarget = SENTRY_DSN_PROD + } + + Sentry.init({ + dsn: sentryTarget, + debug: METAMASK_DEBUG, + release, + beforeSend: (report) => rewriteReport(report), + }) + + Sentry.configureScope(scope => { + scope.setExtra('isBrave', isBrave) + }) + + function rewriteReport(report) { + try { + // simplify certain complex error messages (e.g. Ethjs) + simplifyErrorMessages(report) + // modify report urls + rewriteReportUrls(report) + } catch (err) { + console.warn(err) + } + } + + return Sentry +} + +function simplifyErrorMessages (report) { + rewriteErrorMessages(report, (errorMessage) => { + // simplify ethjs error messages + errorMessage = extractEthjsErrorMessage(errorMessage) + // simplify 'Transaction Failed: known transaction' + if (errorMessage.indexOf('Transaction Failed: known transaction') === 0) { + // cut the hash from the error message + errorMessage = 'Transaction Failed: known transaction' + } + return errorMessage + }) +} + +function rewriteErrorMessages (report, rewriteFn) { + // rewrite top level message + if (typeof report.message === 'string') report.message = rewriteFn(report.message) + // rewrite each exception message + if (report.exception && report.exception.values) { + report.exception.values.forEach(item => { + if (typeof item.value === 'string') item.value = rewriteFn(item.value) + }) + } +} + +function rewriteReportUrls (report) { + // update request url + report.request.url = toMetamaskUrl(report.request.url) + // update exception stack trace + if (report.exception && report.exception.values) { + report.exception.values.forEach(item => { + item.stacktrace.frames.forEach(frame => { + frame.filename = toMetamaskUrl(frame.filename) + }) + }) + } +} + +function toMetamaskUrl (origUrl) { + const filePath = origUrl.split(location.origin)[1] + if (!filePath) return origUrl + const metamaskUrl = `metamask${filePath}` + return metamaskUrl +} diff --git a/app/scripts/ui.js b/app/scripts/ui.js index 98a036338..8893ceaad 100644 --- a/app/scripts/ui.js +++ b/app/scripts/ui.js @@ -9,7 +9,7 @@ const extension = require('extensionizer') const ExtensionPlatform = require('./platforms/extension') const NotificationManager = require('./lib/notification-manager') const notificationManager = new NotificationManager() -const setupRaven = require('./lib/setupRaven') +const setupSentry = require('./lib/setupSentry') const log = require('loglevel') start().catch(log.error) @@ -21,7 +21,7 @@ async function start () { // setup sentry error reporting const release = global.platform.getVersion() - setupRaven({ release }) + setupSentry({ release }) // inject css // const css = MetaMaskUiCss() diff --git a/package-lock.json b/package-lock.json index b754db4b8..dc63d8b91 100644 --- a/package-lock.json +++ b/package-lock.json @@ -489,6 +489,16 @@ } } }, + "@sentry/browser": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-4.1.1.tgz", + "integrity": "sha512-rmkGlTh0AL3Jf0DvF3BluChIyzPkkYpNgIwEHjxTUiLp6BQdgwakZuzBqSPJrEs+jMsKMoesOuJ/fAAG0K7+Ew==", + "requires": { + "@sentry/core": "4.1.1", + "@sentry/types": "4.1.0", + "@sentry/utils": "4.1.1" + } + }, "@sentry/cli": { "version": "1.30.3", "resolved": "https://registry.npmjs.org/@sentry/cli/-/cli-1.30.3.tgz", @@ -531,6 +541,48 @@ } } }, + "@sentry/core": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-4.1.1.tgz", + "integrity": "sha512-QJExTxZ1ZA5P/To5gOwd3sowukXW0N/Q9nfu8biRDNa+YURn6ElLjO0fD6eIBqX1f3npo/kTiWZwFBc7LXEzSg==", + "requires": { + "@sentry/hub": "4.1.1", + "@sentry/minimal": "4.1.1", + "@sentry/types": "4.1.0", + "@sentry/utils": "4.1.1" + } + }, + "@sentry/hub": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-4.1.1.tgz", + "integrity": "sha512-VmcZOgcbFjJzK1oQNwcFP/wgfoWQr24dFv1C0uwdXldNXx3mwyUVkomvklBHz90HwiahsI/gCc+ZmbC3ECQk2Q==", + "requires": { + "@sentry/types": "4.1.0", + "@sentry/utils": "4.1.1" + } + }, + "@sentry/minimal": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-4.1.1.tgz", + "integrity": "sha512-xRKWA46OGnZinJyTljDUel53emPP9mb/XNi/kF6SBaVDOUXl7HAB8kP7Bn7eLBwOanxN8PbYoAzh/lIQXWTmDg==", + "requires": { + "@sentry/hub": "4.1.1", + "@sentry/types": "4.1.0" + } + }, + "@sentry/types": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@sentry/types/-/types-4.1.0.tgz", + "integrity": "sha512-KY7B9wYs1NACHlYzG4OuP6k4uQJkyDPJppftjj3NJYShfwdDTO1I2Swkhhb5dJMEMMMpBJGxXmiqZ2mX5ErISQ==" + }, + "@sentry/utils": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-4.1.1.tgz", + "integrity": "sha512-XMvGqAWATBrRkOF0lkt0Ij8of2mRmp4WeFTUAgiKzCekxfUBLBaTb4wTaFXz1cnnnjVTwcAq72qBRMhHwQ0IIg==", + "requires": { + "@sentry/types": "4.1.0" + } + }, "@sinonjs/formatio": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-2.0.0.tgz", @@ -27118,11 +27170,6 @@ "eve-raphael": "0.5.0" } }, - "raven-js": { - "version": "3.27.0", - "resolved": "https://registry.npmjs.org/raven-js/-/raven-js-3.27.0.tgz", - "integrity": "sha512-vChdOL+yzecfnGA+B5EhEZkJ3kY3KlMzxEhShKh6Vdtooyl0yZfYNFQfYzgMf2v4pyQa+OTZ5esTxxgOOZDHqw==" - }, "raw-body": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", diff --git a/package.json b/package.json index 3b35c6cff..ebac62d7f 100644 --- a/package.json +++ b/package.json @@ -82,6 +82,7 @@ }, "dependencies": { "@material-ui/core": "1.0.0", + "@sentry/browser": "^4.1.1", "@zxing/library": "^0.8.0", "abi-decoder": "^1.0.9", "asmcrypto.js": "0.22.0", @@ -186,7 +187,6 @@ "pumpify": "^1.3.4", "qrcode-npm": "0.0.3", "ramda": "^0.24.1", - "raven-js": "^3.27.0", "react": "^15.6.2", "react-addons-css-transition-group": "^15.6.0", "react-dom": "^15.6.2", -- cgit From 73ec4e66cb7a476d01371a61692b0d8d9224da04 Mon Sep 17 00:00:00 2001 From: kumavis Date: Sat, 20 Oct 2018 03:14:59 -0400 Subject: sentry - include app state in ui errors --- app/scripts/lib/setupSentry.js | 8 +++++++- app/scripts/ui.js | 12 +++++++++++- package-lock.json | 6 +++--- package.json | 2 +- ui/app/reducers.js | 26 ++++++++++++++++---------- 5 files changed, 38 insertions(+), 16 deletions(-) diff --git a/app/scripts/lib/setupSentry.js b/app/scripts/lib/setupSentry.js index aa8d72194..69042bc19 100644 --- a/app/scripts/lib/setupSentry.js +++ b/app/scripts/lib/setupSentry.js @@ -8,7 +8,7 @@ module.exports = setupSentry // Setup sentry remote error reporting function setupSentry (opts) { - const { release } = opts + const { release, getState } = opts let sentryTarget // detect brave const isBrave = Boolean(window.chrome.ipcRenderer) @@ -38,9 +38,15 @@ function setupSentry (opts) { simplifyErrorMessages(report) // modify report urls rewriteReportUrls(report) + // append app state + if (getState) { + const appState = getState() + report.extra.appState = appState + } } catch (err) { console.warn(err) } + return report } return Sentry diff --git a/app/scripts/ui.js b/app/scripts/ui.js index 8893ceaad..c4f6615db 100644 --- a/app/scripts/ui.js +++ b/app/scripts/ui.js @@ -21,7 +21,17 @@ async function start () { // setup sentry error reporting const release = global.platform.getVersion() - setupSentry({ release }) + setupSentry({ release, getState }) + // provide app state to append to error logs + function getState() { + // get app state + const state = window.getCleanAppState() + // remove unnecessary data + delete state.localeMessages + delete state.metamask.recentBlocks + // return state to be added to request + return state + } // inject css // const css = MetaMaskUiCss() diff --git a/package-lock.json b/package-lock.json index dc63d8b91..04c2b7014 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6183,9 +6183,9 @@ } }, "clone": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.1.tgz", - "integrity": "sha1-0hfR6WERjjrJpLi7oyhVU79kfNs=" + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=" }, "clone-buffer": { "version": "1.0.0", diff --git a/package.json b/package.json index ebac62d7f..9f56e726a 100644 --- a/package.json +++ b/package.json @@ -98,7 +98,7 @@ "browserify-derequire": "^0.9.4", "browserify-unibabel": "^3.0.0", "classnames": "^2.2.5", - "clone": "^2.1.1", + "clone": "^2.1.2", "copy-to-clipboard": "^3.0.8", "css-loader": "^0.28.11", "currency-formatter": "^1.4.2", diff --git a/ui/app/reducers.js b/ui/app/reducers.js index 80e76d570..e1a982f93 100644 --- a/ui/app/reducers.js +++ b/ui/app/reducers.js @@ -1,3 +1,4 @@ +const clone = require('clone') const extend = require('xtend') const copyToClipboard = require('copy-to-clipboard') @@ -52,19 +53,24 @@ function rootReducer (state, action) { return state } +window.getCleanAppState = function () { + const state = clone(window.METAMASK_CACHED_LOG_STATE) + // append additional information + state.version = global.platform.getVersion() + state.browser = window.navigator.userAgent + // ensure seedWords are not included + if (state.metamask) delete state.metamask.seedWords + if (state.appState.currentView) delete state.appState.currentView.seedWords + return state +} + window.logStateString = function (cb) { - const state = window.METAMASK_CACHED_LOG_STATE - const version = global.platform.getVersion() - const browser = window.navigator.userAgent - return global.platform.getPlatformInfo((err, platform) => { - if (err) { - return cb(err) - } - state.version = version + const state = window.getCleanAppState() + global.platform.getPlatformInfo((err, platform) => { + if (err) return cb(err) state.platform = platform - state.browser = browser const stateString = JSON.stringify(state, removeSeedWords, 2) - return cb(null, stateString) + cb(null, stateString) }) } -- cgit From fda101912bbb99f7f1adbac9856d34105390c408 Mon Sep 17 00:00:00 2001 From: kumavis Date: Sun, 21 Oct 2018 00:52:41 -0400 Subject: ui - use variable to clarify result of emptiness check --- old-ui/app/components/pending-tx.js | 6 ++++-- ui/app/components/send/send.utils.js | 4 +++- ui/app/helpers/transactions.util.js | 4 +++- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/old-ui/app/components/pending-tx.js b/old-ui/app/components/pending-tx.js index d8d2334a4..b02476f46 100644 --- a/old-ui/app/components/pending-tx.js +++ b/old-ui/app/components/pending-tx.js @@ -488,8 +488,10 @@ PendingTx.prototype.verifyGasParams = function () { ) } -PendingTx.prototype._notZeroOrEmptyString = function (obj) { - return obj !== '' && obj !== '0x0' && obj !== '0x' // '0x' means null +PendingTx.prototype._notZeroOrEmptyString = function (value) { + // Geth will return '0x', and ganache-core v2.2.1 will return '0x0' + const valueIsEmpty = !value || value === '0x' || value === '0x0' + return !valueIsEmpty } PendingTx.prototype.bnMultiplyByFraction = function (targetBN, numerator, denominator) { diff --git a/ui/app/components/send/send.utils.js b/ui/app/components/send/send.utils.js index af7b3823f..eb1667c63 100644 --- a/ui/app/components/send/send.utils.js +++ b/ui/app/components/send/send.utils.js @@ -215,7 +215,9 @@ async function estimateGas ({ // if recipient has no code, gas is 21k max: if (!selectedToken && !data) { const code = Boolean(to) && await global.eth.getCode(to) - if (!code || code === '0x' || code === '0x0') { // Infura will return '0x', and ganache-core v2.2.1 will return '0x0' + // Geth will return '0x', and ganache-core v2.2.1 will return '0x0' + const codeIsEmpty = !code || code === '0x' || code === '0x0' + if (codeIsEmpty) { return SIMPLE_GAS_COST } } else if (selectedToken && !to) { diff --git a/ui/app/helpers/transactions.util.js b/ui/app/helpers/transactions.util.js index 9be77e14f..cfe2c4229 100644 --- a/ui/app/helpers/transactions.util.js +++ b/ui/app/helpers/transactions.util.js @@ -114,7 +114,9 @@ export function getLatestSubmittedTxWithNonce (transactions = [], nonce = '0x0') export async function isSmartContractAddress (address) { const code = await global.eth.getCode(address) - return code && code !== '0x' && code !== '0x0' // Infura will return '0x', and ganache-core v2.2.1 will return '0x0' + // Geth will return '0x', and ganache-core v2.2.1 will return '0x0' + const codeIsEmpty = !code || code === '0x' || code === '0x0' + return !codeIsEmpty } export function sumHexes (...args) { -- cgit From 17a856cfd35a0e419524cf00e852be6c797b1e0b Mon Sep 17 00:00:00 2001 From: kumavis Date: Sun, 21 Oct 2018 00:57:45 -0400 Subject: send tx - validate - simplify error message for attempting to call function on non-contract address --- app/_locales/en/messages.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index 4cdf6b8dc..e2fb3fc13 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -1176,7 +1176,7 @@ "message": "Transaction Error. Exception thrown in contract code." }, "transactionErrorNoContract": { - "message": "Trying to call a contract function at an address that is not a contract address." + "message": "Trying to call a function on a non-contract address." }, "transactionMemo": { "message": "Transaction memo (optional)" -- cgit From 31e5cad1e34c1b07079c430bb1903f7914021111 Mon Sep 17 00:00:00 2001 From: kumavis Date: Sun, 21 Oct 2018 01:01:21 -0400 Subject: tx-gas-util - set error message when invalidating tx based on tx data but no contract code --- app/scripts/controllers/transactions/tx-gas-utils.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/app/scripts/controllers/transactions/tx-gas-utils.js b/app/scripts/controllers/transactions/tx-gas-utils.js index 436900715..def67c2c3 100644 --- a/app/scripts/controllers/transactions/tx-gas-utils.js +++ b/app/scripts/controllers/transactions/tx-gas-utils.js @@ -62,20 +62,21 @@ class TxGasUtil { const recipient = txParams.to const hasRecipient = Boolean(recipient) - // see if we can set the gas based on the recipient + // see if we can set the gas based on the recipient if (hasRecipient) { const code = await this.query.getCode(recipient) // For an address with no code, geth will return '0x', and ganache-core v2.2.1 will return '0x0' const codeIsEmpty = !code || code === '0x' || code === '0x0' - + if (codeIsEmpty) { // if there's data in the params, but there's no contract code, it's not a valid transaction if (txParams.data) { - const err = new Error() + const err = new Error('TxGasUtil - Trying to call a function on a non-contract address') + // set error key so ui can display localized error message err.errorKey = TRANSACTION_NO_CONTRACT_ERROR_KEY throw err } - + // This is a standard ether simple send, gas requirement is exactly 21k txParams.gas = SIMPLE_GAS_COST // prevents buffer addition -- cgit From 61c7bbb1c1f0c216d5f8cd0d0753c78bc635624e Mon Sep 17 00:00:00 2001 From: kumavis Date: Sun, 21 Oct 2018 01:20:08 -0400 Subject: network - improve logging and type conversion --- app/scripts/controllers/network/network.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/app/scripts/controllers/network/network.js b/app/scripts/controllers/network/network.js index b386161da..904c20cff 100644 --- a/app/scripts/controllers/network/network.js +++ b/app/scripts/controllers/network/network.js @@ -86,17 +86,19 @@ module.exports = class NetworkController extends EventEmitter { return log.warn('NetworkController - lookupNetwork aborted due to missing provider') } const ethQuery = new EthQuery(this._provider) - ethQuery.sendAsync({ method: 'eth_chainId' }, (err, chainId) => { + ethQuery.sendAsync({ method: 'eth_chainId' }, (err, chainIdHex) => { if (err) { + // if eth_chainId is not supported, fallback to net_verion ethQuery.sendAsync({ method: 'net_version' }, (err, network) => { if (err) return this.setNetworkState('loading') - log.info('web3.getNetwork returned net_version = ' + network) + log.info(`net_version returned ${network}`) this.setNetworkState(network) }) return } - log.info('web3.getNetwork returned chainId = ' + parseInt(chainId)) - this.setNetworkState(parseInt(chainId)) + const chainId = Number.parseInt(chainIdHex, 16) + log.info(`net_version returned ${chainId}`) + this.setNetworkState(chainId) }) } -- cgit From b62d07f3a5bdfde7e295f17b7f601c6f2d5314ef Mon Sep 17 00:00:00 2001 From: kumavis Date: Sun, 21 Oct 2018 04:32:07 -0400 Subject: Update network.js --- app/scripts/controllers/network/network.js | 1 + 1 file changed, 1 insertion(+) diff --git a/app/scripts/controllers/network/network.js b/app/scripts/controllers/network/network.js index 904c20cff..6a5369f06 100644 --- a/app/scripts/controllers/network/network.js +++ b/app/scripts/controllers/network/network.js @@ -86,6 +86,7 @@ module.exports = class NetworkController extends EventEmitter { return log.warn('NetworkController - lookupNetwork aborted due to missing provider') } const ethQuery = new EthQuery(this._provider) + // first attempt to perform lookup via eth_chainId ethQuery.sendAsync({ method: 'eth_chainId' }, (err, chainIdHex) => { if (err) { // if eth_chainId is not supported, fallback to net_verion -- cgit From baa3af46f375f46a3516ee7dec4e83795cbcfb66 Mon Sep 17 00:00:00 2001 From: brunobar79 Date: Sun, 21 Oct 2018 05:35:37 -0400 Subject: install truffle globally --- test/e2e/beta/run-drizzle.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/e2e/beta/run-drizzle.sh b/test/e2e/beta/run-drizzle.sh index 7bfffd7e6..bfb7e6fdb 100755 --- a/test/e2e/beta/run-drizzle.sh +++ b/test/e2e/beta/run-drizzle.sh @@ -11,7 +11,7 @@ sleep 5 cd test/e2e/beta/ rm -rf drizzle-test mkdir drizzle-test && cd drizzle-test -npm install truffle +sudo npm install -g truffle truffle unbox drizzle echo "Deploying contracts for Drizzle test..." truffle compile && truffle migrate -- cgit From 6d09f60bbfe5ee737ff7a138260cc33e3db5ca46 Mon Sep 17 00:00:00 2001 From: kumavis Date: Sun, 21 Oct 2018 05:48:15 -0400 Subject: ens-ipfs - refactor for readability (#5568) * ens-ipfs - refactor for readability * ens-ipfs - use official ipfs gateway for better performance * lint - remove unused code * ens-ipfs - support path and search * lint - gotta love that linter * ens-ipfs - improve loading page formatting * ens-ipfs - loading - redirect to 404 after 1 min timeout * ens-ipfs - destructure for cleaner code --- app/loading.html | 12 ++++- app/scripts/background.js | 10 ++-- app/scripts/lib/contracts/registrar.js | 1 - app/scripts/lib/contracts/resolver.js | 2 - app/scripts/lib/ens-ipfs/contracts/registrar.js | 1 + app/scripts/lib/ens-ipfs/contracts/resolver.js | 2 + app/scripts/lib/ens-ipfs/resolver.js | 54 +++++++++++++++++++ app/scripts/lib/ens-ipfs/setup.js | 63 ++++++++++++++++++++++ app/scripts/lib/ipfsContent.js | 46 ---------------- app/scripts/lib/resolver.js | 71 ------------------------- 10 files changed, 134 insertions(+), 128 deletions(-) delete mode 100644 app/scripts/lib/contracts/registrar.js delete mode 100644 app/scripts/lib/contracts/resolver.js create mode 100644 app/scripts/lib/ens-ipfs/contracts/registrar.js create mode 100644 app/scripts/lib/ens-ipfs/contracts/resolver.js create mode 100644 app/scripts/lib/ens-ipfs/resolver.js create mode 100644 app/scripts/lib/ens-ipfs/setup.js delete mode 100644 app/scripts/lib/ipfsContent.js delete mode 100644 app/scripts/lib/resolver.js diff --git a/app/loading.html b/app/loading.html index aef5d9607..71403a5ac 100644 --- a/app/loading.html +++ b/app/loading.html @@ -1,5 +1,9 @@ - + + + + + MetaMask Loading