aboutsummaryrefslogtreecommitdiffstats
path: root/app
diff options
context:
space:
mode:
authorfrankiebee <frankie.diamond@gmail.com>2017-07-12 03:18:44 +0800
committerfrankiebee <frankie.diamond@gmail.com>2017-07-12 03:18:44 +0800
commita670e54973ed1bae20455507a4b3c44e231ba822 (patch)
tree00300ea3362b7b48be26d6547f89ed4c5bfac597 /app
parentc121ac21ec3bed0381e36de7ead1b583a3da148c (diff)
parentf5de16c91174fbbf208e5aef8f542d3bbbb3cb93 (diff)
downloadtangerine-wallet-browser-a670e54973ed1bae20455507a4b3c44e231ba822.tar
tangerine-wallet-browser-a670e54973ed1bae20455507a4b3c44e231ba822.tar.gz
tangerine-wallet-browser-a670e54973ed1bae20455507a4b3c44e231ba822.tar.bz2
tangerine-wallet-browser-a670e54973ed1bae20455507a4b3c44e231ba822.tar.lz
tangerine-wallet-browser-a670e54973ed1bae20455507a4b3c44e231ba822.tar.xz
tangerine-wallet-browser-a670e54973ed1bae20455507a4b3c44e231ba822.tar.zst
tangerine-wallet-browser-a670e54973ed1bae20455507a4b3c44e231ba822.zip
Merge branch 'nonce-tracker' of https://github.com/MetaMask/metamask-plugin into nonce-tracker
Diffstat (limited to 'app')
-rw-r--r--app/manifest.json2
-rw-r--r--app/scripts/controllers/preferences.js29
-rw-r--r--app/scripts/controllers/transactions.js65
-rw-r--r--app/scripts/metamask-controller.js12
-rw-r--r--app/scripts/migrations/015.js38
-rw-r--r--app/scripts/migrations/index.js1
6 files changed, 121 insertions, 26 deletions
diff --git a/app/manifest.json b/app/manifest.json
index 7ae20158c..aafc33e66 100644
--- a/app/manifest.json
+++ b/app/manifest.json
@@ -1,7 +1,7 @@
{
"name": "MetaMask",
"short_name": "Metamask",
- "version": "3.7.8",
+ "version": "3.8.3",
"manifest_version": 2,
"author": "https://metamask.io",
"description": "Ethereum Browser Extension",
diff --git a/app/scripts/controllers/preferences.js b/app/scripts/controllers/preferences.js
index aa8e05fcc..e45224593 100644
--- a/app/scripts/controllers/preferences.js
+++ b/app/scripts/controllers/preferences.js
@@ -8,13 +8,11 @@ class PreferencesController {
const initState = extend({
frequentRpcList: [],
currentAccountTab: 'history',
+ tokens: [],
}, opts.initState)
this.store = new ObservableStore(initState)
}
-
- //
- // PUBLIC METHODS
- //
+// PUBLIC METHODS
setSelectedAddress (_address) {
return new Promise((resolve, reject) => {
@@ -28,6 +26,29 @@ class PreferencesController {
return this.store.getState().selectedAddress
}
+ addToken (rawAddress, symbol, decimals) {
+ const address = normalizeAddress(rawAddress)
+ const newEntry = { address, symbol, decimals }
+
+ const tokens = this.store.getState().tokens
+ const previousIndex = tokens.find((token, index) => {
+ return token.address === address
+ })
+
+ if (previousIndex) {
+ tokens[previousIndex] = newEntry
+ } else {
+ tokens.push(newEntry)
+ }
+
+ this.store.updateState({ tokens })
+ return Promise.resolve()
+ }
+
+ getTokens () {
+ return this.store.getState().tokens
+ }
+
updateFrequentRpcList (_url) {
return this.addToFrequentRpcList(_url)
.then((rpcList) => {
diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js
index 14b423d5d..fb0219fc3 100644
--- a/app/scripts/controllers/transactions.js
+++ b/app/scripts/controllers/transactions.js
@@ -8,8 +8,6 @@ const TxProviderUtil = require('../lib/tx-utils')
const createId = require('../lib/random-id')
const NonceTracker = require('../lib/nonce-tracker')
-const RETRY_LIMIT = 200
-
module.exports = class TransactionController extends EventEmitter {
constructor (opts) {
super()
@@ -36,7 +34,10 @@ module.exports = class TransactionController extends EventEmitter {
this.query = opts.ethQuery
this.txProviderUtils = new TxProviderUtil(this.query)
this.blockTracker.on('rawBlock', this.checkForTxInBlock.bind(this))
- this.blockTracker.on('latest', this.resubmitPendingTxs.bind(this))
+ // this is a little messy but until ethstore has been either
+ // removed or redone this is to guard against the race condition
+ // where ethStore hasent been populated by the results yet
+ this.blockTracker.once('latest', () => this.blockTracker.on('latest', this.resubmitPendingTxs.bind(this)))
this.blockTracker.on('sync', this.queryPendingTxs.bind(this))
this.signEthTx = opts.signTransaction
this.ethStore = opts.ethStore
@@ -162,13 +163,15 @@ module.exports = class TransactionController extends EventEmitter {
const txParams = txMeta.txParams
// ensure value
txParams.value = txParams.value || '0x0'
- this.query.gasPrice((err, gasPrice) => {
- if (err) return cb(err)
- // set gasPrice
- txParams.gasPrice = gasPrice
- // set gasLimit
- this.txProviderUtils.analyzeGasUsage(txMeta, cb)
- })
+ if (!txParams.gasPrice) {
+ this.query.gasPrice((err, gasPrice) => {
+ if (err) return cb(err)
+ // set gasPrice
+ txParams.gasPrice = gasPrice
+ })
+ }
+ // set gasLimit
+ this.txProviderUtils.analyzeGasUsage(txMeta, cb)
}
getUnapprovedTxList () {
@@ -429,10 +432,24 @@ module.exports = class TransactionController extends EventEmitter {
// only try resubmitting if their are transactions to resubmit
if (!pending.length) return
const resubmit = denodeify(this._resubmitTx.bind(this))
- Promise.all(pending.map(txMeta => resubmit(txMeta)))
+ pending.forEach((txMeta) => resubmit(txMeta)
.catch((reason) => {
- log.info('Problem resubmitting tx', reason)
- })
+ /*
+ Dont marked as failed if the error is a "known" transaction warning
+ "there is already a transaction with the same sender-nonce
+ but higher/same gas price"
+ */
+ const errorMessage = reason.message.toLowerCase()
+ const isKnownTx = (
+ // geth
+ errorMessage === 'replacement transaction underpriced'
+ || errorMessage.startsWith('known transaction')
+ // parity
+ || errorMessage === 'gas price too low to replace'
+ )
+ // ignore resubmit warnings, return early
+ if (!isKnownTx) this.setTxStatusFailed(txMeta.id, reason.message)
+ }))
}
_resubmitTx (txMeta, cb) {
@@ -443,15 +460,25 @@ module.exports = class TransactionController extends EventEmitter {
const gtBalance = Number.parseInt(txMeta.txParams.value) > Number.parseInt(balance)
if (!('retryCount' in txMeta)) txMeta.retryCount = 0
- // if the value of the transaction is greater then the balance
- // or the nonce of the transaction is lower then the accounts nonce
- // dont resubmit the tx
- if (gtBalance || txNonce < nonce) return cb()
+ // if the value of the transaction is greater then the balance, fail.
+ if (gtBalance) {
+ const message = 'Insufficient balance.'
+ this.setTxStatusFailed(txMeta.id, message)
+ cb()
+ return log.error(message)
+ }
+
+ // if the nonce of the transaction is lower then the accounts nonce, fail.
+ if (txNonce < nonce) {
+ const message = 'Invalid nonce.'
+ this.setTxStatusFailed(txMeta.id, message)
+ cb()
+ return log.error(message)
+ }
+
// Only auto-submit already-signed txs:
if (!('rawTx' in txMeta)) return cb()
- if (txMeta.retryCount > RETRY_LIMIT) return
-
// Increment a try counter.
txMeta.retryCount++
const rawTx = txMeta.rawTx
diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js
index be64a45c7..573594b39 100644
--- a/app/scripts/metamask-controller.js
+++ b/app/scripts/metamask-controller.js
@@ -184,7 +184,9 @@ module.exports = class MetamaskController extends EventEmitter {
eth_syncing: false,
web3_clientVersion: `MetaMask/v${version}`,
},
+ // rpc data source
rpcUrl: this.networkController.getCurrentRpcAddress(),
+ originHttpHeaderKey: 'X-Metamask-Origin',
// account mgmt
getAccounts: (cb) => {
const isUnlocked = this.keyringController.memStore.getState().isUnlocked
@@ -293,6 +295,7 @@ module.exports = class MetamaskController extends EventEmitter {
// PreferencesController
setSelectedAddress: nodeify(preferencesController.setSelectedAddress).bind(preferencesController),
+ addToken: nodeify(preferencesController.addToken).bind(preferencesController),
setCurrentAccountTab: nodeify(preferencesController.setCurrentAccountTab).bind(preferencesController),
setDefaultRpc: nodeify(this.setDefaultRpc).bind(this),
setCustomRpc: nodeify(this.setCustomRpc).bind(this),
@@ -355,8 +358,13 @@ module.exports = class MetamaskController extends EventEmitter {
}
setupProviderConnection (outStream, originDomain) {
- streamIntoProvider(outStream, this.provider, logger)
- function logger (err, request, response) {
+ streamIntoProvider(outStream, this.provider, onRequest, onResponse)
+ // append dapp origin domain to request
+ function onRequest (request) {
+ request.origin = originDomain
+ }
+ // log rpc activity
+ function onResponse (err, request, response) {
if (err) return console.error(err)
if (response.error) {
console.error('Error in RPC response:\n', response.error)
diff --git a/app/scripts/migrations/015.js b/app/scripts/migrations/015.js
new file mode 100644
index 000000000..4b839580b
--- /dev/null
+++ b/app/scripts/migrations/015.js
@@ -0,0 +1,38 @@
+const version = 15
+
+/*
+
+This migration sets transactions with the 'Gave up submitting tx.' err message
+to a 'failed' stated
+
+*/
+
+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) => {
+ 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/index.js b/app/scripts/migrations/index.js
index fb1ad7863..651ee6a9c 100644
--- a/app/scripts/migrations/index.js
+++ b/app/scripts/migrations/index.js
@@ -25,4 +25,5 @@ module.exports = [
require('./012'),
require('./013'),
require('./014'),
+ require('./015'),
]